[
  {
    "path": ".gitattributes",
    "content": "###############################################################################\n# Set default behavior to automatically normalize line endings.\n###############################################################################\n* text=auto\n\n###############################################################################\n# Set default behavior for command prompt diff.\n#\n# This is need for earlier builds of msysgit that does not have it on by\n# default for csharp files.\n# Note: This is only used by command line\n###############################################################################\n#*.cs     diff=csharp\n\n###############################################################################\n# Set the merge driver for project and solution files\n#\n# Merging from the command prompt will add diff markers to the files if there\n# are conflicts (Merging from VS is not affected by the settings below, in VS\n# the diff markers are never inserted). Diff markers may cause the following \n# file extensions to fail to load in VS. An alternative would be to treat\n# these files as binary and thus will always conflict and require user\n# intervention with every merge. To do so, just uncomment the entries below\n###############################################################################\n#*.sln       merge=binary\n#*.csproj    merge=binary\n#*.vbproj    merge=binary\n#*.vcxproj   merge=binary\n#*.vcproj    merge=binary\n#*.dbproj    merge=binary\n#*.fsproj    merge=binary\n#*.lsproj    merge=binary\n#*.wixproj   merge=binary\n#*.modelproj merge=binary\n#*.sqlproj   merge=binary\n#*.wwaproj   merge=binary\n\n###############################################################################\n# behavior for image files\n#\n# image files are treated as binary by default.\n###############################################################################\n#*.jpg   binary\n#*.png   binary\n#*.gif   binary\n\n###############################################################################\n# diff behavior for common document formats\n# \n# Convert binary document formats to text before diffing them. This feature\n# is only available from the command line. Turn it on by uncommenting the \n# entries below.\n###############################################################################\n#*.doc   diff=astextplain\n#*.DOC   diff=astextplain\n#*.docx  diff=astextplain\n#*.DOCX  diff=astextplain\n#*.dot   diff=astextplain\n#*.DOT   diff=astextplain\n#*.pdf   diff=astextplain\n#*.PDF   diff=astextplain\n#*.rtf   diff=astextplain\n#*.RTF   diff=astextplain\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: AssetStudioBuild\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\n  workflow_dispatch:\n\njobs:\n  build:\n    runs-on: windows-latest\n\n    steps:\n      - uses: actions/checkout@v2\n      - uses: microsoft/setup-msbuild@v1.1\n      \n      - name: Download FBX SDK\n        run: |\n          md fbx\n          cd fbx\n          Invoke-WebRequest \"https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_win.exe\" -OutFile \"fbxsdk.exe\"\n          Start-Process -FilePath \"fbxsdk.exe\" /S -Wait\n          Invoke-WebRequest \"https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_pdbs.exe\" -OutFile \"fbxpdb.exe\"\n          Start-Process -FilePath \"fbxpdb.exe\" /S -Wait\n          cd ..\n\n      - name: Nuget Restore\n        run: nuget restore\n      \n      - name: Build .Net472\n        run: msbuild /p:Configuration=Release /p:TargetFramework=net472 /verbosity:minimal\n\n      - name: Build .Net5\n        run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net5.0-windows /p:SelfContained=false /verbosity:minimal\n\n      - name: Build .Net6\n        run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net6.0-windows /p:SelfContained=false /verbosity:minimal\n\n      - name: Upload .Net472 Artifact\n        uses: actions/upload-artifact@v2\n        with:\n          name: AssetStudio.net472\n          path: AssetStudioGUI/bin/Release/net472\n\n      - name: Upload .Net5 Artifact\n        uses: actions/upload-artifact@v2\n        with:\n          name: AssetStudio.net5\n          path: AssetStudioGUI/bin/Release/net5.0-windows/publish\n\n      - name: Upload .Net6 Artifact\n        uses: actions/upload-artifact@v2\n        with:\n          name: AssetStudio.net6\n          path: AssetStudioGUI/bin/Release/net6.0-windows/publish\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- Backup*.rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb"
  },
  {
    "path": "AssetStudio/7zip/Common/CRC.cs",
    "content": "// Common/CRC.cs\n\nnamespace SevenZip\n{\n\tpublic class CRC\n\t{\n\t\tpublic static readonly uint[] Table;\n\n\t\tstatic CRC()\n\t\t{\n\t\t\tTable = new uint[256];\n\t\t\tconst uint kPoly = 0xEDB88320;\n\t\t\tfor (uint i = 0; i < 256; i++)\n\t\t\t{\n\t\t\t\tuint r = i;\n\t\t\t\tfor (int j = 0; j < 8; j++)\n\t\t\t\t\tif ((r & 1) != 0)\n\t\t\t\t\t\tr = (r >> 1) ^ kPoly;\n\t\t\t\t\telse\n\t\t\t\t\t\tr >>= 1;\n\t\t\t\tTable[i] = r;\n\t\t\t}\n\t\t}\n\n\t\tuint _value = 0xFFFFFFFF;\n\n\t\tpublic void Init() { _value = 0xFFFFFFFF; }\n\n\t\tpublic void UpdateByte(byte b)\n\t\t{\n\t\t\t_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);\n\t\t}\n\n\t\tpublic void Update(byte[] data, uint offset, uint size)\n\t\t{\n\t\t\tfor (uint i = 0; i < size; i++)\n\t\t\t\t_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);\n\t\t}\n\n\t\tpublic uint GetDigest() { return _value ^ 0xFFFFFFFF; }\n\n\t\tstatic uint CalculateDigest(byte[] data, uint offset, uint size)\n\t\t{\n\t\t\tCRC crc = new CRC();\n\t\t\t// crc.Init();\n\t\t\tcrc.Update(data, offset, size);\n\t\t\treturn crc.GetDigest();\n\t\t}\n\n\t\tstatic bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)\n\t\t{\n\t\t\treturn (CalculateDigest(data, offset, size) == digest);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Common/CommandLineParser.cs",
    "content": "// CommandLineParser.cs\n\nusing System;\nusing System.Collections;\n\nnamespace SevenZip.CommandLineParser\n{\n\tpublic enum SwitchType\n\t{\n\t\tSimple,\n\t\tPostMinus,\n\t\tLimitedPostString,\n\t\tUnLimitedPostString,\n\t\tPostChar\n\t}\n\n\tpublic class SwitchForm\n\t{\n\t\tpublic string IDString;\n\t\tpublic SwitchType Type;\n\t\tpublic bool Multi;\n\t\tpublic int MinLen;\n\t\tpublic int MaxLen;\n\t\tpublic string PostCharSet;\n\n\t\tpublic SwitchForm(string idString, SwitchType type, bool multi,\n\t\t\tint minLen, int maxLen, string postCharSet)\n\t\t{\n\t\t\tIDString = idString;\n\t\t\tType = type;\n\t\t\tMulti = multi;\n\t\t\tMinLen = minLen;\n\t\t\tMaxLen = maxLen;\n\t\t\tPostCharSet = postCharSet;\n\t\t}\n\t\tpublic SwitchForm(string idString, SwitchType type, bool multi, int minLen):\n\t\t\tthis(idString, type, multi, minLen, 0, \"\")\n\t\t{\n\t\t}\n\t\tpublic SwitchForm(string idString, SwitchType type, bool multi):\n\t\t\tthis(idString, type, multi, 0)\n\t\t{\n\t\t}\n\t}\n\n\tpublic class SwitchResult\n\t{\n\t\tpublic bool ThereIs;\n\t\tpublic bool WithMinus;\n\t\tpublic ArrayList PostStrings = new ArrayList();\n\t\tpublic int PostCharIndex;\n\t\tpublic SwitchResult()\n\t\t{\n\t\t\tThereIs = false;\n\t\t}\n\t}\n\n\tpublic class Parser\n\t{\n\t\tpublic ArrayList NonSwitchStrings = new ArrayList();\n\t\tSwitchResult[] _switches;\n\n\t\tpublic Parser(int numSwitches)\n\t\t{\n\t\t\t_switches = new SwitchResult[numSwitches];\n\t\t\tfor (int i = 0; i < numSwitches; i++)\n\t\t\t\t_switches[i] = new SwitchResult();\n\t\t}\n\n\t\tbool ParseString(string srcString, SwitchForm[] switchForms)\n\t\t{\n\t\t\tint len = srcString.Length;\n\t\t\tif (len == 0)\n\t\t\t\treturn false;\n\t\t\tint pos = 0;\n\t\t\tif (!IsItSwitchChar(srcString[pos]))\n\t\t\t\treturn false;\n\t\t\twhile (pos < len)\n\t\t\t{\n\t\t\t\tif (IsItSwitchChar(srcString[pos]))\n\t\t\t\t\tpos++;\n\t\t\t\tconst int kNoLen = -1;\n\t\t\t\tint matchedSwitchIndex = 0;\n\t\t\t\tint maxLen = kNoLen;\n\t\t\t\tfor (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)\n\t\t\t\t{\n\t\t\t\t\tint switchLen = switchForms[switchIndex].IDString.Length;\n\t\t\t\t\tif (switchLen <= maxLen || pos + switchLen > len)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif (String.Compare(switchForms[switchIndex].IDString, 0,\n\t\t\t\t\t\t\tsrcString, pos, switchLen, true) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tmatchedSwitchIndex = switchIndex;\n\t\t\t\t\t\tmaxLen = switchLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (maxLen == kNoLen)\n\t\t\t\t\tthrow new Exception(\"maxLen == kNoLen\");\n\t\t\t\tSwitchResult matchedSwitch = _switches[matchedSwitchIndex];\n\t\t\t\tSwitchForm switchForm = switchForms[matchedSwitchIndex];\n\t\t\t\tif ((!switchForm.Multi) && matchedSwitch.ThereIs)\n\t\t\t\t\tthrow new Exception(\"switch must be single\");\n\t\t\t\tmatchedSwitch.ThereIs = true;\n\t\t\t\tpos += maxLen;\n\t\t\t\tint tailSize = len - pos;\n\t\t\t\tSwitchType type = switchForm.Type;\n\t\t\t\tswitch (type)\n\t\t\t\t{\n\t\t\t\t\tcase SwitchType.PostMinus:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (tailSize == 0)\n\t\t\t\t\t\t\t\tmatchedSwitch.WithMinus = false;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmatchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus);\n\t\t\t\t\t\t\t\tif (matchedSwitch.WithMinus)\n\t\t\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tcase SwitchType.PostChar:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (tailSize < switchForm.MinLen)\n\t\t\t\t\t\t\t\tthrow new Exception(\"switch is not full\");\n\t\t\t\t\t\t\tstring charSet = switchForm.PostCharSet;\n\t\t\t\t\t\t\tconst int kEmptyCharValue = -1;\n\t\t\t\t\t\t\tif (tailSize == 0)\n\t\t\t\t\t\t\t\tmatchedSwitch.PostCharIndex = kEmptyCharValue;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint index = charSet.IndexOf(srcString[pos]);\n\t\t\t\t\t\t\t\tif (index < 0)\n\t\t\t\t\t\t\t\t\tmatchedSwitch.PostCharIndex = kEmptyCharValue;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmatchedSwitch.PostCharIndex = index;\n\t\t\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tcase SwitchType.LimitedPostString:\n\t\t\t\t\tcase SwitchType.UnLimitedPostString:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint minLen = switchForm.MinLen;\n\t\t\t\t\t\t\tif (tailSize < minLen)\n\t\t\t\t\t\t\t\tthrow new Exception(\"switch is not full\");\n\t\t\t\t\t\t\tif (type == SwitchType.UnLimitedPostString)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmatchedSwitch.PostStrings.Add(srcString.Substring(pos));\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tString stringSwitch = srcString.Substring(pos, minLen);\n\t\t\t\t\t\t\tpos += minLen;\n\t\t\t\t\t\t\tfor (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tchar c = srcString[pos];\n\t\t\t\t\t\t\t\tif (IsItSwitchChar(c))\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tstringSwitch += c;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmatchedSwitch.PostStrings.Add(stringSwitch);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\n\t\t}\n\n\t\tpublic void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)\n\t\t{\n\t\t\tint numCommandStrings = commandStrings.Length;\n\t\t\tbool stopSwitch = false;\n\t\t\tfor (int i = 0; i < numCommandStrings; i++)\n\t\t\t{\n\t\t\t\tstring s = commandStrings[i];\n\t\t\t\tif (stopSwitch)\n\t\t\t\t\tNonSwitchStrings.Add(s);\n\t\t\t\telse\n\t\t\t\t\tif (s == kStopSwitchParsing)\n\t\t\t\t\tstopSwitch = true;\n\t\t\t\telse\n\t\t\t\t\tif (!ParseString(s, switchForms))\n\t\t\t\t\tNonSwitchStrings.Add(s);\n\t\t\t}\n\t\t}\n\n\t\tpublic SwitchResult this[int index] { get { return _switches[index]; } }\n\n\t\tpublic static int ParseCommand(CommandForm[] commandForms, string commandString,\n\t\t\tout string postString)\n\t\t{\n\t\t\tfor (int i = 0; i < commandForms.Length; i++)\n\t\t\t{\n\t\t\t\tstring id = commandForms[i].IDString;\n\t\t\t\tif (commandForms[i].PostStringMode)\n\t\t\t\t{\n\t\t\t\t\tif (commandString.IndexOf(id) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tpostString = commandString.Substring(id.Length);\n\t\t\t\t\t\treturn i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tif (commandString == id)\n\t\t\t\t{\n\t\t\t\t\tpostString = \"\";\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpostString = \"\";\n\t\t\treturn -1;\n\t\t}\n\n\t\tstatic bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,\n\t\t\tstring commandString, ArrayList indices)\n\t\t{\n\t\t\tindices.Clear();\n\t\t\tint numUsedChars = 0;\n\t\t\tfor (int i = 0; i < numForms; i++)\n\t\t\t{\n\t\t\t\tCommandSubCharsSet charsSet = forms[i];\n\t\t\t\tint currentIndex = -1;\n\t\t\t\tint len = charsSet.Chars.Length;\n\t\t\t\tfor (int j = 0; j < len; j++)\n\t\t\t\t{\n\t\t\t\t\tchar c = charsSet.Chars[j];\n\t\t\t\t\tint newIndex = commandString.IndexOf(c);\n\t\t\t\t\tif (newIndex >= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (currentIndex >= 0)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\tif (commandString.IndexOf(c, newIndex + 1) >= 0)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\tcurrentIndex = j;\n\t\t\t\t\t\tnumUsedChars++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (currentIndex == -1 && !charsSet.EmptyAllowed)\n\t\t\t\t\treturn false;\n\t\t\t\tindices.Add(currentIndex);\n\t\t\t}\n\t\t\treturn (numUsedChars == commandString.Length);\n\t\t}\n\t\tconst char kSwitchID1 = '-';\n\t\tconst char kSwitchID2 = '/';\n\n\t\tconst char kSwitchMinus = '-';\n\t\tconst string kStopSwitchParsing = \"--\";\n\n\t\tstatic bool IsItSwitchChar(char c)\n\t\t{\n\t\t\treturn (c == kSwitchID1 || c == kSwitchID2);\n\t\t}\n\t}\n\n\tpublic class CommandForm\n\t{\n\t\tpublic string IDString = \"\";\n\t\tpublic bool PostStringMode = false;\n\t\tpublic CommandForm(string idString, bool postStringMode)\n\t\t{\n\t\t\tIDString = idString;\n\t\t\tPostStringMode = postStringMode;\n\t\t}\n\t}\n\n\tclass CommandSubCharsSet\n\t{\n\t\tpublic string Chars = \"\";\n\t\tpublic bool EmptyAllowed = false;\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Common/InBuffer.cs",
    "content": "// InBuffer.cs\n\nnamespace SevenZip.Buffer\n{\n\tpublic class InBuffer\n\t{\n\t\tbyte[] m_Buffer;\n\t\tuint m_Pos;\n\t\tuint m_Limit;\n\t\tuint m_BufferSize;\n\t\tSystem.IO.Stream m_Stream;\n\t\tbool m_StreamWasExhausted;\n\t\tulong m_ProcessedSize;\n\n\t\tpublic InBuffer(uint bufferSize)\n\t\t{\n\t\t\tm_Buffer = new byte[bufferSize];\n\t\t\tm_BufferSize = bufferSize;\n\t\t}\n\n\t\tpublic void Init(System.IO.Stream stream)\n\t\t{\n\t\t\tm_Stream = stream;\n\t\t\tm_ProcessedSize = 0;\n\t\t\tm_Limit = 0;\n\t\t\tm_Pos = 0;\n\t\t\tm_StreamWasExhausted = false;\n\t\t}\n\n\t\tpublic bool ReadBlock()\n\t\t{\n\t\t\tif (m_StreamWasExhausted)\n\t\t\t\treturn false;\n\t\t\tm_ProcessedSize += m_Pos;\n\t\t\tint aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);\n\t\t\tm_Pos = 0;\n\t\t\tm_Limit = (uint)aNumProcessedBytes;\n\t\t\tm_StreamWasExhausted = (aNumProcessedBytes == 0);\n\t\t\treturn (!m_StreamWasExhausted);\n\t\t}\n\n\n\t\tpublic void ReleaseStream()\n\t\t{\n\t\t\t// m_Stream.Close(); \n\t\t\tm_Stream = null;\n\t\t}\n\n\t\tpublic bool ReadByte(byte b) // check it\n\t\t{\n\t\t\tif (m_Pos >= m_Limit)\n\t\t\t\tif (!ReadBlock())\n\t\t\t\t\treturn false;\n\t\t\tb = m_Buffer[m_Pos++];\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic byte ReadByte()\n\t\t{\n\t\t\t// return (byte)m_Stream.ReadByte();\n\t\t\tif (m_Pos >= m_Limit)\n\t\t\t\tif (!ReadBlock())\n\t\t\t\t\treturn 0xFF;\n\t\t\treturn m_Buffer[m_Pos++];\n\t\t}\n\n\t\tpublic ulong GetProcessedSize()\n\t\t{\n\t\t\treturn m_ProcessedSize + m_Pos;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Common/OutBuffer.cs",
    "content": "// OutBuffer.cs\n\nnamespace SevenZip.Buffer\n{\n\tpublic class OutBuffer\n\t{\n\t\tbyte[] m_Buffer;\n\t\tuint m_Pos;\n\t\tuint m_BufferSize;\n\t\tSystem.IO.Stream m_Stream;\n\t\tulong m_ProcessedSize;\n\n\t\tpublic OutBuffer(uint bufferSize)\n\t\t{\n\t\t\tm_Buffer = new byte[bufferSize];\n\t\t\tm_BufferSize = bufferSize;\n\t\t}\n\n\t\tpublic void SetStream(System.IO.Stream stream) { m_Stream = stream; }\n\t\tpublic void FlushStream() { m_Stream.Flush(); }\n\t\tpublic void CloseStream() { m_Stream.Close(); }\n\t\tpublic void ReleaseStream() { m_Stream = null; }\n\n\t\tpublic void Init()\n\t\t{\n\t\t\tm_ProcessedSize = 0;\n\t\t\tm_Pos = 0;\n\t\t}\n\n\t\tpublic void WriteByte(byte b)\n\t\t{\n\t\t\tm_Buffer[m_Pos++] = b;\n\t\t\tif (m_Pos >= m_BufferSize)\n\t\t\t\tFlushData();\n\t\t}\n\n\t\tpublic void FlushData()\n\t\t{\n\t\t\tif (m_Pos == 0)\n\t\t\t\treturn;\n\t\t\tm_Stream.Write(m_Buffer, 0, (int)m_Pos);\n\t\t\tm_Pos = 0;\n\t\t}\n\n\t\tpublic ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/LZ/IMatchFinder.cs",
    "content": "// IMatchFinder.cs\n\nusing System;\n\nnamespace SevenZip.Compression.LZ\n{\n\tinterface IInWindowStream\n\t{\n\t\tvoid SetStream(System.IO.Stream inStream);\n\t\tvoid Init();\n\t\tvoid ReleaseStream();\n\t\tByte GetIndexByte(Int32 index);\n\t\tUInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);\n\t\tUInt32 GetNumAvailableBytes();\n\t}\n\n\tinterface IMatchFinder : IInWindowStream\n\t{\n\t\tvoid Create(UInt32 historySize, UInt32 keepAddBufferBefore,\n\t\t\t\tUInt32 matchMaxLen, UInt32 keepAddBufferAfter);\n\t\tUInt32 GetMatches(UInt32[] distances);\n\t\tvoid Skip(UInt32 num);\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/LZ/LzBinTree.cs",
    "content": "// LzBinTree.cs\n\nusing System;\n\nnamespace SevenZip.Compression.LZ\n{\n\tpublic class BinTree : InWindow, IMatchFinder\n\t{\n\t\tUInt32 _cyclicBufferPos;\n\t\tUInt32 _cyclicBufferSize = 0;\n\t\tUInt32 _matchMaxLen;\n\n\t\tUInt32[] _son;\n\t\tUInt32[] _hash;\n\n\t\tUInt32 _cutValue = 0xFF;\n\t\tUInt32 _hashMask;\n\t\tUInt32 _hashSizeSum = 0;\n\n\t\tbool HASH_ARRAY = true;\n\n\t\tconst UInt32 kHash2Size = 1 << 10;\n\t\tconst UInt32 kHash3Size = 1 << 16;\n\t\tconst UInt32 kBT2HashSize = 1 << 16;\n\t\tconst UInt32 kStartMaxLen = 1;\n\t\tconst UInt32 kHash3Offset = kHash2Size;\n\t\tconst UInt32 kEmptyHashValue = 0;\n\t\tconst UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;\n\t\n\t\tUInt32 kNumHashDirectBytes = 0;\n\t\tUInt32 kMinMatchCheck = 4;\n\t\tUInt32 kFixHashSize = kHash2Size + kHash3Size;\n\t\t\n\t\tpublic void SetType(int numHashBytes)\n\t\t{\n\t\t\tHASH_ARRAY = (numHashBytes > 2);\n\t\t\tif (HASH_ARRAY)\n\t\t\t{\n\t\t\t\tkNumHashDirectBytes = 0;\n\t\t\t\tkMinMatchCheck = 4;\n\t\t\t\tkFixHashSize = kHash2Size + kHash3Size;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tkNumHashDirectBytes = 2;\n\t\t\t\tkMinMatchCheck = 2 + 1;\n\t\t\t\tkFixHashSize = 0;\n\t\t\t}\n\t\t}\n\n\t\tpublic new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }\n\t\tpublic new void ReleaseStream() { base.ReleaseStream(); }\n\t\t\n\t\tpublic new void Init()\n\t\t{\n\t\t\tbase.Init();\n\t\t\tfor (UInt32 i = 0; i < _hashSizeSum; i++)\n\t\t\t\t_hash[i] = kEmptyHashValue;\n\t\t\t_cyclicBufferPos = 0;\n\t\t\tReduceOffsets(-1);\n\t\t}\n\n\t\tpublic new void MovePos()\n\t\t{\n\t\t\tif (++_cyclicBufferPos >= _cyclicBufferSize)\n\t\t\t\t_cyclicBufferPos = 0;\n\t\t\tbase.MovePos();\n\t\t\tif (_pos == kMaxValForNormalize)\n\t\t\t\tNormalize();\n\t\t}\n\n\t\tpublic new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }\n\n\t\tpublic new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)\n\t\t{ return base.GetMatchLen(index, distance, limit); }\n\n\t\tpublic new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }\n\n\t\tpublic void Create(UInt32 historySize, UInt32 keepAddBufferBefore,\n\t\t\t\tUInt32 matchMaxLen, UInt32 keepAddBufferAfter)\n\t\t{\n\t\t\tif (historySize > kMaxValForNormalize - 256)\n\t\t\t\tthrow new Exception();\n\t\t\t_cutValue = 16 + (matchMaxLen >> 1);\n\t\t\t\t\n\t\t\tUInt32 windowReservSize = (historySize + keepAddBufferBefore +\n\t\t\t\t\tmatchMaxLen + keepAddBufferAfter) / 2 + 256;\n\n\t\t\tbase.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);\n\n\t\t\t_matchMaxLen = matchMaxLen;\n\n\t\t\tUInt32 cyclicBufferSize = historySize + 1;\n\t\t\tif (_cyclicBufferSize != cyclicBufferSize)\n\t\t\t\t_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];\n\n\t\t\tUInt32 hs = kBT2HashSize;\n\n\t\t\tif (HASH_ARRAY)\n\t\t\t{\n\t\t\t\ths = historySize - 1;\n\t\t\t\ths |= (hs >> 1);\n\t\t\t\ths |= (hs >> 2);\n\t\t\t\ths |= (hs >> 4);\n\t\t\t\ths |= (hs >> 8);\n\t\t\t\ths >>= 1;\n\t\t\t\ths |= 0xFFFF;\n\t\t\t\tif (hs > (1 << 24))\n\t\t\t\t\ths >>= 1;\n\t\t\t\t_hashMask = hs;\n\t\t\t\ths++;\n\t\t\t\ths += kFixHashSize;\n\t\t\t}\n\t\t\tif (hs != _hashSizeSum)\n\t\t\t\t_hash = new UInt32[_hashSizeSum = hs];\n\t\t}\n\n\t\tpublic UInt32 GetMatches(UInt32[] distances)\n\t\t{\n\t\t\tUInt32 lenLimit;\n\t\t\tif (_pos + _matchMaxLen <= _streamPos)\n\t\t\t\tlenLimit = _matchMaxLen;\n\t\t\telse\n\t\t\t{\n\t\t\t\tlenLimit = _streamPos - _pos;\n\t\t\t\tif (lenLimit < kMinMatchCheck)\n\t\t\t\t{\n\t\t\t\t\tMovePos();\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tUInt32 offset = 0;\n\t\t\tUInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;\n\t\t\tUInt32 cur = _bufferOffset + _pos;\n\t\t\tUInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;\n\t\t\tUInt32 hashValue, hash2Value = 0, hash3Value = 0;\n\n\t\t\tif (HASH_ARRAY)\n\t\t\t{\n\t\t\t\tUInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];\n\t\t\t\thash2Value = temp & (kHash2Size - 1);\n\t\t\t\ttemp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);\n\t\t\t\thash3Value = temp & (kHash3Size - 1);\n\t\t\t\thashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;\n\t\t\t}\n\t\t\telse\n\t\t\t\thashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);\n\n\t\t\tUInt32 curMatch = _hash[kFixHashSize + hashValue];\n\t\t\tif (HASH_ARRAY)\n\t\t\t{\n\t\t\t\tUInt32 curMatch2 = _hash[hash2Value];\n\t\t\t\tUInt32 curMatch3 = _hash[kHash3Offset + hash3Value];\n\t\t\t\t_hash[hash2Value] = _pos;\n\t\t\t\t_hash[kHash3Offset + hash3Value] = _pos;\n\t\t\t\tif (curMatch2 > matchMinPos)\n\t\t\t\t\tif (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])\n\t\t\t\t\t{\n\t\t\t\t\t\tdistances[offset++] = maxLen = 2;\n\t\t\t\t\t\tdistances[offset++] = _pos - curMatch2 - 1;\n\t\t\t\t\t}\n\t\t\t\tif (curMatch3 > matchMinPos)\n\t\t\t\t\tif (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])\n\t\t\t\t\t{\n\t\t\t\t\t\tif (curMatch3 == curMatch2)\n\t\t\t\t\t\t\toffset -= 2;\n\t\t\t\t\t\tdistances[offset++] = maxLen = 3;\n\t\t\t\t\t\tdistances[offset++] = _pos - curMatch3 - 1;\n\t\t\t\t\t\tcurMatch2 = curMatch3;\n\t\t\t\t\t}\n\t\t\t\tif (offset != 0 && curMatch2 == curMatch)\n\t\t\t\t{\n\t\t\t\t\toffset -= 2;\n\t\t\t\t\tmaxLen = kStartMaxLen;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t_hash[kFixHashSize + hashValue] = _pos;\n\n\t\t\tUInt32 ptr0 = (_cyclicBufferPos << 1) + 1;\n\t\t\tUInt32 ptr1 = (_cyclicBufferPos << 1);\n\n\t\t\tUInt32 len0, len1;\n\t\t\tlen0 = len1 = kNumHashDirectBytes;\n\t\t\t\n\t\t\tif (kNumHashDirectBytes != 0)\n\t\t\t{\n\t\t\t\tif (curMatch > matchMinPos)\n\t\t\t\t{\n\t\t\t\t\tif (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=\n\t\t\t\t\t\t\t_bufferBase[cur + kNumHashDirectBytes])\n\t\t\t\t\t{\n\t\t\t\t\t\tdistances[offset++] = maxLen = kNumHashDirectBytes;\n\t\t\t\t\t\tdistances[offset++] = _pos - curMatch - 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tUInt32 count = _cutValue;\n\t\t\t\n\t\t\twhile(true)\n\t\t\t{\n\t\t\t\tif(curMatch <= matchMinPos || count-- == 0)\n\t\t\t\t{\n\t\t\t\t\t_son[ptr0] = _son[ptr1] = kEmptyHashValue;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tUInt32 delta = _pos - curMatch;\n\t\t\t\tUInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?\n\t\t\t\t\t\t\t(_cyclicBufferPos - delta) :\n\t\t\t\t\t\t\t(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;\n\n\t\t\t\tUInt32 pby1 = _bufferOffset + curMatch;\n\t\t\t\tUInt32 len = Math.Min(len0, len1);\n\t\t\t\tif (_bufferBase[pby1 + len] == _bufferBase[cur + len])\n\t\t\t\t{\n\t\t\t\t\twhile(++len != lenLimit)\n\t\t\t\t\t\tif (_bufferBase[pby1 + len] != _bufferBase[cur + len])\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tif (maxLen < len)\n\t\t\t\t\t{\n\t\t\t\t\t\tdistances[offset++] = maxLen = len;\n\t\t\t\t\t\tdistances[offset++] = delta - 1;\n\t\t\t\t\t\tif (len == lenLimit)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_son[ptr1] = _son[cyclicPos];\n\t\t\t\t\t\t\t_son[ptr0] = _son[cyclicPos + 1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (_bufferBase[pby1 + len] < _bufferBase[cur + len])\n\t\t\t\t{\n\t\t\t\t\t_son[ptr1] = curMatch;\n\t\t\t\t\tptr1 = cyclicPos + 1;\n\t\t\t\t\tcurMatch = _son[ptr1];\n\t\t\t\t\tlen1 = len;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_son[ptr0] = curMatch;\n\t\t\t\t\tptr0 = cyclicPos;\n\t\t\t\t\tcurMatch = _son[ptr0];\n\t\t\t\t\tlen0 = len;\n\t\t\t\t}\n\t\t\t}\n\t\t\tMovePos();\n\t\t\treturn offset;\n\t\t}\n\n\t\tpublic void Skip(UInt32 num)\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tUInt32 lenLimit;\n\t\t\t\tif (_pos + _matchMaxLen <= _streamPos)\n\t\t\t\t\tlenLimit = _matchMaxLen;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlenLimit = _streamPos - _pos;\n\t\t\t\t\tif (lenLimit < kMinMatchCheck)\n\t\t\t\t\t{\n\t\t\t\t\t\tMovePos();\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tUInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;\n\t\t\t\tUInt32 cur = _bufferOffset + _pos;\n\n\t\t\t\tUInt32 hashValue;\n\n\t\t\t\tif (HASH_ARRAY)\n\t\t\t\t{\n\t\t\t\t\tUInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];\n\t\t\t\t\tUInt32 hash2Value = temp & (kHash2Size - 1);\n\t\t\t\t\t_hash[hash2Value] = _pos;\n\t\t\t\t\ttemp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);\n\t\t\t\t\tUInt32 hash3Value = temp & (kHash3Size - 1);\n\t\t\t\t\t_hash[kHash3Offset + hash3Value] = _pos;\n\t\t\t\t\thashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\thashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);\n\n\t\t\t\tUInt32 curMatch = _hash[kFixHashSize + hashValue];\n\t\t\t\t_hash[kFixHashSize + hashValue] = _pos;\n\n\t\t\t\tUInt32 ptr0 = (_cyclicBufferPos << 1) + 1;\n\t\t\t\tUInt32 ptr1 = (_cyclicBufferPos << 1);\n\n\t\t\t\tUInt32 len0, len1;\n\t\t\t\tlen0 = len1 = kNumHashDirectBytes;\n\n\t\t\t\tUInt32 count = _cutValue;\n\t\t\t\twhile (true)\n\t\t\t\t{\n\t\t\t\t\tif (curMatch <= matchMinPos || count-- == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t_son[ptr0] = _son[ptr1] = kEmptyHashValue;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tUInt32 delta = _pos - curMatch;\n\t\t\t\t\tUInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?\n\t\t\t\t\t\t\t\t(_cyclicBufferPos - delta) :\n\t\t\t\t\t\t\t\t(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;\n\n\t\t\t\t\tUInt32 pby1 = _bufferOffset + curMatch;\n\t\t\t\t\tUInt32 len = Math.Min(len0, len1);\n\t\t\t\t\tif (_bufferBase[pby1 + len] == _bufferBase[cur + len])\n\t\t\t\t\t{\n\t\t\t\t\t\twhile (++len != lenLimit)\n\t\t\t\t\t\t\tif (_bufferBase[pby1 + len] != _bufferBase[cur + len])\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tif (len == lenLimit)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_son[ptr1] = _son[cyclicPos];\n\t\t\t\t\t\t\t_son[ptr0] = _son[cyclicPos + 1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (_bufferBase[pby1 + len] < _bufferBase[cur + len])\n\t\t\t\t\t{\n\t\t\t\t\t\t_son[ptr1] = curMatch;\n\t\t\t\t\t\tptr1 = cyclicPos + 1;\n\t\t\t\t\t\tcurMatch = _son[ptr1];\n\t\t\t\t\t\tlen1 = len;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_son[ptr0] = curMatch;\n\t\t\t\t\t\tptr0 = cyclicPos;\n\t\t\t\t\t\tcurMatch = _son[ptr0];\n\t\t\t\t\t\tlen0 = len;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tMovePos();\n\t\t\t}\n\t\t\twhile (--num != 0);\n\t\t}\n\n\t\tvoid NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)\n\t\t{\n\t\t\tfor (UInt32 i = 0; i < numItems; i++)\n\t\t\t{\n\t\t\t\tUInt32 value = items[i];\n\t\t\t\tif (value <= subValue)\n\t\t\t\t\tvalue = kEmptyHashValue;\n\t\t\t\telse\n\t\t\t\t\tvalue -= subValue;\n\t\t\t\titems[i] = value;\n\t\t\t}\n\t\t}\n\n\t\tvoid Normalize()\n\t\t{\n\t\t\tUInt32 subValue = _pos - _cyclicBufferSize;\n\t\t\tNormalizeLinks(_son, _cyclicBufferSize * 2, subValue);\n\t\t\tNormalizeLinks(_hash, _hashSizeSum, subValue);\n\t\t\tReduceOffsets((Int32)subValue);\n\t\t}\n\n\t\tpublic void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/LZ/LzInWindow.cs",
    "content": "// LzInWindow.cs\n\nusing System;\n\nnamespace SevenZip.Compression.LZ\n{\n\tpublic class InWindow\n\t{\n\t\tpublic Byte[] _bufferBase = null; // pointer to buffer with data\n\t\tSystem.IO.Stream _stream;\n\t\tUInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done\n\t\tbool _streamEndWasReached; // if (true) then _streamPos shows real end of stream\n\n\t\tUInt32 _pointerToLastSafePosition;\n\n\t\tpublic UInt32 _bufferOffset;\n\n\t\tpublic UInt32 _blockSize; // Size of Allocated memory block\n\t\tpublic UInt32 _pos; // offset (from _buffer) of curent byte\n\t\tUInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos\n\t\tUInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos\n\t\tpublic UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream\n\n\t\tpublic void MoveBlock()\n\t\t{\n\t\t\tUInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;\n\t\t\t// we need one additional byte, since MovePos moves on 1 byte.\n\t\t\tif (offset > 0)\n\t\t\t\toffset--;\n\t\t\t\n\t\t\tUInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;\n\n\t\t\t// check negative offset ????\n\t\t\tfor (UInt32 i = 0; i < numBytes; i++)\n\t\t\t\t_bufferBase[i] = _bufferBase[offset + i];\n\t\t\t_bufferOffset -= offset;\n\t\t}\n\n\t\tpublic virtual void ReadBlock()\n\t\t{\n\t\t\tif (_streamEndWasReached)\n\t\t\t\treturn;\n\t\t\twhile (true)\n\t\t\t{\n\t\t\t\tint size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);\n\t\t\t\tif (size == 0)\n\t\t\t\t\treturn;\n\t\t\t\tint numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);\n\t\t\t\tif (numReadBytes == 0)\n\t\t\t\t{\n\t\t\t\t\t_posLimit = _streamPos;\n\t\t\t\t\tUInt32 pointerToPostion = _bufferOffset + _posLimit;\n\t\t\t\t\tif (pointerToPostion > _pointerToLastSafePosition)\n\t\t\t\t\t\t_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);\n\n\t\t\t\t\t_streamEndWasReached = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t_streamPos += (UInt32)numReadBytes;\n\t\t\t\tif (_streamPos >= _pos + _keepSizeAfter)\n\t\t\t\t\t_posLimit = _streamPos - _keepSizeAfter;\n\t\t\t}\n\t\t}\n\n\t\tvoid Free() { _bufferBase = null; }\n\n\t\tpublic void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)\n\t\t{\n\t\t\t_keepSizeBefore = keepSizeBefore;\n\t\t\t_keepSizeAfter = keepSizeAfter;\n\t\t\tUInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;\n\t\t\tif (_bufferBase == null || _blockSize != blockSize)\n\t\t\t{\n\t\t\t\tFree();\n\t\t\t\t_blockSize = blockSize;\n\t\t\t\t_bufferBase = new Byte[_blockSize];\n\t\t\t}\n\t\t\t_pointerToLastSafePosition = _blockSize - keepSizeAfter;\n\t\t}\n\n\t\tpublic void SetStream(System.IO.Stream stream) { _stream = stream; }\n\t\tpublic void ReleaseStream() { _stream = null; }\n\n\t\tpublic void Init()\n\t\t{\n\t\t\t_bufferOffset = 0;\n\t\t\t_pos = 0;\n\t\t\t_streamPos = 0;\n\t\t\t_streamEndWasReached = false;\n\t\t\tReadBlock();\n\t\t}\n\n\t\tpublic void MovePos()\n\t\t{\n\t\t\t_pos++;\n\t\t\tif (_pos > _posLimit)\n\t\t\t{\n\t\t\t\tUInt32 pointerToPostion = _bufferOffset + _pos;\n\t\t\t\tif (pointerToPostion > _pointerToLastSafePosition)\n\t\t\t\t\tMoveBlock();\n\t\t\t\tReadBlock();\n\t\t\t}\n\t\t}\n\n\t\tpublic Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }\n\n\t\t// index + limit have not to exceed _keepSizeAfter;\n\t\tpublic UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)\n\t\t{\n\t\t\tif (_streamEndWasReached)\n\t\t\t\tif ((_pos + index) + limit > _streamPos)\n\t\t\t\t\tlimit = _streamPos - (UInt32)(_pos + index);\n\t\t\tdistance++;\n\t\t\t// Byte *pby = _buffer + (size_t)_pos + index;\n\t\t\tUInt32 pby = _bufferOffset + _pos + (UInt32)index;\n\n\t\t\tUInt32 i;\n\t\t\tfor (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);\n\t\t\treturn i;\n\t\t}\n\n\t\tpublic UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }\n\n\t\tpublic void ReduceOffsets(Int32 subValue)\n\t\t{\n\t\t\t_bufferOffset += (UInt32)subValue;\n\t\t\t_posLimit -= (UInt32)subValue;\n\t\t\t_pos -= (UInt32)subValue;\n\t\t\t_streamPos -= (UInt32)subValue;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/LZ/LzOutWindow.cs",
    "content": "// LzOutWindow.cs\n\nnamespace SevenZip.Compression.LZ\n{\n\tpublic class OutWindow\n\t{\n\t\tbyte[] _buffer = null;\n\t\tuint _pos;\n\t\tuint _windowSize = 0;\n\t\tuint _streamPos;\n\t\tSystem.IO.Stream _stream;\n\n\t\tpublic uint TrainSize = 0;\n\n\t\tpublic void Create(uint windowSize)\n\t\t{\n\t\t\tif (_windowSize != windowSize)\n\t\t\t{\n\t\t\t\t// System.GC.Collect();\n\t\t\t\t_buffer = new byte[windowSize];\n\t\t\t}\n\t\t\t_windowSize = windowSize;\n\t\t\t_pos = 0;\n\t\t\t_streamPos = 0;\n\t\t}\n\n\t\tpublic void Init(System.IO.Stream stream, bool solid)\n\t\t{\n\t\t\tReleaseStream();\n\t\t\t_stream = stream;\n\t\t\tif (!solid)\n\t\t\t{\n\t\t\t\t_streamPos = 0;\n\t\t\t\t_pos = 0;\n\t\t\t\tTrainSize = 0;\n\t\t\t}\n\t\t}\n\t\n\t\tpublic bool Train(System.IO.Stream stream)\n\t\t{\n\t\t\tlong len = stream.Length;\n\t\t\tuint size = (len < _windowSize) ? (uint)len : _windowSize;\n\t\t\tTrainSize = size;\n\t\t\tstream.Position = len - size;\n\t\t\t_streamPos = _pos = 0;\n\t\t\twhile (size > 0)\n\t\t\t{\n\t\t\t\tuint curSize = _windowSize - _pos;\n\t\t\t\tif (size < curSize)\n\t\t\t\t\tcurSize = size;\n\t\t\t\tint numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);\n\t\t\t\tif (numReadBytes == 0)\n\t\t\t\t\treturn false;\n\t\t\t\tsize -= (uint)numReadBytes;\n\t\t\t\t_pos += (uint)numReadBytes;\n\t\t\t\t_streamPos += (uint)numReadBytes;\n\t\t\t\tif (_pos == _windowSize)\n\t\t\t\t\t_streamPos = _pos = 0;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic void ReleaseStream()\n\t\t{\n\t\t\tFlush();\n\t\t\t_stream = null;\n\t\t}\n\n\t\tpublic void Flush()\n\t\t{\n\t\t\tuint size = _pos - _streamPos;\n\t\t\tif (size == 0)\n\t\t\t\treturn;\n\t\t\t_stream.Write(_buffer, (int)_streamPos, (int)size);\n\t\t\tif (_pos >= _windowSize)\n\t\t\t\t_pos = 0;\n\t\t\t_streamPos = _pos;\n\t\t}\n\n\t\tpublic void CopyBlock(uint distance, uint len)\n\t\t{\n\t\t\tuint pos = _pos - distance - 1;\n\t\t\tif (pos >= _windowSize)\n\t\t\t\tpos += _windowSize;\n\t\t\tfor (; len > 0; len--)\n\t\t\t{\n\t\t\t\tif (pos >= _windowSize)\n\t\t\t\t\tpos = 0;\n\t\t\t\t_buffer[_pos++] = _buffer[pos++];\n\t\t\t\tif (_pos >= _windowSize)\n\t\t\t\t\tFlush();\n\t\t\t}\n\t\t}\n\n\t\tpublic void PutByte(byte b)\n\t\t{\n\t\t\t_buffer[_pos++] = b;\n\t\t\tif (_pos >= _windowSize)\n\t\t\t\tFlush();\n\t\t}\n\n\t\tpublic byte GetByte(uint distance)\n\t\t{\n\t\t\tuint pos = _pos - distance - 1;\n\t\t\tif (pos >= _windowSize)\n\t\t\t\tpos += _windowSize;\n\t\t\treturn _buffer[pos];\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/LZMA/LzmaBase.cs",
    "content": "// LzmaBase.cs\n\nnamespace SevenZip.Compression.LZMA\n{\n\tinternal abstract class Base\n\t{\n\t\tpublic const uint kNumRepDistances = 4;\n\t\tpublic const uint kNumStates = 12;\n\n\t\t// static byte []kLiteralNextStates  = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};\n\t\t// static byte []kMatchNextStates    = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\n\t\t// static byte []kRepNextStates      = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\n\t\t// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};\n\n\t\tpublic struct State\n\t\t{\n\t\t\tpublic uint Index;\n\t\t\tpublic void Init() { Index = 0; }\n\t\t\tpublic void UpdateChar()\n\t\t\t{\n\t\t\t\tif (Index < 4) Index = 0;\n\t\t\t\telse if (Index < 10) Index -= 3;\n\t\t\t\telse Index -= 6;\n\t\t\t}\n\t\t\tpublic void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }\n\t\t\tpublic void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }\n\t\t\tpublic void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }\n\t\t\tpublic bool IsCharState() { return Index < 7; }\n\t\t}\n\n\t\tpublic const int kNumPosSlotBits = 6;\n\t\tpublic const int kDicLogSizeMin = 0;\n\t\t// public const int kDicLogSizeMax = 30;\n\t\t// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;\n\n\t\tpublic const int kNumLenToPosStatesBits = 2; // it's for speed optimization\n\t\tpublic const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;\n\n\t\tpublic const uint kMatchMinLen = 2;\n\n\t\tpublic static uint GetLenToPosState(uint len)\n\t\t{\n\t\t\tlen -= kMatchMinLen;\n\t\t\tif (len < kNumLenToPosStates)\n\t\t\t\treturn len;\n\t\t\treturn (uint)(kNumLenToPosStates - 1);\n\t\t}\n\n\t\tpublic const int kNumAlignBits = 4;\n\t\tpublic const uint kAlignTableSize = 1 << kNumAlignBits;\n\t\tpublic const uint kAlignMask = (kAlignTableSize - 1);\n\n\t\tpublic const uint kStartPosModelIndex = 4;\n\t\tpublic const uint kEndPosModelIndex = 14;\n\t\tpublic const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;\n\n\t\tpublic const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);\n\n\t\tpublic const uint kNumLitPosStatesBitsEncodingMax = 4;\n\t\tpublic const uint kNumLitContextBitsMax = 8;\n\n\t\tpublic const int kNumPosStatesBitsMax = 4;\n\t\tpublic const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);\n\t\tpublic const int kNumPosStatesBitsEncodingMax = 4;\n\t\tpublic const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);\n\n\t\tpublic const int kNumLowLenBits = 3;\n\t\tpublic const int kNumMidLenBits = 3;\n\t\tpublic const int kNumHighLenBits = 8;\n\t\tpublic const uint kNumLowLenSymbols = 1 << kNumLowLenBits;\n\t\tpublic const uint kNumMidLenSymbols = 1 << kNumMidLenBits;\n\t\tpublic const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +\n\t\t\t\t(1 << kNumHighLenBits);\n\t\tpublic const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/LZMA/LzmaDecoder.cs",
    "content": "// LzmaDecoder.cs\n\nusing System;\n\nnamespace SevenZip.Compression.LZMA\n{\n\tusing RangeCoder;\n\n\tpublic class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream\n\t{\n\t\tclass LenDecoder\n\t\t{\n\t\t\tBitDecoder m_Choice = new BitDecoder();\n\t\t\tBitDecoder m_Choice2 = new BitDecoder();\n\t\t\tBitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];\n\t\t\tBitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];\n\t\t\tBitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);\n\t\t\tuint m_NumPosStates = 0;\n\n\t\t\tpublic void Create(uint numPosStates)\n\t\t\t{\n\t\t\t\tfor (uint posState = m_NumPosStates; posState < numPosStates; posState++)\n\t\t\t\t{\n\t\t\t\t\tm_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);\n\t\t\t\t\tm_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);\n\t\t\t\t}\n\t\t\t\tm_NumPosStates = numPosStates;\n\t\t\t}\n\n\t\t\tpublic void Init()\n\t\t\t{\n\t\t\t\tm_Choice.Init();\n\t\t\t\tfor (uint posState = 0; posState < m_NumPosStates; posState++)\n\t\t\t\t{\n\t\t\t\t\tm_LowCoder[posState].Init();\n\t\t\t\t\tm_MidCoder[posState].Init();\n\t\t\t\t}\n\t\t\t\tm_Choice2.Init();\n\t\t\t\tm_HighCoder.Init();\n\t\t\t}\n\n\t\t\tpublic uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)\n\t\t\t{\n\t\t\t\tif (m_Choice.Decode(rangeDecoder) == 0)\n\t\t\t\t\treturn m_LowCoder[posState].Decode(rangeDecoder);\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tuint symbol = Base.kNumLowLenSymbols;\n\t\t\t\t\tif (m_Choice2.Decode(rangeDecoder) == 0)\n\t\t\t\t\t\tsymbol += m_MidCoder[posState].Decode(rangeDecoder);\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsymbol += Base.kNumMidLenSymbols;\n\t\t\t\t\t\tsymbol += m_HighCoder.Decode(rangeDecoder);\n\t\t\t\t\t}\n\t\t\t\t\treturn symbol;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tclass LiteralDecoder\n\t\t{\n\t\t\tstruct Decoder2\n\t\t\t{\n\t\t\t\tBitDecoder[] m_Decoders;\n\t\t\t\tpublic void Create() { m_Decoders = new BitDecoder[0x300]; }\n\t\t\t\tpublic void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }\n\n\t\t\t\tpublic byte DecodeNormal(RangeCoder.Decoder rangeDecoder)\n\t\t\t\t{\n\t\t\t\t\tuint symbol = 1;\n\t\t\t\t\tdo\n\t\t\t\t\t\tsymbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);\n\t\t\t\t\twhile (symbol < 0x100);\n\t\t\t\t\treturn (byte)symbol;\n\t\t\t\t}\n\n\t\t\t\tpublic byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)\n\t\t\t\t{\n\t\t\t\t\tuint symbol = 1;\n\t\t\t\t\tdo\n\t\t\t\t\t{\n\t\t\t\t\t\tuint matchBit = (uint)(matchByte >> 7) & 1;\n\t\t\t\t\t\tmatchByte <<= 1;\n\t\t\t\t\t\tuint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);\n\t\t\t\t\t\tsymbol = (symbol << 1) | bit;\n\t\t\t\t\t\tif (matchBit != bit)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twhile (symbol < 0x100)\n\t\t\t\t\t\t\t\tsymbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twhile (symbol < 0x100);\n\t\t\t\t\treturn (byte)symbol;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tDecoder2[] m_Coders;\n\t\t\tint m_NumPrevBits;\n\t\t\tint m_NumPosBits;\n\t\t\tuint m_PosMask;\n\n\t\t\tpublic void Create(int numPosBits, int numPrevBits)\n\t\t\t{\n\t\t\t\tif (m_Coders != null && m_NumPrevBits == numPrevBits &&\n\t\t\t\t\tm_NumPosBits == numPosBits)\n\t\t\t\t\treturn;\n\t\t\t\tm_NumPosBits = numPosBits;\n\t\t\t\tm_PosMask = ((uint)1 << numPosBits) - 1;\n\t\t\t\tm_NumPrevBits = numPrevBits;\n\t\t\t\tuint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);\n\t\t\t\tm_Coders = new Decoder2[numStates];\n\t\t\t\tfor (uint i = 0; i < numStates; i++)\n\t\t\t\t\tm_Coders[i].Create();\n\t\t\t}\n\n\t\t\tpublic void Init()\n\t\t\t{\n\t\t\t\tuint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);\n\t\t\t\tfor (uint i = 0; i < numStates; i++)\n\t\t\t\t\tm_Coders[i].Init();\n\t\t\t}\n\n\t\t\tuint GetState(uint pos, byte prevByte)\n\t\t\t{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }\n\n\t\t\tpublic byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)\n\t\t\t{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }\n\n\t\t\tpublic byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)\n\t\t\t{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }\n\t\t};\n\n\t\tLZ.OutWindow m_OutWindow = new LZ.OutWindow();\n\t\tRangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();\n\n\t\tBitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];\n\t\tBitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];\n\t\tBitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];\n\t\tBitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];\n\t\tBitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];\n\t\tBitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];\n\n\t\tBitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];\n\t\tBitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];\n\n\t\tBitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);\n\n\t\tLenDecoder m_LenDecoder = new LenDecoder();\n\t\tLenDecoder m_RepLenDecoder = new LenDecoder();\n\n\t\tLiteralDecoder m_LiteralDecoder = new LiteralDecoder();\n\n\t\tuint m_DictionarySize;\n\t\tuint m_DictionarySizeCheck;\n\n\t\tuint m_PosStateMask;\n\n\t\tpublic Decoder()\n\t\t{\n\t\t\tm_DictionarySize = 0xFFFFFFFF;\n\t\t\tfor (int i = 0; i < Base.kNumLenToPosStates; i++)\n\t\t\t\tm_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);\n\t\t}\n\n\t\tvoid SetDictionarySize(uint dictionarySize)\n\t\t{\n\t\t\tif (m_DictionarySize != dictionarySize)\n\t\t\t{\n\t\t\t\tm_DictionarySize = dictionarySize;\n\t\t\t\tm_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);\n\t\t\t\tuint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));\n\t\t\t\tm_OutWindow.Create(blockSize);\n\t\t\t}\n\t\t}\n\n\t\tvoid SetLiteralProperties(int lp, int lc)\n\t\t{\n\t\t\tif (lp > 8)\n\t\t\t\tthrow new InvalidParamException();\n\t\t\tif (lc > 8)\n\t\t\t\tthrow new InvalidParamException();\n\t\t\tm_LiteralDecoder.Create(lp, lc);\n\t\t}\n\n\t\tvoid SetPosBitsProperties(int pb)\n\t\t{\n\t\t\tif (pb > Base.kNumPosStatesBitsMax)\n\t\t\t\tthrow new InvalidParamException();\n\t\t\tuint numPosStates = (uint)1 << pb;\n\t\t\tm_LenDecoder.Create(numPosStates);\n\t\t\tm_RepLenDecoder.Create(numPosStates);\n\t\t\tm_PosStateMask = numPosStates - 1;\n\t\t}\n\n\t\tbool _solid = false;\n\t\tvoid Init(System.IO.Stream inStream, System.IO.Stream outStream)\n\t\t{\n\t\t\tm_RangeDecoder.Init(inStream);\n\t\t\tm_OutWindow.Init(outStream, _solid);\n\n\t\t\tuint i;\n\t\t\tfor (i = 0; i < Base.kNumStates; i++)\n\t\t\t{\n\t\t\t\tfor (uint j = 0; j <= m_PosStateMask; j++)\n\t\t\t\t{\n\t\t\t\t\tuint index = (i << Base.kNumPosStatesBitsMax) + j;\n\t\t\t\t\tm_IsMatchDecoders[index].Init();\n\t\t\t\t\tm_IsRep0LongDecoders[index].Init();\n\t\t\t\t}\n\t\t\t\tm_IsRepDecoders[i].Init();\n\t\t\t\tm_IsRepG0Decoders[i].Init();\n\t\t\t\tm_IsRepG1Decoders[i].Init();\n\t\t\t\tm_IsRepG2Decoders[i].Init();\n\t\t\t}\n\n\t\t\tm_LiteralDecoder.Init();\n\t\t\tfor (i = 0; i < Base.kNumLenToPosStates; i++)\n\t\t\t\tm_PosSlotDecoder[i].Init();\n\t\t\t// m_PosSpecDecoder.Init();\n\t\t\tfor (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)\n\t\t\t\tm_PosDecoders[i].Init();\n\n\t\t\tm_LenDecoder.Init();\n\t\t\tm_RepLenDecoder.Init();\n\t\t\tm_PosAlignDecoder.Init();\n\t\t}\n\n\t\tpublic void Code(System.IO.Stream inStream, System.IO.Stream outStream,\n\t\t\tInt64 inSize, Int64 outSize, ICodeProgress progress)\n\t\t{\n\t\t\tInit(inStream, outStream);\n\n\t\t\tBase.State state = new Base.State();\n\t\t\tstate.Init();\n\t\t\tuint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;\n\n\t\t\tUInt64 nowPos64 = 0;\n\t\t\tUInt64 outSize64 = (UInt64)outSize;\n\t\t\tif (nowPos64 < outSize64)\n\t\t\t{\n\t\t\t\tif (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)\n\t\t\t\t\tthrow new DataErrorException();\n\t\t\t\tstate.UpdateChar();\n\t\t\t\tbyte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);\n\t\t\t\tm_OutWindow.PutByte(b);\n\t\t\t\tnowPos64++;\n\t\t\t}\n\t\t\twhile (nowPos64 < outSize64)\n\t\t\t{\n\t\t\t\t// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);\n\t\t\t\t\t// while(nowPos64 < next)\n\t\t\t\t{\n\t\t\t\t\tuint posState = (uint)nowPos64 & m_PosStateMask;\n\t\t\t\t\tif (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tbyte b;\n\t\t\t\t\t\tbyte prevByte = m_OutWindow.GetByte(0);\n\t\t\t\t\t\tif (!state.IsCharState())\n\t\t\t\t\t\t\tb = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,\n\t\t\t\t\t\t\t\t(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tb = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);\n\t\t\t\t\t\tm_OutWindow.PutByte(b);\n\t\t\t\t\t\tstate.UpdateChar();\n\t\t\t\t\t\tnowPos64++;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tuint len;\n\t\t\t\t\t\tif (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstate.UpdateShortRep();\n\t\t\t\t\t\t\t\t\tm_OutWindow.PutByte(m_OutWindow.GetByte(rep0));\n\t\t\t\t\t\t\t\t\tnowPos64++;\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tUInt32 distance;\n\t\t\t\t\t\t\t\tif (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdistance = rep1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)\n\t\t\t\t\t\t\t\t\t\tdistance = rep2;\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdistance = rep3;\n\t\t\t\t\t\t\t\t\t\trep3 = rep2;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\trep2 = rep1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trep1 = rep0;\n\t\t\t\t\t\t\t\trep0 = distance;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlen = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;\n\t\t\t\t\t\t\tstate.UpdateRep();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trep3 = rep2;\n\t\t\t\t\t\t\trep2 = rep1;\n\t\t\t\t\t\t\trep1 = rep0;\n\t\t\t\t\t\t\tlen = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);\n\t\t\t\t\t\t\tstate.UpdateMatch();\n\t\t\t\t\t\t\tuint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);\n\t\t\t\t\t\t\tif (posSlot >= Base.kStartPosModelIndex)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint numDirectBits = (int)((posSlot >> 1) - 1);\n\t\t\t\t\t\t\t\trep0 = ((2 | (posSlot & 1)) << numDirectBits);\n\t\t\t\t\t\t\t\tif (posSlot < Base.kEndPosModelIndex)\n\t\t\t\t\t\t\t\t\trep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,\n\t\t\t\t\t\t\t\t\t\t\trep0 - posSlot - 1, m_RangeDecoder, numDirectBits);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\trep0 += (m_RangeDecoder.DecodeDirectBits(\n\t\t\t\t\t\t\t\t\t\tnumDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);\n\t\t\t\t\t\t\t\t\trep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\trep0 = posSlot;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (rep0 == 0xFFFFFFFF)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tthrow new DataErrorException();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_OutWindow.CopyBlock(rep0, len);\n\t\t\t\t\t\tnowPos64 += len;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_OutWindow.Flush();\n\t\t\tm_OutWindow.ReleaseStream();\n\t\t\tm_RangeDecoder.ReleaseStream();\n\t\t}\n\n\t\tpublic void SetDecoderProperties(byte[] properties)\n\t\t{\n\t\t\tif (properties.Length < 5)\n\t\t\t\tthrow new InvalidParamException();\n\t\t\tint lc = properties[0] % 9;\n\t\t\tint remainder = properties[0] / 9;\n\t\t\tint lp = remainder % 5;\n\t\t\tint pb = remainder / 5;\n\t\t\tif (pb > Base.kNumPosStatesBitsMax)\n\t\t\t\tthrow new InvalidParamException();\n\t\t\tUInt32 dictionarySize = 0;\n\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\tdictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);\n\t\t\tSetDictionarySize(dictionarySize);\n\t\t\tSetLiteralProperties(lp, lc);\n\t\t\tSetPosBitsProperties(pb);\n\t\t}\n\n\t\tpublic bool Train(System.IO.Stream stream)\n\t\t{\n\t\t\t_solid = true;\n\t\t\treturn m_OutWindow.Train(stream);\n\t\t}\n\n\t\t/*\n\t\tpublic override bool CanRead { get { return true; }}\n\t\tpublic override bool CanWrite { get { return true; }}\n\t\tpublic override bool CanSeek { get { return true; }}\n\t\tpublic override long Length { get { return 0; }}\n\t\tpublic override long Position\n\t\t{\n\t\t\tget { return 0;\t}\n\t\t\tset { }\n\t\t}\n\t\tpublic override void Flush() { }\n\t\tpublic override int Read(byte[] buffer, int offset, int count) \n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tpublic override void Write(byte[] buffer, int offset, int count)\n\t\t{\n\t\t}\n\t\tpublic override long Seek(long offset, System.IO.SeekOrigin origin)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tpublic override void SetLength(long value) {}\n\t\t*/\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/LZMA/LzmaEncoder.cs",
    "content": "// LzmaEncoder.cs\n\nusing System;\n\nnamespace SevenZip.Compression.LZMA\n{\n\tusing RangeCoder;\n\n\tpublic class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties\n\t{\n\t\tenum EMatchFinderType\n\t\t{\n\t\t\tBT2,\n\t\t\tBT4,\n\t\t};\n\n\t\tconst UInt32 kIfinityPrice = 0xFFFFFFF;\n\n\t\tstatic Byte[] g_FastPos = new Byte[1 << 11];\n\n\t\tstatic Encoder()\n\t\t{\n\t\t\tconst Byte kFastSlots = 22;\n\t\t\tint c = 2;\n\t\t\tg_FastPos[0] = 0;\n\t\t\tg_FastPos[1] = 1;\n\t\t\tfor (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)\n\t\t\t{\n\t\t\t\tUInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1));\n\t\t\t\tfor (UInt32 j = 0; j < k; j++, c++)\n\t\t\t\t\tg_FastPos[c] = slotFast;\n\t\t\t}\n\t\t}\n\n\t\tstatic UInt32 GetPosSlot(UInt32 pos)\n\t\t{\n\t\t\tif (pos < (1 << 11))\n\t\t\t\treturn g_FastPos[pos];\n\t\t\tif (pos < (1 << 21))\n\t\t\t\treturn (UInt32)(g_FastPos[pos >> 10] + 20);\n\t\t\treturn (UInt32)(g_FastPos[pos >> 20] + 40);\n\t\t}\n\n\t\tstatic UInt32 GetPosSlot2(UInt32 pos)\n\t\t{\n\t\t\tif (pos < (1 << 17))\n\t\t\t\treturn (UInt32)(g_FastPos[pos >> 6] + 12);\n\t\t\tif (pos < (1 << 27))\n\t\t\t\treturn (UInt32)(g_FastPos[pos >> 16] + 32);\n\t\t\treturn (UInt32)(g_FastPos[pos >> 26] + 52);\n\t\t}\n\n\t\tBase.State _state = new Base.State();\n\t\tByte _previousByte;\n\t\tUInt32[] _repDistances = new UInt32[Base.kNumRepDistances];\n\n\t\tvoid BaseInit()\n\t\t{\n\t\t\t_state.Init();\n\t\t\t_previousByte = 0;\n\t\t\tfor (UInt32 i = 0; i < Base.kNumRepDistances; i++)\n\t\t\t\t_repDistances[i] = 0;\n\t\t}\n\n\t\tconst int kDefaultDictionaryLogSize = 22;\n\t\tconst UInt32 kNumFastBytesDefault = 0x20;\n\n\t\tclass LiteralEncoder\n\t\t{\n\t\t\tpublic struct Encoder2\n\t\t\t{\n\t\t\t\tBitEncoder[] m_Encoders;\n\n\t\t\t\tpublic void Create() { m_Encoders = new BitEncoder[0x300]; }\n\n\t\t\t\tpublic void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); }\n\n\t\t\t\tpublic void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)\n\t\t\t\t{\n\t\t\t\t\tuint context = 1;\n\t\t\t\t\tfor (int i = 7; i >= 0; i--)\n\t\t\t\t\t{\n\t\t\t\t\t\tuint bit = (uint)((symbol >> i) & 1);\n\t\t\t\t\t\tm_Encoders[context].Encode(rangeEncoder, bit);\n\t\t\t\t\t\tcontext = (context << 1) | bit;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpublic void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)\n\t\t\t\t{\n\t\t\t\t\tuint context = 1;\n\t\t\t\t\tbool same = true;\n\t\t\t\t\tfor (int i = 7; i >= 0; i--)\n\t\t\t\t\t{\n\t\t\t\t\t\tuint bit = (uint)((symbol >> i) & 1);\n\t\t\t\t\t\tuint state = context;\n\t\t\t\t\t\tif (same)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuint matchBit = (uint)((matchByte >> i) & 1);\n\t\t\t\t\t\t\tstate += ((1 + matchBit) << 8);\n\t\t\t\t\t\t\tsame = (matchBit == bit);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_Encoders[state].Encode(rangeEncoder, bit);\n\t\t\t\t\t\tcontext = (context << 1) | bit;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpublic uint GetPrice(bool matchMode, byte matchByte, byte symbol)\n\t\t\t\t{\n\t\t\t\t\tuint price = 0;\n\t\t\t\t\tuint context = 1;\n\t\t\t\t\tint i = 7;\n\t\t\t\t\tif (matchMode)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (; i >= 0; i--)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuint matchBit = (uint)(matchByte >> i) & 1;\n\t\t\t\t\t\t\tuint bit = (uint)(symbol >> i) & 1;\n\t\t\t\t\t\t\tprice += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);\n\t\t\t\t\t\t\tcontext = (context << 1) | bit;\n\t\t\t\t\t\t\tif (matchBit != bit)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ti--;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (; i >= 0; i--)\n\t\t\t\t\t{\n\t\t\t\t\t\tuint bit = (uint)(symbol >> i) & 1;\n\t\t\t\t\t\tprice += m_Encoders[context].GetPrice(bit);\n\t\t\t\t\t\tcontext = (context << 1) | bit;\n\t\t\t\t\t}\n\t\t\t\t\treturn price;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tEncoder2[] m_Coders;\n\t\t\tint m_NumPrevBits;\n\t\t\tint m_NumPosBits;\n\t\t\tuint m_PosMask;\n\n\t\t\tpublic void Create(int numPosBits, int numPrevBits)\n\t\t\t{\n\t\t\t\tif (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)\n\t\t\t\t\treturn;\n\t\t\t\tm_NumPosBits = numPosBits;\n\t\t\t\tm_PosMask = ((uint)1 << numPosBits) - 1;\n\t\t\t\tm_NumPrevBits = numPrevBits;\n\t\t\t\tuint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);\n\t\t\t\tm_Coders = new Encoder2[numStates];\n\t\t\t\tfor (uint i = 0; i < numStates; i++)\n\t\t\t\t\tm_Coders[i].Create();\n\t\t\t}\n\n\t\t\tpublic void Init()\n\t\t\t{\n\t\t\t\tuint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);\n\t\t\t\tfor (uint i = 0; i < numStates; i++)\n\t\t\t\t\tm_Coders[i].Init();\n\t\t\t}\n\n\t\t\tpublic Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)\n\t\t\t{ return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; }\n\t\t}\n\n\t\tclass LenEncoder\n\t\t{\n\t\t\tRangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder();\n\t\t\tRangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder();\n\t\t\tRangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];\n\t\t\tRangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];\n\t\t\tRangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits);\n\n\t\t\tpublic LenEncoder()\n\t\t\t{\n\t\t\t\tfor (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)\n\t\t\t\t{\n\t\t\t\t\t_lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits);\n\t\t\t\t\t_midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic void Init(UInt32 numPosStates)\n\t\t\t{\n\t\t\t\t_choice.Init();\n\t\t\t\t_choice2.Init();\n\t\t\t\tfor (UInt32 posState = 0; posState < numPosStates; posState++)\n\t\t\t\t{\n\t\t\t\t\t_lowCoder[posState].Init();\n\t\t\t\t\t_midCoder[posState].Init();\n\t\t\t\t}\n\t\t\t\t_highCoder.Init();\n\t\t\t}\n\n\t\t\tpublic void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)\n\t\t\t{\n\t\t\t\tif (symbol < Base.kNumLowLenSymbols)\n\t\t\t\t{\n\t\t\t\t\t_choice.Encode(rangeEncoder, 0);\n\t\t\t\t\t_lowCoder[posState].Encode(rangeEncoder, symbol);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsymbol -= Base.kNumLowLenSymbols;\n\t\t\t\t\t_choice.Encode(rangeEncoder, 1);\n\t\t\t\t\tif (symbol < Base.kNumMidLenSymbols)\n\t\t\t\t\t{\n\t\t\t\t\t\t_choice2.Encode(rangeEncoder, 0);\n\t\t\t\t\t\t_midCoder[posState].Encode(rangeEncoder, symbol);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_choice2.Encode(rangeEncoder, 1);\n\t\t\t\t\t\t_highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)\n\t\t\t{\n\t\t\t\tUInt32 a0 = _choice.GetPrice0();\n\t\t\t\tUInt32 a1 = _choice.GetPrice1();\n\t\t\t\tUInt32 b0 = a1 + _choice2.GetPrice0();\n\t\t\t\tUInt32 b1 = a1 + _choice2.GetPrice1();\n\t\t\t\tUInt32 i = 0;\n\t\t\t\tfor (i = 0; i < Base.kNumLowLenSymbols; i++)\n\t\t\t\t{\n\t\t\t\t\tif (i >= numSymbols)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tprices[st + i] = a0 + _lowCoder[posState].GetPrice(i);\n\t\t\t\t}\n\t\t\t\tfor (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)\n\t\t\t\t{\n\t\t\t\t\tif (i >= numSymbols)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tprices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);\n\t\t\t\t}\n\t\t\t\tfor (; i < numSymbols; i++)\n\t\t\t\t\tprices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);\n\t\t\t}\n\t\t};\n\n\t\tconst UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;\n\n\t\tclass LenPriceTableEncoder : LenEncoder\n\t\t{\n\t\t\tUInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];\n\t\t\tUInt32 _tableSize;\n\t\t\tUInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];\n\n\t\t\tpublic void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }\n\n\t\t\tpublic UInt32 GetPrice(UInt32 symbol, UInt32 posState)\n\t\t\t{\n\t\t\t\treturn _prices[posState * Base.kNumLenSymbols + symbol];\n\t\t\t}\n\n\t\t\tvoid UpdateTable(UInt32 posState)\n\t\t\t{\n\t\t\t\tSetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);\n\t\t\t\t_counters[posState] = _tableSize;\n\t\t\t}\n\n\t\t\tpublic void UpdateTables(UInt32 numPosStates)\n\t\t\t{\n\t\t\t\tfor (UInt32 posState = 0; posState < numPosStates; posState++)\n\t\t\t\t\tUpdateTable(posState);\n\t\t\t}\n\n\t\t\tpublic new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)\n\t\t\t{\n\t\t\t\tbase.Encode(rangeEncoder, symbol, posState);\n\t\t\t\tif (--_counters[posState] == 0)\n\t\t\t\t\tUpdateTable(posState);\n\t\t\t}\n\t\t}\n\n\t\tconst UInt32 kNumOpts = 1 << 12;\n\t\tclass Optimal\n\t\t{\n\t\t\tpublic Base.State State;\n\n\t\t\tpublic bool Prev1IsChar;\n\t\t\tpublic bool Prev2;\n\n\t\t\tpublic UInt32 PosPrev2;\n\t\t\tpublic UInt32 BackPrev2;\n\n\t\t\tpublic UInt32 Price;\n\t\t\tpublic UInt32 PosPrev;\n\t\t\tpublic UInt32 BackPrev;\n\n\t\t\tpublic UInt32 Backs0;\n\t\t\tpublic UInt32 Backs1;\n\t\t\tpublic UInt32 Backs2;\n\t\t\tpublic UInt32 Backs3;\n\n\t\t\tpublic void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }\n\t\t\tpublic void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }\n\t\t\tpublic bool IsShortRep() { return (BackPrev == 0); }\n\t\t};\n\t\tOptimal[] _optimum = new Optimal[kNumOpts];\n\t\tLZ.IMatchFinder _matchFinder = null;\n\t\tRangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();\n\n\t\tRangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];\n\t\tRangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates];\n\t\tRangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates];\n\t\tRangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates];\n\t\tRangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates];\n\t\tRangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];\n\n\t\tRangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates];\n\t\t\n\t\tRangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];\n\t\tRangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits);\n\n\t\tLenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();\n\t\tLenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();\n\n\t\tLiteralEncoder _literalEncoder = new LiteralEncoder();\n\n\t\tUInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2];\n\t\t\n\t\tUInt32 _numFastBytes = kNumFastBytesDefault;\n\t\tUInt32 _longestMatchLength;\n\t\tUInt32 _numDistancePairs;\n\n\t\tUInt32 _additionalOffset;\n\n\t\tUInt32 _optimumEndIndex;\n\t\tUInt32 _optimumCurrentIndex;\n\n\t\tbool _longestMatchWasFound;\n\n\t\tUInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];\n\t\tUInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];\n\t\tUInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];\n\t\tUInt32 _alignPriceCount;\n\n\t\tUInt32 _distTableSize = (kDefaultDictionaryLogSize * 2);\n\n\t\tint _posStateBits = 2;\n\t\tUInt32 _posStateMask = (4 - 1);\n\t\tint _numLiteralPosStateBits = 0;\n\t\tint _numLiteralContextBits = 3;\n\n\t\tUInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize);\n\t\tUInt32 _dictionarySizePrev = 0xFFFFFFFF;\n\t\tUInt32 _numFastBytesPrev = 0xFFFFFFFF;\n\n\t\tInt64 nowPos64;\n\t\tbool _finished;\n\t\tSystem.IO.Stream _inStream;\n\n\t\tEMatchFinderType _matchFinderType = EMatchFinderType.BT4;\n\t\tbool _writeEndMark = false;\n\t\t\n\t\tbool _needReleaseMFStream;\n\n\t\tvoid Create()\n\t\t{\n\t\t\tif (_matchFinder == null)\n\t\t\t{\n\t\t\t\tLZ.BinTree bt = new LZ.BinTree();\n\t\t\t\tint numHashBytes = 4;\n\t\t\t\tif (_matchFinderType == EMatchFinderType.BT2)\n\t\t\t\t\tnumHashBytes = 2;\n\t\t\t\tbt.SetType(numHashBytes);\n\t\t\t\t_matchFinder = bt;\n\t\t\t}\n\t\t\t_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);\n\n\t\t\tif (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)\n\t\t\t\treturn;\n\t\t\t_matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);\n\t\t\t_dictionarySizePrev = _dictionarySize;\n\t\t\t_numFastBytesPrev = _numFastBytes;\n\t\t}\n\n\t\tpublic Encoder()\n\t\t{\n\t\t\tfor (int i = 0; i < kNumOpts; i++)\n\t\t\t\t_optimum[i] = new Optimal();\n\t\t\tfor (int i = 0; i < Base.kNumLenToPosStates; i++)\n\t\t\t\t_posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits);\n\t\t}\n\n\t\tvoid SetWriteEndMarkerMode(bool writeEndMarker)\n\t\t{\n\t\t\t_writeEndMark = writeEndMarker;\n\t\t}\n\n\t\tvoid Init()\n\t\t{\n\t\t\tBaseInit();\n\t\t\t_rangeEncoder.Init();\n\n\t\t\tuint i;\n\t\t\tfor (i = 0; i < Base.kNumStates; i++)\n\t\t\t{\n\t\t\t\tfor (uint j = 0; j <= _posStateMask; j++)\n\t\t\t\t{\n\t\t\t\t\tuint complexState = (i << Base.kNumPosStatesBitsMax) + j;\n\t\t\t\t\t_isMatch[complexState].Init();\n\t\t\t\t\t_isRep0Long[complexState].Init();\n\t\t\t\t}\n\t\t\t\t_isRep[i].Init();\n\t\t\t\t_isRepG0[i].Init();\n\t\t\t\t_isRepG1[i].Init();\n\t\t\t\t_isRepG2[i].Init();\n\t\t\t}\n\t\t\t_literalEncoder.Init();\n\t\t\tfor (i = 0; i < Base.kNumLenToPosStates; i++)\n\t\t\t\t_posSlotEncoder[i].Init();\n\t\t\tfor (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)\n\t\t\t\t_posEncoders[i].Init();\n\n\t\t\t_lenEncoder.Init((UInt32)1 << _posStateBits);\n\t\t\t_repMatchLenEncoder.Init((UInt32)1 << _posStateBits);\n\n\t\t\t_posAlignEncoder.Init();\n\n\t\t\t_longestMatchWasFound = false;\n\t\t\t_optimumEndIndex = 0;\n\t\t\t_optimumCurrentIndex = 0;\n\t\t\t_additionalOffset = 0;\n\t\t}\n\n\t\tvoid ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)\n\t\t{\n\t\t\tlenRes = 0;\n\t\t\tnumDistancePairs = _matchFinder.GetMatches(_matchDistances);\n\t\t\tif (numDistancePairs > 0)\n\t\t\t{\n\t\t\t\tlenRes = _matchDistances[numDistancePairs - 2];\n\t\t\t\tif (lenRes == _numFastBytes)\n\t\t\t\t\tlenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],\n\t\t\t\t\t\tBase.kMatchMaxLen - lenRes);\n\t\t\t}\n\t\t\t_additionalOffset++;\n\t\t}\n\n\n\t\tvoid MovePos(UInt32 num)\n\t\t{\n\t\t\tif (num > 0)\n\t\t\t{\n\t\t\t\t_matchFinder.Skip(num);\n\t\t\t\t_additionalOffset += num;\n\t\t\t}\n\t\t}\n\n\t\tUInt32 GetRepLen1Price(Base.State state, UInt32 posState)\n\t\t{\n\t\t\treturn _isRepG0[state.Index].GetPrice0() +\n\t\t\t\t\t_isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();\n\t\t}\n\n\t\tUInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)\n\t\t{\n\t\t\tUInt32 price;\n\t\t\tif (repIndex == 0)\n\t\t\t{\n\t\t\t\tprice = _isRepG0[state.Index].GetPrice0();\n\t\t\t\tprice += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tprice = _isRepG0[state.Index].GetPrice1();\n\t\t\t\tif (repIndex == 1)\n\t\t\t\t\tprice += _isRepG1[state.Index].GetPrice0();\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tprice += _isRepG1[state.Index].GetPrice1();\n\t\t\t\t\tprice += _isRepG2[state.Index].GetPrice(repIndex - 2);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn price;\n\t\t}\n\n\t\tUInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)\n\t\t{\n\t\t\tUInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);\n\t\t\treturn price + GetPureRepPrice(repIndex, state, posState);\n\t\t}\n\t\n\t\tUInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)\n\t\t{\n\t\t\tUInt32 price;\n\t\t\tUInt32 lenToPosState = Base.GetLenToPosState(len);\n\t\t\tif (pos < Base.kNumFullDistances)\n\t\t\t\tprice = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];\n\t\t\telse\n\t\t\t\tprice = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +\n\t\t\t\t\t_alignPrices[pos & Base.kAlignMask];\n\t\t\treturn price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);\n\t\t}\n\n\t\tUInt32 Backward(out UInt32 backRes, UInt32 cur)\n\t\t{\n\t\t\t_optimumEndIndex = cur;\n\t\t\tUInt32 posMem = _optimum[cur].PosPrev;\n\t\t\tUInt32 backMem = _optimum[cur].BackPrev;\n\t\t\tdo\n\t\t\t{\n\t\t\t\tif (_optimum[cur].Prev1IsChar)\n\t\t\t\t{\n\t\t\t\t\t_optimum[posMem].MakeAsChar();\n\t\t\t\t\t_optimum[posMem].PosPrev = posMem - 1;\n\t\t\t\t\tif (_optimum[cur].Prev2)\n\t\t\t\t\t{\n\t\t\t\t\t\t_optimum[posMem - 1].Prev1IsChar = false;\n\t\t\t\t\t\t_optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;\n\t\t\t\t\t\t_optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tUInt32 posPrev = posMem;\n\t\t\t\tUInt32 backCur = backMem;\n\n\t\t\t\tbackMem = _optimum[posPrev].BackPrev;\n\t\t\t\tposMem = _optimum[posPrev].PosPrev;\n\n\t\t\t\t_optimum[posPrev].BackPrev = backCur;\n\t\t\t\t_optimum[posPrev].PosPrev = cur;\n\t\t\t\tcur = posPrev;\n\t\t\t}\n\t\t\twhile (cur > 0);\n\t\t\tbackRes = _optimum[0].BackPrev;\n\t\t\t_optimumCurrentIndex = _optimum[0].PosPrev;\n\t\t\treturn _optimumCurrentIndex;\n\t\t}\n\n\t\tUInt32[] reps = new UInt32[Base.kNumRepDistances];\n\t\tUInt32[] repLens = new UInt32[Base.kNumRepDistances];\n\n\n\t\tUInt32 GetOptimum(UInt32 position, out UInt32 backRes)\n\t\t{\n\t\t\tif (_optimumEndIndex != _optimumCurrentIndex)\n\t\t\t{\n\t\t\t\tUInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;\n\t\t\t\tbackRes = _optimum[_optimumCurrentIndex].BackPrev;\n\t\t\t\t_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;\n\t\t\t\treturn lenRes;\n\t\t\t}\n\t\t\t_optimumCurrentIndex = _optimumEndIndex = 0;\n\n\t\t\tUInt32 lenMain, numDistancePairs;\n\t\t\tif (!_longestMatchWasFound)\n\t\t\t{\n\t\t\t\tReadMatchDistances(out lenMain, out numDistancePairs);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlenMain = _longestMatchLength;\n\t\t\t\tnumDistancePairs = _numDistancePairs;\n\t\t\t\t_longestMatchWasFound = false;\n\t\t\t}\n\n\t\t\tUInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;\n\t\t\tif (numAvailableBytes < 2)\n\t\t\t{\n\t\t\t\tbackRes = 0xFFFFFFFF;\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tif (numAvailableBytes > Base.kMatchMaxLen)\n\t\t\t\tnumAvailableBytes = Base.kMatchMaxLen;\n\n\t\t\tUInt32 repMaxIndex = 0;\n\t\t\tUInt32 i;\t\t\t\n\t\t\tfor (i = 0; i < Base.kNumRepDistances; i++)\n\t\t\t{\n\t\t\t\treps[i] = _repDistances[i];\n\t\t\t\trepLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);\n\t\t\t\tif (repLens[i] > repLens[repMaxIndex])\n\t\t\t\t\trepMaxIndex = i;\n\t\t\t}\n\t\t\tif (repLens[repMaxIndex] >= _numFastBytes)\n\t\t\t{\n\t\t\t\tbackRes = repMaxIndex;\n\t\t\t\tUInt32 lenRes = repLens[repMaxIndex];\n\t\t\t\tMovePos(lenRes - 1);\n\t\t\t\treturn lenRes;\n\t\t\t}\n\n\t\t\tif (lenMain >= _numFastBytes)\n\t\t\t{\n\t\t\t\tbackRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;\n\t\t\t\tMovePos(lenMain - 1);\n\t\t\t\treturn lenMain;\n\t\t\t}\n\t\t\t\n\t\t\tByte currentByte = _matchFinder.GetIndexByte(0 - 1);\n\t\t\tByte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));\n\n\t\t\tif (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)\n\t\t\t{\n\t\t\t\tbackRes = (UInt32)0xFFFFFFFF;\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t_optimum[0].State = _state;\n\n\t\t\tUInt32 posState = (position & _posStateMask);\n\n\t\t\t_optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +\n\t\t\t\t\t_literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);\n\t\t\t_optimum[1].MakeAsChar();\n\n\t\t\tUInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();\n\t\t\tUInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();\n\n\t\t\tif (matchByte == currentByte)\n\t\t\t{\n\t\t\t\tUInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);\n\t\t\t\tif (shortRepPrice < _optimum[1].Price)\n\t\t\t\t{\n\t\t\t\t\t_optimum[1].Price = shortRepPrice;\n\t\t\t\t\t_optimum[1].MakeAsShortRep();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tUInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);\n\n\t\t\tif(lenEnd < 2)\n\t\t\t{\n\t\t\t\tbackRes = _optimum[1].BackPrev;\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\t\n\t\t\t_optimum[1].PosPrev = 0;\n\n\t\t\t_optimum[0].Backs0 = reps[0];\n\t\t\t_optimum[0].Backs1 = reps[1];\n\t\t\t_optimum[0].Backs2 = reps[2];\n\t\t\t_optimum[0].Backs3 = reps[3];\n\n\t\t\tUInt32 len = lenEnd;\n\t\t\tdo\n\t\t\t\t_optimum[len--].Price = kIfinityPrice;\n\t\t\twhile (len >= 2);\n\n\t\t\tfor (i = 0; i < Base.kNumRepDistances; i++)\n\t\t\t{\n\t\t\t\tUInt32 repLen = repLens[i];\n\t\t\t\tif (repLen < 2)\n\t\t\t\t\tcontinue;\n\t\t\t\tUInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\tUInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);\n\t\t\t\t\tOptimal optimum = _optimum[repLen];\n\t\t\t\t\tif (curAndLenPrice < optimum.Price)\n\t\t\t\t\t{\n\t\t\t\t\t\toptimum.Price = curAndLenPrice;\n\t\t\t\t\t\toptimum.PosPrev = 0;\n\t\t\t\t\t\toptimum.BackPrev = i;\n\t\t\t\t\t\toptimum.Prev1IsChar = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\twhile (--repLen >= 2);\n\t\t\t}\n\n\t\t\tUInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();\n\t\t\t\n\t\t\tlen = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);\n\t\t\tif (len <= lenMain)\n\t\t\t{\n\t\t\t\tUInt32 offs = 0;\n\t\t\t\twhile (len > _matchDistances[offs])\n\t\t\t\t\toffs += 2;\n\t\t\t\tfor (; ; len++)\n\t\t\t\t{\n\t\t\t\t\tUInt32 distance = _matchDistances[offs + 1];\n\t\t\t\t\tUInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);\n\t\t\t\t\tOptimal optimum = _optimum[len];\n\t\t\t\t\tif (curAndLenPrice < optimum.Price)\n\t\t\t\t\t{\n\t\t\t\t\t\toptimum.Price = curAndLenPrice;\n\t\t\t\t\t\toptimum.PosPrev = 0;\n\t\t\t\t\t\toptimum.BackPrev = distance + Base.kNumRepDistances;\n\t\t\t\t\t\toptimum.Prev1IsChar = false;\n\t\t\t\t\t}\n\t\t\t\t\tif (len == _matchDistances[offs])\n\t\t\t\t\t{\n\t\t\t\t\t\toffs += 2;\n\t\t\t\t\t\tif (offs == numDistancePairs)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tUInt32 cur = 0;\n\n\t\t\twhile (true)\n\t\t\t{\n\t\t\t\tcur++;\n\t\t\t\tif (cur == lenEnd)\n\t\t\t\t\treturn Backward(out backRes, cur);\n\t\t\t\tUInt32 newLen;\n\t\t\t\tReadMatchDistances(out newLen, out numDistancePairs);\n\t\t\t\tif (newLen >= _numFastBytes)\n\t\t\t\t{\n\t\t\t\t\t_numDistancePairs = numDistancePairs;\n\t\t\t\t\t_longestMatchLength = newLen;\n\t\t\t\t\t_longestMatchWasFound = true;\n\t\t\t\t\treturn Backward(out backRes, cur);\n\t\t\t\t}\n\t\t\t\tposition++;\n\t\t\t\tUInt32 posPrev = _optimum[cur].PosPrev;\n\t\t\t\tBase.State state;\n\t\t\t\tif (_optimum[cur].Prev1IsChar)\n\t\t\t\t{\n\t\t\t\t\tposPrev--;\n\t\t\t\t\tif (_optimum[cur].Prev2)\n\t\t\t\t\t{\n\t\t\t\t\t\tstate = _optimum[_optimum[cur].PosPrev2].State;\n\t\t\t\t\t\tif (_optimum[cur].BackPrev2 < Base.kNumRepDistances)\n\t\t\t\t\t\t\tstate.UpdateRep();\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tstate.UpdateMatch();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tstate = _optimum[posPrev].State;\n\t\t\t\t\tstate.UpdateChar();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tstate = _optimum[posPrev].State;\n\t\t\t\tif (posPrev == cur - 1)\n\t\t\t\t{\n\t\t\t\t\tif (_optimum[cur].IsShortRep())\n\t\t\t\t\t\tstate.UpdateShortRep();\n\t\t\t\t\telse\n\t\t\t\t\t\tstate.UpdateChar();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tUInt32 pos;\n\t\t\t\t\tif (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)\n\t\t\t\t\t{\n\t\t\t\t\t\tposPrev = _optimum[cur].PosPrev2;\n\t\t\t\t\t\tpos = _optimum[cur].BackPrev2;\n\t\t\t\t\t\tstate.UpdateRep();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpos = _optimum[cur].BackPrev;\n\t\t\t\t\t\tif (pos < Base.kNumRepDistances)\n\t\t\t\t\t\t\tstate.UpdateRep();\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tstate.UpdateMatch();\n\t\t\t\t\t}\n\t\t\t\t\tOptimal opt = _optimum[posPrev];\n\t\t\t\t\tif (pos < Base.kNumRepDistances)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (pos == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treps[0] = opt.Backs0;\n\t\t\t\t\t\t\treps[1] = opt.Backs1;\n\t\t\t\t\t\t\treps[2] = opt.Backs2;\n\t\t\t\t\t\t\treps[3] = opt.Backs3;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (pos == 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treps[0] = opt.Backs1;\n\t\t\t\t\t\t\treps[1] = opt.Backs0;\n\t\t\t\t\t\t\treps[2] = opt.Backs2;\n\t\t\t\t\t\t\treps[3] = opt.Backs3;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (pos == 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treps[0] = opt.Backs2;\n\t\t\t\t\t\t\treps[1] = opt.Backs0;\n\t\t\t\t\t\t\treps[2] = opt.Backs1;\n\t\t\t\t\t\t\treps[3] = opt.Backs3;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treps[0] = opt.Backs3;\n\t\t\t\t\t\t\treps[1] = opt.Backs0;\n\t\t\t\t\t\t\treps[2] = opt.Backs1;\n\t\t\t\t\t\t\treps[3] = opt.Backs2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treps[0] = (pos - Base.kNumRepDistances);\n\t\t\t\t\t\treps[1] = opt.Backs0;\n\t\t\t\t\t\treps[2] = opt.Backs1;\n\t\t\t\t\t\treps[3] = opt.Backs2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_optimum[cur].State = state;\n\t\t\t\t_optimum[cur].Backs0 = reps[0];\n\t\t\t\t_optimum[cur].Backs1 = reps[1];\n\t\t\t\t_optimum[cur].Backs2 = reps[2];\n\t\t\t\t_optimum[cur].Backs3 = reps[3];\n\t\t\t\tUInt32 curPrice = _optimum[cur].Price;\n\n\t\t\t\tcurrentByte = _matchFinder.GetIndexByte(0 - 1);\n\t\t\t\tmatchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));\n\n\t\t\t\tposState = (position & _posStateMask);\n\n\t\t\t\tUInt32 curAnd1Price = curPrice +\n\t\t\t\t\t_isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +\n\t\t\t\t\t_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).\n\t\t\t\t\tGetPrice(!state.IsCharState(), matchByte, currentByte);\n\n\t\t\t\tOptimal nextOptimum = _optimum[cur + 1];\n\n\t\t\t\tbool nextIsChar = false;\n\t\t\t\tif (curAnd1Price < nextOptimum.Price)\n\t\t\t\t{\n\t\t\t\t\tnextOptimum.Price = curAnd1Price;\n\t\t\t\t\tnextOptimum.PosPrev = cur;\n\t\t\t\t\tnextOptimum.MakeAsChar();\n\t\t\t\t\tnextIsChar = true;\n\t\t\t\t}\n\n\t\t\t\tmatchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();\n\t\t\t\trepMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();\n\n\t\t\t\tif (matchByte == currentByte &&\n\t\t\t\t\t!(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))\n\t\t\t\t{\n\t\t\t\t\tUInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);\n\t\t\t\t\tif (shortRepPrice <= nextOptimum.Price)\n\t\t\t\t\t{\n\t\t\t\t\t\tnextOptimum.Price = shortRepPrice;\n\t\t\t\t\t\tnextOptimum.PosPrev = cur;\n\t\t\t\t\t\tnextOptimum.MakeAsShortRep();\n\t\t\t\t\t\tnextIsChar = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tUInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;\n\t\t\t\tnumAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);\n\t\t\t\tnumAvailableBytes = numAvailableBytesFull;\n\n\t\t\t\tif (numAvailableBytes < 2)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (numAvailableBytes > _numFastBytes)\n\t\t\t\t\tnumAvailableBytes = _numFastBytes;\n\t\t\t\tif (!nextIsChar && matchByte != currentByte)\n\t\t\t\t{\n\t\t\t\t\t// try Literal + rep0\n\t\t\t\t\tUInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);\n\t\t\t\t\tUInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);\n\t\t\t\t\tif (lenTest2 >= 2)\n\t\t\t\t\t{\n\t\t\t\t\t\tBase.State state2 = state;\n\t\t\t\t\t\tstate2.UpdateChar();\n\t\t\t\t\t\tUInt32 posStateNext = (position + 1) & _posStateMask;\n\t\t\t\t\t\tUInt32 nextRepMatchPrice = curAnd1Price +\n\t\t\t\t\t\t\t_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +\n\t\t\t\t\t\t\t_isRep[state2.Index].GetPrice1();\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tUInt32 offset = cur + 1 + lenTest2;\n\t\t\t\t\t\t\twhile (lenEnd < offset)\n\t\t\t\t\t\t\t\t_optimum[++lenEnd].Price = kIfinityPrice;\n\t\t\t\t\t\t\tUInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(\n\t\t\t\t\t\t\t\t0, lenTest2, state2, posStateNext);\n\t\t\t\t\t\t\tOptimal optimum = _optimum[offset];\n\t\t\t\t\t\t\tif (curAndLenPrice < optimum.Price)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\toptimum.Price = curAndLenPrice;\n\t\t\t\t\t\t\t\toptimum.PosPrev = cur + 1;\n\t\t\t\t\t\t\t\toptimum.BackPrev = 0;\n\t\t\t\t\t\t\t\toptimum.Prev1IsChar = true;\n\t\t\t\t\t\t\t\toptimum.Prev2 = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tUInt32 startLen = 2; // speed optimization \n\n\t\t\t\tfor (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)\n\t\t\t\t{\n\t\t\t\t\tUInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);\n\t\t\t\t\tif (lenTest < 2)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tUInt32 lenTestTemp = lenTest;\n\t\t\t\t\tdo\n\t\t\t\t\t{\n\t\t\t\t\t\twhile (lenEnd < cur + lenTest)\n\t\t\t\t\t\t\t_optimum[++lenEnd].Price = kIfinityPrice;\n\t\t\t\t\t\tUInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);\n\t\t\t\t\t\tOptimal optimum = _optimum[cur + lenTest];\n\t\t\t\t\t\tif (curAndLenPrice < optimum.Price)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toptimum.Price = curAndLenPrice;\n\t\t\t\t\t\t\toptimum.PosPrev = cur;\n\t\t\t\t\t\t\toptimum.BackPrev = repIndex;\n\t\t\t\t\t\t\toptimum.Prev1IsChar = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twhile(--lenTest >= 2);\n\t\t\t\t\tlenTest = lenTestTemp;\n\n\t\t\t\t\tif (repIndex == 0)\n\t\t\t\t\t\tstartLen = lenTest + 1;\n\n\t\t\t\t\t// if (_maxMode)\n\t\t\t\t\tif (lenTest < numAvailableBytesFull)\n\t\t\t\t\t{\n\t\t\t\t\t\tUInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);\n\t\t\t\t\t\tUInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t);\n\t\t\t\t\t\tif (lenTest2 >= 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tBase.State state2 = state;\n\t\t\t\t\t\t\tstate2.UpdateRep();\n\t\t\t\t\t\t\tUInt32 posStateNext = (position + lenTest) & _posStateMask;\n\t\t\t\t\t\t\tUInt32 curAndLenCharPrice = \n\t\t\t\t\t\t\t\t\trepMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + \n\t\t\t\t\t\t\t\t\t_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +\n\t\t\t\t\t\t\t\t\t_literalEncoder.GetSubCoder(position + lenTest, \n\t\t\t\t\t\t\t\t\t_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,\n\t\t\t\t\t\t\t\t\t_matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), \n\t\t\t\t\t\t\t\t\t_matchFinder.GetIndexByte((Int32)lenTest - 1));\n\t\t\t\t\t\t\tstate2.UpdateChar();\n\t\t\t\t\t\t\tposStateNext = (position + lenTest + 1) & _posStateMask;\n\t\t\t\t\t\t\tUInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();\n\t\t\t\t\t\t\tUInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// for(; lenTest2 >= 2; lenTest2--)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tUInt32 offset = lenTest + 1 + lenTest2;\n\t\t\t\t\t\t\t\twhile(lenEnd < cur + offset)\n\t\t\t\t\t\t\t\t\t_optimum[++lenEnd].Price = kIfinityPrice;\n\t\t\t\t\t\t\t\tUInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);\n\t\t\t\t\t\t\t\tOptimal optimum = _optimum[cur + offset];\n\t\t\t\t\t\t\t\tif (curAndLenPrice < optimum.Price) \n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\toptimum.Price = curAndLenPrice;\n\t\t\t\t\t\t\t\t\toptimum.PosPrev = cur + lenTest + 1;\n\t\t\t\t\t\t\t\t\toptimum.BackPrev = 0;\n\t\t\t\t\t\t\t\t\toptimum.Prev1IsChar = true;\n\t\t\t\t\t\t\t\t\toptimum.Prev2 = true;\n\t\t\t\t\t\t\t\t\toptimum.PosPrev2 = cur;\n\t\t\t\t\t\t\t\t\toptimum.BackPrev2 = repIndex;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (newLen > numAvailableBytes)\n\t\t\t\t{\n\t\t\t\t\tnewLen = numAvailableBytes;\n\t\t\t\t\tfor (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;\n\t\t\t\t\t_matchDistances[numDistancePairs] = newLen;\n\t\t\t\t\tnumDistancePairs += 2;\n\t\t\t\t}\n\t\t\t\tif (newLen >= startLen)\n\t\t\t\t{\n\t\t\t\t\tnormalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();\n\t\t\t\t\twhile (lenEnd < cur + newLen)\n\t\t\t\t\t\t_optimum[++lenEnd].Price = kIfinityPrice;\n\n\t\t\t\t\tUInt32 offs = 0;\n\t\t\t\t\twhile (startLen > _matchDistances[offs])\n\t\t\t\t\t\toffs += 2;\n\n\t\t\t\t\tfor (UInt32 lenTest = startLen; ; lenTest++)\n\t\t\t\t\t{\n\t\t\t\t\t\tUInt32 curBack = _matchDistances[offs + 1];\n\t\t\t\t\t\tUInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);\n\t\t\t\t\t\tOptimal optimum = _optimum[cur + lenTest];\n\t\t\t\t\t\tif (curAndLenPrice < optimum.Price)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toptimum.Price = curAndLenPrice;\n\t\t\t\t\t\t\toptimum.PosPrev = cur;\n\t\t\t\t\t\t\toptimum.BackPrev = curBack + Base.kNumRepDistances;\n\t\t\t\t\t\t\toptimum.Prev1IsChar = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (lenTest == _matchDistances[offs])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (lenTest < numAvailableBytesFull)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tUInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);\n\t\t\t\t\t\t\t\tUInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);\n\t\t\t\t\t\t\t\tif (lenTest2 >= 2)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tBase.State state2 = state;\n\t\t\t\t\t\t\t\t\tstate2.UpdateMatch();\n\t\t\t\t\t\t\t\t\tUInt32 posStateNext = (position + lenTest) & _posStateMask;\n\t\t\t\t\t\t\t\t\tUInt32 curAndLenCharPrice = curAndLenPrice +\n\t\t\t\t\t\t\t\t\t\t_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +\n\t\t\t\t\t\t\t\t\t\t_literalEncoder.GetSubCoder(position + lenTest,\n\t\t\t\t\t\t\t\t\t\t_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).\n\t\t\t\t\t\t\t\t\t\tGetPrice(true,\n\t\t\t\t\t\t\t\t\t\t_matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1),\n\t\t\t\t\t\t\t\t\t\t_matchFinder.GetIndexByte((Int32)lenTest - 1));\n\t\t\t\t\t\t\t\t\tstate2.UpdateChar();\n\t\t\t\t\t\t\t\t\tposStateNext = (position + lenTest + 1) & _posStateMask;\n\t\t\t\t\t\t\t\t\tUInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();\n\t\t\t\t\t\t\t\t\tUInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();\n\n\t\t\t\t\t\t\t\t\tUInt32 offset = lenTest + 1 + lenTest2;\n\t\t\t\t\t\t\t\t\twhile (lenEnd < cur + offset)\n\t\t\t\t\t\t\t\t\t\t_optimum[++lenEnd].Price = kIfinityPrice;\n\t\t\t\t\t\t\t\t\tcurAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);\n\t\t\t\t\t\t\t\t\toptimum = _optimum[cur + offset];\n\t\t\t\t\t\t\t\t\tif (curAndLenPrice < optimum.Price)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\toptimum.Price = curAndLenPrice;\n\t\t\t\t\t\t\t\t\t\toptimum.PosPrev = cur + lenTest + 1;\n\t\t\t\t\t\t\t\t\t\toptimum.BackPrev = 0;\n\t\t\t\t\t\t\t\t\t\toptimum.Prev1IsChar = true;\n\t\t\t\t\t\t\t\t\t\toptimum.Prev2 = true;\n\t\t\t\t\t\t\t\t\t\toptimum.PosPrev2 = cur;\n\t\t\t\t\t\t\t\t\t\toptimum.BackPrev2 = curBack + Base.kNumRepDistances;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\toffs += 2;\n\t\t\t\t\t\t\tif (offs == numDistancePairs)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbool ChangePair(UInt32 smallDist, UInt32 bigDist)\n\t\t{\n\t\t\tconst int kDif = 7;\n\t\t\treturn (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));\n\t\t}\n\n\t\tvoid WriteEndMarker(UInt32 posState)\n\t\t{\n\t\t\tif (!_writeEndMark)\n\t\t\t\treturn;\n\n\t\t\t_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);\n\t\t\t_isRep[_state.Index].Encode(_rangeEncoder, 0);\n\t\t\t_state.UpdateMatch();\n\t\t\tUInt32 len = Base.kMatchMinLen;\n\t\t\t_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);\n\t\t\tUInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;\n\t\t\tUInt32 lenToPosState = Base.GetLenToPosState(len);\n\t\t\t_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);\n\t\t\tint footerBits = 30;\n\t\t\tUInt32 posReduced = (((UInt32)1) << footerBits) - 1;\n\t\t\t_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);\n\t\t\t_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);\n\t\t}\n\n\t\tvoid Flush(UInt32 nowPos)\n\t\t{\n\t\t\tReleaseMFStream();\n\t\t\tWriteEndMarker(nowPos & _posStateMask);\n\t\t\t_rangeEncoder.FlushData();\n\t\t\t_rangeEncoder.FlushStream();\n\t\t}\n\n\t\tpublic void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)\n\t\t{\n\t\t\tinSize = 0;\n\t\t\toutSize = 0;\n\t\t\tfinished = true;\n\n\t\t\tif (_inStream != null)\n\t\t\t{\n\t\t\t\t_matchFinder.SetStream(_inStream);\n\t\t\t\t_matchFinder.Init();\n\t\t\t\t_needReleaseMFStream = true;\n\t\t\t\t_inStream = null;\n\t\t\t\tif (_trainSize > 0)\n\t\t\t\t\t_matchFinder.Skip(_trainSize);\n\t\t\t}\n\n\t\t\tif (_finished)\n\t\t\t\treturn;\n\t\t\t_finished = true;\n\n\n\t\t\tInt64 progressPosValuePrev = nowPos64;\n\t\t\tif (nowPos64 == 0)\n\t\t\t{\n\t\t\t\tif (_matchFinder.GetNumAvailableBytes() == 0)\n\t\t\t\t{\n\t\t\t\t\tFlush((UInt32)nowPos64);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tUInt32 len, numDistancePairs; // it's not used\n\t\t\t\tReadMatchDistances(out len, out numDistancePairs);\n\t\t\t\tUInt32 posState = (UInt32)(nowPos64) & _posStateMask;\n\t\t\t\t_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);\n\t\t\t\t_state.UpdateChar();\n\t\t\t\tByte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));\n\t\t\t\t_literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);\n\t\t\t\t_previousByte = curByte;\n\t\t\t\t_additionalOffset--;\n\t\t\t\tnowPos64++;\n\t\t\t}\n\t\t\tif (_matchFinder.GetNumAvailableBytes() == 0)\n\t\t\t{\n\t\t\t\tFlush((UInt32)nowPos64);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\twhile (true)\n\t\t\t{\n\t\t\t\tUInt32 pos;\n\t\t\t\tUInt32 len = GetOptimum((UInt32)nowPos64, out pos);\n\t\t\t\t\n\t\t\t\tUInt32 posState = ((UInt32)nowPos64) & _posStateMask;\n\t\t\t\tUInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;\n\t\t\t\tif (len == 1 && pos == 0xFFFFFFFF)\n\t\t\t\t{\n\t\t\t\t\t_isMatch[complexState].Encode(_rangeEncoder, 0);\n\t\t\t\t\tByte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));\n\t\t\t\t\tLiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);\n\t\t\t\t\tif (!_state.IsCharState())\n\t\t\t\t\t{\n\t\t\t\t\t\tByte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));\n\t\t\t\t\t\tsubCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tsubCoder.Encode(_rangeEncoder, curByte);\n\t\t\t\t\t_previousByte = curByte;\n\t\t\t\t\t_state.UpdateChar();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t_isMatch[complexState].Encode(_rangeEncoder, 1);\n\t\t\t\t\tif (pos < Base.kNumRepDistances)\n\t\t\t\t\t{\n\t\t\t\t\t\t_isRep[_state.Index].Encode(_rangeEncoder, 1);\n\t\t\t\t\t\tif (pos == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_isRepG0[_state.Index].Encode(_rangeEncoder, 0);\n\t\t\t\t\t\t\tif (len == 1)\n\t\t\t\t\t\t\t\t_isRep0Long[complexState].Encode(_rangeEncoder, 0);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t_isRep0Long[complexState].Encode(_rangeEncoder, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_isRepG0[_state.Index].Encode(_rangeEncoder, 1);\n\t\t\t\t\t\t\tif (pos == 1)\n\t\t\t\t\t\t\t\t_isRepG1[_state.Index].Encode(_rangeEncoder, 0);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_isRepG1[_state.Index].Encode(_rangeEncoder, 1);\n\t\t\t\t\t\t\t\t_isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (len == 1)\n\t\t\t\t\t\t\t_state.UpdateShortRep();\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);\n\t\t\t\t\t\t\t_state.UpdateRep();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tUInt32 distance = _repDistances[pos];\n\t\t\t\t\t\tif (pos != 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (UInt32 i = pos; i >= 1; i--)\n\t\t\t\t\t\t\t\t_repDistances[i] = _repDistances[i - 1];\n\t\t\t\t\t\t\t_repDistances[0] = distance;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_isRep[_state.Index].Encode(_rangeEncoder, 0);\n\t\t\t\t\t\t_state.UpdateMatch();\n\t\t\t\t\t\t_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);\n\t\t\t\t\t\tpos -= Base.kNumRepDistances;\n\t\t\t\t\t\tUInt32 posSlot = GetPosSlot(pos);\n\t\t\t\t\t\tUInt32 lenToPosState = Base.GetLenToPosState(len);\n\t\t\t\t\t\t_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);\n\n\t\t\t\t\t\tif (posSlot >= Base.kStartPosModelIndex)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint footerBits = (int)((posSlot >> 1) - 1);\n\t\t\t\t\t\t\tUInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);\n\t\t\t\t\t\t\tUInt32 posReduced = pos - baseVal;\n\n\t\t\t\t\t\t\tif (posSlot < Base.kEndPosModelIndex)\n\t\t\t\t\t\t\t\tRangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders,\n\t\t\t\t\t\t\t\t\t\tbaseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);\n\t\t\t\t\t\t\t\t_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);\n\t\t\t\t\t\t\t\t_alignPriceCount++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tUInt32 distance = pos;\n\t\t\t\t\t\tfor (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)\n\t\t\t\t\t\t\t_repDistances[i] = _repDistances[i - 1];\n\t\t\t\t\t\t_repDistances[0] = distance;\n\t\t\t\t\t\t_matchPriceCount++;\n\t\t\t\t\t}\n\t\t\t\t\t_previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));\n\t\t\t\t}\n\t\t\t\t_additionalOffset -= len;\n\t\t\t\tnowPos64 += len;\n\t\t\t\tif (_additionalOffset == 0)\n\t\t\t\t{\n\t\t\t\t\t// if (!_fastMode)\n\t\t\t\t\tif (_matchPriceCount >= (1 << 7))\n\t\t\t\t\t\tFillDistancesPrices();\n\t\t\t\t\tif (_alignPriceCount >= Base.kAlignTableSize)\n\t\t\t\t\t\tFillAlignPrices();\n\t\t\t\t\tinSize = nowPos64;\n\t\t\t\t\toutSize = _rangeEncoder.GetProcessedSizeAdd();\n\t\t\t\t\tif (_matchFinder.GetNumAvailableBytes() == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tFlush((UInt32)nowPos64);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (nowPos64 - progressPosValuePrev >= (1 << 12))\n\t\t\t\t\t{\n\t\t\t\t\t\t_finished = false;\n\t\t\t\t\t\tfinished = false;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid ReleaseMFStream()\n\t\t{\n\t\t\tif (_matchFinder != null && _needReleaseMFStream)\n\t\t\t{\n\t\t\t\t_matchFinder.ReleaseStream();\n\t\t\t\t_needReleaseMFStream = false;\n\t\t\t}\n\t\t}\n\n\t\tvoid SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }\n\t\tvoid ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }\n\n\t\tvoid ReleaseStreams()\n\t\t{\n\t\t\tReleaseMFStream();\n\t\t\tReleaseOutStream();\n\t\t}\n\n\t\tvoid SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,\n\t\t\t\tInt64 inSize, Int64 outSize)\n\t\t{\n\t\t\t_inStream = inStream;\n\t\t\t_finished = false;\n\t\t\tCreate();\n\t\t\tSetOutStream(outStream);\n\t\t\tInit();\n\n\t\t\t// if (!_fastMode)\n\t\t\t{\n\t\t\t\tFillDistancesPrices();\n\t\t\t\tFillAlignPrices();\n\t\t\t}\n\n\t\t\t_lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);\n\t\t\t_lenEncoder.UpdateTables((UInt32)1 << _posStateBits);\n\t\t\t_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);\n\t\t\t_repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);\n\n\t\t\tnowPos64 = 0;\n\t\t}\n\n\n\t\tpublic void Code(System.IO.Stream inStream, System.IO.Stream outStream,\n\t\t\tInt64 inSize, Int64 outSize, ICodeProgress progress)\n\t\t{\n\t\t\t_needReleaseMFStream = false;\n\t\t\ttry\n\t\t\t{\n\t\t\t\tSetStreams(inStream, outStream, inSize, outSize);\n\t\t\t\twhile (true)\n\t\t\t\t{\n\t\t\t\t\tInt64 processedInSize;\n\t\t\t\t\tInt64 processedOutSize;\n\t\t\t\t\tbool finished;\n\t\t\t\t\tCodeOneBlock(out processedInSize, out processedOutSize, out finished);\n\t\t\t\t\tif (finished)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (progress != null)\n\t\t\t\t\t{\n\t\t\t\t\t\tprogress.SetProgress(processedInSize, processedOutSize);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfinally\n\t\t\t{\n\t\t\t\tReleaseStreams();\n\t\t\t}\n\t\t}\n\n\t\tconst int kPropSize = 5;\n\t\tByte[] properties = new Byte[kPropSize];\n\n\t\tpublic void WriteCoderProperties(System.IO.Stream outStream)\n\t\t{\n\t\t\tproperties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);\n\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\tproperties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF);\n\t\t\toutStream.Write(properties, 0, kPropSize);\n\t\t}\n\t\t\n\t\tUInt32[] tempPrices = new UInt32[Base.kNumFullDistances];\n\t\tUInt32 _matchPriceCount;\n\n\t\tvoid FillDistancesPrices()\n\t\t{\n\t\t\tfor (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)\n\t\t\t{ \n\t\t\t\tUInt32 posSlot = GetPosSlot(i);\n\t\t\t\tint footerBits = (int)((posSlot >> 1) - 1);\n\t\t\t\tUInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);\n\t\t\t\ttempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, \n\t\t\t\t\tbaseVal - posSlot - 1, footerBits, i - baseVal);\n\t\t\t}\n\n\t\t\tfor (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)\n\t\t\t{\n\t\t\t\tUInt32 posSlot;\n\t\t\t\tRangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];\n\t\t\t\n\t\t\t\tUInt32 st = (lenToPosState << Base.kNumPosSlotBits);\n\t\t\t\tfor (posSlot = 0; posSlot < _distTableSize; posSlot++)\n\t\t\t\t\t_posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);\n\t\t\t\tfor (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)\n\t\t\t\t\t_posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits);\n\n\t\t\t\tUInt32 st2 = lenToPosState * Base.kNumFullDistances;\n\t\t\t\tUInt32 i;\n\t\t\t\tfor (i = 0; i < Base.kStartPosModelIndex; i++)\n\t\t\t\t\t_distancesPrices[st2 + i] = _posSlotPrices[st + i];\n\t\t\t\tfor (; i < Base.kNumFullDistances; i++)\n\t\t\t\t\t_distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];\n\t\t\t}\n\t\t\t_matchPriceCount = 0;\n\t\t}\n\n\t\tvoid FillAlignPrices()\n\t\t{\n\t\t\tfor (UInt32 i = 0; i < Base.kAlignTableSize; i++)\n\t\t\t\t_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);\n\t\t\t_alignPriceCount = 0;\n\t\t}\n\n\n\t\tstatic string[] kMatchFinderIDs = \n\t\t{\n\t\t\t\"BT2\",\n\t\t\t\"BT4\",\n\t\t};\n\n\t\tstatic int FindMatchFinder(string s)\n\t\t{\n\t\t\tfor (int m = 0; m < kMatchFinderIDs.Length; m++)\n\t\t\t\tif (s == kMatchFinderIDs[m])\n\t\t\t\t\treturn m;\n\t\t\treturn -1;\n\t\t}\n\t\n\t\tpublic void SetCoderProperties(CoderPropID[] propIDs, object[] properties)\n\t\t{\n\t\t\tfor (UInt32 i = 0; i < properties.Length; i++)\n\t\t\t{\n\t\t\t\tobject prop = properties[i];\n\t\t\t\tswitch (propIDs[i])\n\t\t\t\t{\n\t\t\t\t\tcase CoderPropID.NumFastBytes:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!(prop is Int32))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\tInt32 numFastBytes = (Int32)prop;\n\t\t\t\t\t\tif (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\t_numFastBytes = (UInt32)numFastBytes;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CoderPropID.Algorithm:\n\t\t\t\t\t{\n\t\t\t\t\t\t/*\n\t\t\t\t\t\tif (!(prop is Int32))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\tInt32 maximize = (Int32)prop;\n\t\t\t\t\t\t_fastMode = (maximize == 0);\n\t\t\t\t\t\t_maxMode = (maximize >= 2);\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CoderPropID.MatchFinder:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!(prop is String))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\tEMatchFinderType matchFinderIndexPrev = _matchFinderType;\n\t\t\t\t\t\tint m = FindMatchFinder(((string)prop).ToUpper());\n\t\t\t\t\t\tif (m < 0)\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\t_matchFinderType = (EMatchFinderType)m;\n\t\t\t\t\t\tif (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_dictionarySizePrev = 0xFFFFFFFF;\n\t\t\t\t\t\t\t_matchFinder = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CoderPropID.DictionarySize:\n\t\t\t\t\t{\n\t\t\t\t\t\tconst int kDicLogSizeMaxCompress = 30;\n\t\t\t\t\t\tif (!(prop is Int32))\n\t\t\t\t\t\t\tthrow new InvalidParamException(); ;\n\t\t\t\t\t\tInt32 dictionarySize = (Int32)prop;\n\t\t\t\t\t\tif (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||\n\t\t\t\t\t\t\tdictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\t_dictionarySize = (UInt32)dictionarySize;\n\t\t\t\t\t\tint dicLogSize;\n\t\t\t\t\t\tfor (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)\n\t\t\t\t\t\t\tif (dictionarySize <= ((UInt32)(1) << dicLogSize))\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t_distTableSize = (UInt32)dicLogSize * 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CoderPropID.PosStateBits:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!(prop is Int32))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\tInt32 v = (Int32)prop;\n\t\t\t\t\t\tif (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\t_posStateBits = (int)v;\n\t\t\t\t\t\t_posStateMask = (((UInt32)1) << (int)_posStateBits) - 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CoderPropID.LitPosBits:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!(prop is Int32))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\tInt32 v = (Int32)prop;\n\t\t\t\t\t\tif (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax)\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\t_numLiteralPosStateBits = (int)v;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CoderPropID.LitContextBits:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!(prop is Int32))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\tInt32 v = (Int32)prop;\n\t\t\t\t\t\tif (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax)\n\t\t\t\t\t\t\tthrow new InvalidParamException(); ;\n\t\t\t\t\t\t_numLiteralContextBits = (int)v;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CoderPropID.EndMarker:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!(prop is Boolean))\n\t\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t\t\tSetWriteEndMarkerMode((Boolean)prop);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new InvalidParamException();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tuint _trainSize = 0;\n\t\tpublic void SetTrainSize(uint trainSize)\n\t\t{\n\t\t\t_trainSize = trainSize;\n\t\t}\n\t\t\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/RangeCoder/RangeCoder.cs",
    "content": "using System;\n\nnamespace SevenZip.Compression.RangeCoder\n{\n\tclass Encoder\n\t{\n\t\tpublic const uint kTopValue = (1 << 24);\n\n\t\tSystem.IO.Stream Stream;\n\n\t\tpublic UInt64 Low;\n\t\tpublic uint Range;\n\t\tuint _cacheSize;\n\t\tbyte _cache;\n\n\t\tlong StartPosition;\n\n\t\tpublic void SetStream(System.IO.Stream stream)\n\t\t{\n\t\t\tStream = stream;\n\t\t}\n\n\t\tpublic void ReleaseStream()\n\t\t{\n\t\t\tStream = null;\n\t\t}\n\n\t\tpublic void Init()\n\t\t{\n\t\t\tStartPosition = Stream.Position;\n\n\t\t\tLow = 0;\n\t\t\tRange = 0xFFFFFFFF;\n\t\t\t_cacheSize = 1;\n\t\t\t_cache = 0;\n\t\t}\n\n\t\tpublic void FlushData()\n\t\t{\n\t\t\tfor (int i = 0; i < 5; i++)\n\t\t\t\tShiftLow();\n\t\t}\n\n\t\tpublic void FlushStream()\n\t\t{\n\t\t\tStream.Flush();\n\t\t}\n\n\t\tpublic void CloseStream()\n\t\t{\n\t\t\tStream.Close();\n\t\t}\n\n\t\tpublic void Encode(uint start, uint size, uint total)\n\t\t{\n\t\t\tLow += start * (Range /= total);\n\t\t\tRange *= size;\n\t\t\twhile (Range < kTopValue)\n\t\t\t{\n\t\t\t\tRange <<= 8;\n\t\t\t\tShiftLow();\n\t\t\t}\n\t\t}\n\n\t\tpublic void ShiftLow()\n\t\t{\n\t\t\tif ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)\n\t\t\t{\n\t\t\t\tbyte temp = _cache;\n\t\t\t\tdo\n\t\t\t\t{\n\t\t\t\t\tStream.WriteByte((byte)(temp + (Low >> 32)));\n\t\t\t\t\ttemp = 0xFF;\n\t\t\t\t}\n\t\t\t\twhile (--_cacheSize != 0);\n\t\t\t\t_cache = (byte)(((uint)Low) >> 24);\n\t\t\t}\n\t\t\t_cacheSize++;\n\t\t\tLow = ((uint)Low) << 8;\n\t\t}\n\n\t\tpublic void EncodeDirectBits(uint v, int numTotalBits)\n\t\t{\n\t\t\tfor (int i = numTotalBits - 1; i >= 0; i--)\n\t\t\t{\n\t\t\t\tRange >>= 1;\n\t\t\t\tif (((v >> i) & 1) == 1)\n\t\t\t\t\tLow += Range;\n\t\t\t\tif (Range < kTopValue)\n\t\t\t\t{\n\t\t\t\t\tRange <<= 8;\n\t\t\t\t\tShiftLow();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void EncodeBit(uint size0, int numTotalBits, uint symbol)\n\t\t{\n\t\t\tuint newBound = (Range >> numTotalBits) * size0;\n\t\t\tif (symbol == 0)\n\t\t\t\tRange = newBound;\n\t\t\telse\n\t\t\t{\n\t\t\t\tLow += newBound;\n\t\t\t\tRange -= newBound;\n\t\t\t}\n\t\t\twhile (Range < kTopValue)\n\t\t\t{\n\t\t\t\tRange <<= 8;\n\t\t\t\tShiftLow();\n\t\t\t}\n\t\t}\n\n\t\tpublic long GetProcessedSizeAdd()\n\t\t{\n\t\t\treturn _cacheSize +\n\t\t\t\tStream.Position - StartPosition + 4;\n\t\t\t// (long)Stream.GetProcessedSize();\n\t\t}\n\t}\n\n\tclass Decoder\n\t{\n\t\tpublic const uint kTopValue = (1 << 24);\n\t\tpublic uint Range;\n\t\tpublic uint Code;\n\t\t// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);\n\t\tpublic System.IO.Stream Stream;\n\n\t\tpublic void Init(System.IO.Stream stream)\n\t\t{\n\t\t\t// Stream.Init(stream);\n\t\t\tStream = stream;\n\n\t\t\tCode = 0;\n\t\t\tRange = 0xFFFFFFFF;\n\t\t\tfor (int i = 0; i < 5; i++)\n\t\t\t\tCode = (Code << 8) | (byte)Stream.ReadByte();\n\t\t}\n\n\t\tpublic void ReleaseStream()\n\t\t{\n\t\t\t// Stream.ReleaseStream();\n\t\t\tStream = null;\n\t\t}\n\n\t\tpublic void CloseStream()\n\t\t{\n\t\t\tStream.Close();\n\t\t}\n\n\t\tpublic void Normalize()\n\t\t{\n\t\t\twhile (Range < kTopValue)\n\t\t\t{\n\t\t\t\tCode = (Code << 8) | (byte)Stream.ReadByte();\n\t\t\t\tRange <<= 8;\n\t\t\t}\n\t\t}\n\n\t\tpublic void Normalize2()\n\t\t{\n\t\t\tif (Range < kTopValue)\n\t\t\t{\n\t\t\t\tCode = (Code << 8) | (byte)Stream.ReadByte();\n\t\t\t\tRange <<= 8;\n\t\t\t}\n\t\t}\n\n\t\tpublic uint GetThreshold(uint total)\n\t\t{\n\t\t\treturn Code / (Range /= total);\n\t\t}\n\n\t\tpublic void Decode(uint start, uint size, uint total)\n\t\t{\n\t\t\tCode -= start * Range;\n\t\t\tRange *= size;\n\t\t\tNormalize();\n\t\t}\n\n\t\tpublic uint DecodeDirectBits(int numTotalBits)\n\t\t{\n\t\t\tuint range = Range;\n\t\t\tuint code = Code;\n\t\t\tuint result = 0;\n\t\t\tfor (int i = numTotalBits; i > 0; i--)\n\t\t\t{\n\t\t\t\trange >>= 1;\n\t\t\t\t/*\n\t\t\t\tresult <<= 1;\n\t\t\t\tif (code >= range)\n\t\t\t\t{\n\t\t\t\t\tcode -= range;\n\t\t\t\t\tresult |= 1;\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t\tuint t = (code - range) >> 31;\n\t\t\t\tcode -= range & (t - 1);\n\t\t\t\tresult = (result << 1) | (1 - t);\n\n\t\t\t\tif (range < kTopValue)\n\t\t\t\t{\n\t\t\t\t\tcode = (code << 8) | (byte)Stream.ReadByte();\n\t\t\t\t\trange <<= 8;\n\t\t\t\t}\n\t\t\t}\n\t\t\tRange = range;\n\t\t\tCode = code;\n\t\t\treturn result;\n\t\t}\n\n\t\tpublic uint DecodeBit(uint size0, int numTotalBits)\n\t\t{\n\t\t\tuint newBound = (Range >> numTotalBits) * size0;\n\t\t\tuint symbol;\n\t\t\tif (Code < newBound)\n\t\t\t{\n\t\t\t\tsymbol = 0;\n\t\t\t\tRange = newBound;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsymbol = 1;\n\t\t\t\tCode -= newBound;\n\t\t\t\tRange -= newBound;\n\t\t\t}\n\t\t\tNormalize();\n\t\t\treturn symbol;\n\t\t}\n\n\t\t// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/RangeCoder/RangeCoderBit.cs",
    "content": "using System;\n\nnamespace SevenZip.Compression.RangeCoder\n{\n\tstruct BitEncoder\n\t{\n\t\tpublic const int kNumBitModelTotalBits = 11;\n\t\tpublic const uint kBitModelTotal = (1 << kNumBitModelTotalBits);\n\t\tconst int kNumMoveBits = 5;\n\t\tconst int kNumMoveReducingBits = 2;\n\t\tpublic const int kNumBitPriceShiftBits = 6;\n\n\t\tuint Prob;\n\n\t\tpublic void Init() { Prob = kBitModelTotal >> 1; }\n\n\t\tpublic void UpdateModel(uint symbol)\n\t\t{\n\t\t\tif (symbol == 0)\n\t\t\t\tProb += (kBitModelTotal - Prob) >> kNumMoveBits;\n\t\t\telse\n\t\t\t\tProb -= (Prob) >> kNumMoveBits;\n\t\t}\n\n\t\tpublic void Encode(Encoder encoder, uint symbol)\n\t\t{\n\t\t\t// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);\n\t\t\t// UpdateModel(symbol);\n\t\t\tuint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;\n\t\t\tif (symbol == 0)\n\t\t\t{\n\t\t\t\tencoder.Range = newBound;\n\t\t\t\tProb += (kBitModelTotal - Prob) >> kNumMoveBits;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tencoder.Low += newBound;\n\t\t\t\tencoder.Range -= newBound;\n\t\t\t\tProb -= (Prob) >> kNumMoveBits;\n\t\t\t}\n\t\t\tif (encoder.Range < Encoder.kTopValue)\n\t\t\t{\n\t\t\t\tencoder.Range <<= 8;\n\t\t\t\tencoder.ShiftLow();\n\t\t\t}\n\t\t}\n\n\t\tprivate static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];\n\n\t\tstatic BitEncoder()\n\t\t{\n\t\t\tconst int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);\n\t\t\tfor (int i = kNumBits - 1; i >= 0; i--)\n\t\t\t{\n\t\t\t\tUInt32 start = (UInt32)1 << (kNumBits - i - 1);\n\t\t\t\tUInt32 end = (UInt32)1 << (kNumBits - i);\n\t\t\t\tfor (UInt32 j = start; j < end; j++)\n\t\t\t\t\tProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +\n\t\t\t\t\t\t(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));\n\t\t\t}\n\t\t}\n\n\t\tpublic uint GetPrice(uint symbol)\n\t\t{\n\t\t\treturn ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];\n\t\t}\n\t  public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }\n\t\tpublic uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }\n\t}\n\n\tstruct BitDecoder\n\t{\n\t\tpublic const int kNumBitModelTotalBits = 11;\n\t\tpublic const uint kBitModelTotal = (1 << kNumBitModelTotalBits);\n\t\tconst int kNumMoveBits = 5;\n\n\t\tuint Prob;\n\n\t\tpublic void UpdateModel(int numMoveBits, uint symbol)\n\t\t{\n\t\t\tif (symbol == 0)\n\t\t\t\tProb += (kBitModelTotal - Prob) >> numMoveBits;\n\t\t\telse\n\t\t\t\tProb -= (Prob) >> numMoveBits;\n\t\t}\n\n\t\tpublic void Init() { Prob = kBitModelTotal >> 1; }\n\n\t\tpublic uint Decode(RangeCoder.Decoder rangeDecoder)\n\t\t{\n\t\t\tuint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;\n\t\t\tif (rangeDecoder.Code < newBound)\n\t\t\t{\n\t\t\t\trangeDecoder.Range = newBound;\n\t\t\t\tProb += (kBitModelTotal - Prob) >> kNumMoveBits;\n\t\t\t\tif (rangeDecoder.Range < Decoder.kTopValue)\n\t\t\t\t{\n\t\t\t\t\trangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();\n\t\t\t\t\trangeDecoder.Range <<= 8;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\trangeDecoder.Range -= newBound;\n\t\t\t\trangeDecoder.Code -= newBound;\n\t\t\t\tProb -= (Prob) >> kNumMoveBits;\n\t\t\t\tif (rangeDecoder.Range < Decoder.kTopValue)\n\t\t\t\t{\n\t\t\t\t\trangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();\n\t\t\t\t\trangeDecoder.Range <<= 8;\n\t\t\t\t}\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/Compress/RangeCoder/RangeCoderBitTree.cs",
    "content": "using System;\n\nnamespace SevenZip.Compression.RangeCoder\n{\n\tstruct BitTreeEncoder\n\t{\n\t\tBitEncoder[] Models;\n\t\tint NumBitLevels;\n\n\t\tpublic BitTreeEncoder(int numBitLevels)\n\t\t{\n\t\t\tNumBitLevels = numBitLevels;\n\t\t\tModels = new BitEncoder[1 << numBitLevels];\n\t\t}\n\n\t\tpublic void Init()\n\t\t{\n\t\t\tfor (uint i = 1; i < (1 << NumBitLevels); i++)\n\t\t\t\tModels[i].Init();\n\t\t}\n\n\t\tpublic void Encode(Encoder rangeEncoder, UInt32 symbol)\n\t\t{\n\t\t\tUInt32 m = 1;\n\t\t\tfor (int bitIndex = NumBitLevels; bitIndex > 0; )\n\t\t\t{\n\t\t\t\tbitIndex--;\n\t\t\t\tUInt32 bit = (symbol >> bitIndex) & 1;\n\t\t\t\tModels[m].Encode(rangeEncoder, bit);\n\t\t\t\tm = (m << 1) | bit;\n\t\t\t}\n\t\t}\n\n\t\tpublic void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)\n\t\t{\n\t\t\tUInt32 m = 1;\n\t\t\tfor (UInt32 i = 0; i < NumBitLevels; i++)\n\t\t\t{\n\t\t\t\tUInt32 bit = symbol & 1;\n\t\t\t\tModels[m].Encode(rangeEncoder, bit);\n\t\t\t\tm = (m << 1) | bit;\n\t\t\t\tsymbol >>= 1;\n\t\t\t}\n\t\t}\n\n\t\tpublic UInt32 GetPrice(UInt32 symbol)\n\t\t{\n\t\t\tUInt32 price = 0;\n\t\t\tUInt32 m = 1;\n\t\t\tfor (int bitIndex = NumBitLevels; bitIndex > 0; )\n\t\t\t{\n\t\t\t\tbitIndex--;\n\t\t\t\tUInt32 bit = (symbol >> bitIndex) & 1;\n\t\t\t\tprice += Models[m].GetPrice(bit);\n\t\t\t\tm = (m << 1) + bit;\n\t\t\t}\n\t\t\treturn price;\n\t\t}\n\n\t\tpublic UInt32 ReverseGetPrice(UInt32 symbol)\n\t\t{\n\t\t\tUInt32 price = 0;\n\t\t\tUInt32 m = 1;\n\t\t\tfor (int i = NumBitLevels; i > 0; i--)\n\t\t\t{\n\t\t\t\tUInt32 bit = symbol & 1;\n\t\t\t\tsymbol >>= 1;\n\t\t\t\tprice += Models[m].GetPrice(bit);\n\t\t\t\tm = (m << 1) | bit;\n\t\t\t}\n\t\t\treturn price;\n\t\t}\n\n\t\tpublic static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,\n\t\t\tint NumBitLevels, UInt32 symbol)\n\t\t{\n\t\t\tUInt32 price = 0;\n\t\t\tUInt32 m = 1;\n\t\t\tfor (int i = NumBitLevels; i > 0; i--)\n\t\t\t{\n\t\t\t\tUInt32 bit = symbol & 1;\n\t\t\t\tsymbol >>= 1;\n\t\t\t\tprice += Models[startIndex + m].GetPrice(bit);\n\t\t\t\tm = (m << 1) | bit;\n\t\t\t}\n\t\t\treturn price;\n\t\t}\n\n\t\tpublic static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,\n\t\t\tEncoder rangeEncoder, int NumBitLevels, UInt32 symbol)\n\t\t{\n\t\t\tUInt32 m = 1;\n\t\t\tfor (int i = 0; i < NumBitLevels; i++)\n\t\t\t{\n\t\t\t\tUInt32 bit = symbol & 1;\n\t\t\t\tModels[startIndex + m].Encode(rangeEncoder, bit);\n\t\t\t\tm = (m << 1) | bit;\n\t\t\t\tsymbol >>= 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tstruct BitTreeDecoder\n\t{\n\t\tBitDecoder[] Models;\n\t\tint NumBitLevels;\n\n\t\tpublic BitTreeDecoder(int numBitLevels)\n\t\t{\n\t\t\tNumBitLevels = numBitLevels;\n\t\t\tModels = new BitDecoder[1 << numBitLevels];\n\t\t}\n\n\t\tpublic void Init()\n\t\t{\n\t\t\tfor (uint i = 1; i < (1 << NumBitLevels); i++)\n\t\t\t\tModels[i].Init();\n\t\t}\n\n\t\tpublic uint Decode(RangeCoder.Decoder rangeDecoder)\n\t\t{\n\t\t\tuint m = 1;\n\t\t\tfor (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)\n\t\t\t\tm = (m << 1) + Models[m].Decode(rangeDecoder);\n\t\t\treturn m - ((uint)1 << NumBitLevels);\n\t\t}\n\n\t\tpublic uint ReverseDecode(RangeCoder.Decoder rangeDecoder)\n\t\t{\n\t\t\tuint m = 1;\n\t\t\tuint symbol = 0;\n\t\t\tfor (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)\n\t\t\t{\n\t\t\t\tuint bit = Models[m].Decode(rangeDecoder);\n\t\t\t\tm <<= 1;\n\t\t\t\tm += bit;\n\t\t\t\tsymbol |= (bit << bitIndex);\n\t\t\t}\n\t\t\treturn symbol;\n\t\t}\n\n\t\tpublic static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,\n\t\t\tRangeCoder.Decoder rangeDecoder, int NumBitLevels)\n\t\t{\n\t\t\tuint m = 1;\n\t\t\tuint symbol = 0;\n\t\t\tfor (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)\n\t\t\t{\n\t\t\t\tuint bit = Models[startIndex + m].Decode(rangeDecoder);\n\t\t\t\tm <<= 1;\n\t\t\t\tm += bit;\n\t\t\t\tsymbol |= (bit << bitIndex);\n\t\t\t}\n\t\t\treturn symbol;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/7zip/ICoder.cs",
    "content": "// ICoder.h\n\nusing System;\n\nnamespace SevenZip\n{\n\t/// <summary>\n\t/// The exception that is thrown when an error in input stream occurs during decoding.\n\t/// </summary>\n\tclass DataErrorException : ApplicationException\n\t{\n\t\tpublic DataErrorException(): base(\"Data Error\") { }\n\t}\n\n\t/// <summary>\n\t/// The exception that is thrown when the value of an argument is outside the allowable range.\n\t/// </summary>\n\tclass InvalidParamException : ApplicationException\n\t{\n\t\tpublic InvalidParamException(): base(\"Invalid Parameter\") { }\n\t}\n\n\tpublic interface ICodeProgress\n\t{\n\t\t/// <summary>\n\t\t/// Callback progress.\n\t\t/// </summary>\n\t\t/// <param name=\"inSize\">\n\t\t/// input size. -1 if unknown.\n\t\t/// </param>\n\t\t/// <param name=\"outSize\">\n\t\t/// output size. -1 if unknown.\n\t\t/// </param>\n\t\tvoid SetProgress(Int64 inSize, Int64 outSize);\n\t};\n\n\tpublic interface ICoder\n\t{\n\t\t/// <summary>\n\t\t/// Codes streams.\n\t\t/// </summary>\n\t\t/// <param name=\"inStream\">\n\t\t/// input Stream.\n\t\t/// </param>\n\t\t/// <param name=\"outStream\">\n\t\t/// output Stream.\n\t\t/// </param>\n\t\t/// <param name=\"inSize\">\n\t\t/// input Size. -1 if unknown.\n\t\t/// </param>\n\t\t/// <param name=\"outSize\">\n\t\t/// output Size. -1 if unknown.\n\t\t/// </param>\n\t\t/// <param name=\"progress\">\n\t\t/// callback progress reference.\n\t\t/// </param>\n\t\t/// <exception cref=\"SevenZip.DataErrorException\">\n\t\t/// if input stream is not valid\n\t\t/// </exception>\n\t\tvoid Code(System.IO.Stream inStream, System.IO.Stream outStream,\n\t\t\tInt64 inSize, Int64 outSize, ICodeProgress progress);\n\t};\n\n\t/*\n\tpublic interface ICoder2\n\t{\n\t\t void Code(ISequentialInStream []inStreams,\n\t\t\t\tconst UInt64 []inSizes, \n\t\t\t\tISequentialOutStream []outStreams, \n\t\t\t\tUInt64 []outSizes,\n\t\t\t\tICodeProgress progress);\n\t};\n  */\n\n\t/// <summary>\n\t/// Provides the fields that represent properties idenitifiers for compressing.\n\t/// </summary>\n\tpublic enum CoderPropID\n\t{\n\t\t/// <summary>\n\t\t/// Specifies default property.\n\t\t/// </summary>\n\t\tDefaultProp = 0,\n\t\t/// <summary>\n\t\t/// Specifies size of dictionary.\n\t\t/// </summary>\n\t\tDictionarySize,\n\t\t/// <summary>\n\t\t/// Specifies size of memory for PPM*.\n\t\t/// </summary>\n\t\tUsedMemorySize,\n\t\t/// <summary>\n\t\t/// Specifies order for PPM methods.\n\t\t/// </summary>\n\t\tOrder,\n\t\t/// <summary>\n\t\t/// Specifies Block Size.\n\t\t/// </summary>\n\t\tBlockSize,\n\t\t/// <summary>\n\t\t/// Specifies number of postion state bits for LZMA (0 <= x <= 4).\n\t\t/// </summary>\n\t\tPosStateBits,\n\t\t/// <summary>\n\t\t/// Specifies number of literal context bits for LZMA (0 <= x <= 8).\n\t\t/// </summary>\n\t\tLitContextBits,\n\t\t/// <summary>\n\t\t/// Specifies number of literal position bits for LZMA (0 <= x <= 4).\n\t\t/// </summary>\n\t\tLitPosBits,\n\t\t/// <summary>\n\t\t/// Specifies number of fast bytes for LZ*.\n\t\t/// </summary>\n\t\tNumFastBytes,\n\t\t/// <summary>\n\t\t/// Specifies match finder. LZMA: \"BT2\", \"BT4\" or \"BT4B\".\n\t\t/// </summary>\n\t\tMatchFinder,\n\t\t/// <summary>\n\t\t/// Specifies the number of match finder cyckes.\n\t\t/// </summary>\n\t\tMatchFinderCycles,\n\t\t/// <summary>\n\t\t/// Specifies number of passes.\n\t\t/// </summary>\n\t\tNumPasses,\n\t\t/// <summary>\n\t\t/// Specifies number of algorithm.\n\t\t/// </summary>\n\t\tAlgorithm,\n\t\t/// <summary>\n\t\t/// Specifies the number of threads.\n\t\t/// </summary>\n\t\tNumThreads,\n\t\t/// <summary>\n\t\t/// Specifies mode with end marker.\n\t\t/// </summary>\n\t\tEndMarker\n\t};\n\n\n\tpublic interface ISetCoderProperties\n\t{\n\t\tvoid SetCoderProperties(CoderPropID[] propIDs, object[] properties);\n\t};\n\n\tpublic interface IWriteCoderProperties\n\t{\n\t\tvoid WriteCoderProperties(System.IO.Stream outStream);\n\t}\n\n\tpublic interface ISetDecoderProperties\n\t{\n\t\tvoid SetDecoderProperties(byte[] properties);\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/AssetStudio.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>\n    <Version>0.16.0.0</Version>\n    <AssemblyVersion>0.16.0.0</AssemblyVersion>\n    <FileVersion>0.16.0.0</FileVersion>\n    <Copyright>Copyright © Perfare 2018-2022</Copyright>\n    <DebugType>embedded</DebugType>\n  </PropertyGroup>\n\n  <ItemGroup Condition=\" '$(TargetFramework)' != 'net472' \">\n    <PackageReference Include=\"K4os.Compression.LZ4\" Version=\"1.2.16\" />\n  </ItemGroup>\n\n  <ItemGroup Condition=\" '$(TargetFramework)' == 'net472' \">\n    <PackageReference Include=\"System.Memory\" Version=\"4.5.4\" />\n    <PackageReference Include=\"System.IO.Compression\" Version=\"4.0.0\" />\n    <PackageReference Include=\"K4os.Compression.LZ4\" Version=\"1.1.11\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "AssetStudio/AssetsManager.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\nusing System.Text;\nusing static AssetStudio.ImportHelper;\n\nnamespace AssetStudio\n{\n    public class AssetsManager\n    {\n        public string SpecifyUnityVersion;\n        public List<SerializedFile> assetsFileList = new List<SerializedFile>();\n\n        internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);\n        internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);\n\n        private List<string> importFiles = new List<string>();\n        private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n        private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n        private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n\n        public void LoadFiles(params string[] files)\n        {\n            var path = Path.GetDirectoryName(Path.GetFullPath(files[0]));\n            MergeSplitAssets(path);\n            var toReadFile = ProcessingSplitFiles(files.ToList());\n            Load(toReadFile);\n        }\n\n        public void LoadFolder(string path)\n        {\n            MergeSplitAssets(path, true);\n            var files = Directory.GetFiles(path, \"*.*\", SearchOption.AllDirectories).ToList();\n            var toReadFile = ProcessingSplitFiles(files);\n            Load(toReadFile);\n        }\n\n        private void Load(string[] files)\n        {\n            foreach (var file in files)\n            {\n                importFiles.Add(file);\n                importFilesHash.Add(Path.GetFileName(file));\n            }\n\n            Progress.Reset();\n            //use a for loop because list size can change\n            for (var i = 0; i < importFiles.Count; i++)\n            {\n                LoadFile(importFiles[i]);\n                Progress.Report(i + 1, importFiles.Count);\n            }\n\n            importFiles.Clear();\n            importFilesHash.Clear();\n            noexistFiles.Clear();\n            assetsFileListHash.Clear();\n\n            ReadAssets();\n            ProcessAssets();\n        }\n\n        private void LoadFile(string fullName)\n        {\n            var reader = new FileReader(fullName);\n            LoadFile(reader);\n        }\n\n        private void LoadFile(FileReader reader)\n        {\n            switch (reader.FileType)\n            {\n                case FileType.AssetsFile:\n                    LoadAssetsFile(reader);\n                    break;\n                case FileType.BundleFile:\n                    LoadBundleFile(reader);\n                    break;\n                case FileType.WebFile:\n                    LoadWebFile(reader);\n                    break;\n                case FileType.GZipFile:\n                    LoadFile(DecompressGZip(reader));\n                    break;\n                case FileType.BrotliFile:\n                    LoadFile(DecompressBrotli(reader));\n                    break;\n                case FileType.ZipFile:\n                    LoadZipFile(reader);\n                    break;\n            }\n        }\n\n        private void LoadAssetsFile(FileReader reader)\n        {\n            if (!assetsFileListHash.Contains(reader.FileName))\n            {\n                Logger.Info($\"Loading {reader.FullPath}\");\n                try\n                {\n                    var assetsFile = new SerializedFile(reader, this);\n                    CheckStrippedVersion(assetsFile);\n                    assetsFileList.Add(assetsFile);\n                    assetsFileListHash.Add(assetsFile.fileName);\n\n                    foreach (var sharedFile in assetsFile.m_Externals)\n                    {\n                        var sharedFileName = sharedFile.fileName;\n\n                        if (!importFilesHash.Contains(sharedFileName))\n                        {\n                            var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);\n                            if (!noexistFiles.Contains(sharedFilePath))\n                            {\n                                if (!File.Exists(sharedFilePath))\n                                {\n                                    var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);\n                                    if (findFiles.Length > 0)\n                                    {\n                                        sharedFilePath = findFiles[0];\n                                    }\n                                }\n                                if (File.Exists(sharedFilePath))\n                                {\n                                    importFiles.Add(sharedFilePath);\n                                    importFilesHash.Add(sharedFileName);\n                                }\n                                else\n                                {\n                                    noexistFiles.Add(sharedFilePath);\n                                }\n                            }\n                        }\n                    }\n                }\n                catch (Exception e)\n                {\n                    Logger.Error($\"Error while reading assets file {reader.FullPath}\", e);\n                    reader.Dispose();\n                }\n            }\n            else\n            {\n                Logger.Info($\"Skipping {reader.FullPath}\");\n                reader.Dispose();\n            }\n        }\n\n        private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null)\n        {\n            if (!assetsFileListHash.Contains(reader.FileName))\n            {\n                try\n                {\n                    var assetsFile = new SerializedFile(reader, this);\n                    assetsFile.originalPath = originalPath;\n                    if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)\n                    {\n                        assetsFile.SetVersion(unityVersion);\n                    }\n                    CheckStrippedVersion(assetsFile);\n                    assetsFileList.Add(assetsFile);\n                    assetsFileListHash.Add(assetsFile.fileName);\n                }\n                catch (Exception e)\n                {\n                    Logger.Error($\"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}\", e);\n                    resourceFileReaders.Add(reader.FileName, reader);\n                }\n            }\n            else\n                Logger.Info($\"Skipping {originalPath} ({reader.FileName})\");\n        }\n\n        private void LoadBundleFile(FileReader reader, string originalPath = null)\n        {\n            Logger.Info(\"Loading \" + reader.FullPath);\n            try\n            {\n                var bundleFile = new BundleFile(reader);\n                foreach (var file in bundleFile.fileList)\n                {\n                    var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);\n                    var subReader = new FileReader(dummyPath, file.stream);\n                    if (subReader.FileType == FileType.AssetsFile)\n                    {\n                        LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);\n                    }\n                    else\n                    {\n                        resourceFileReaders[file.fileName] = subReader; //TODO\n                    }\n                }\n            }\n            catch (Exception e)\n            {\n                var str = $\"Error while reading bundle file {reader.FullPath}\";\n                if (originalPath != null)\n                {\n                    str += $\" from {Path.GetFileName(originalPath)}\";\n                }\n                Logger.Error(str, e);\n            }\n            finally\n            {\n                reader.Dispose();\n            }\n        }\n\n        private void LoadWebFile(FileReader reader)\n        {\n            Logger.Info(\"Loading \" + reader.FullPath);\n            try\n            {\n                var webFile = new WebFile(reader);\n                foreach (var file in webFile.fileList)\n                {\n                    var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);\n                    var subReader = new FileReader(dummyPath, file.stream);\n                    switch (subReader.FileType)\n                    {\n                        case FileType.AssetsFile:\n                            LoadAssetsFromMemory(subReader, reader.FullPath);\n                            break;\n                        case FileType.BundleFile:\n                            LoadBundleFile(subReader, reader.FullPath);\n                            break;\n                        case FileType.WebFile:\n                            LoadWebFile(subReader);\n                            break;\n                        case FileType.ResourceFile:\n                            resourceFileReaders[file.fileName] = subReader; //TODO\n                            break;\n                    }\n                }\n            }\n            catch (Exception e)\n            {\n                Logger.Error($\"Error while reading web file {reader.FullPath}\", e);\n            }\n            finally\n            {\n                reader.Dispose();\n            }\n        }\n\n        private void LoadZipFile(FileReader reader)\n        {\n            Logger.Info(\"Loading \" + reader.FileName);\n            try\n            {\n                using (ZipArchive archive = new ZipArchive(reader.BaseStream, ZipArchiveMode.Read))\n                {\n                    List<string> splitFiles = new List<string>();\n                    // register all files before parsing the assets so that the external references can be found\n                    // and find split files\n                    foreach (ZipArchiveEntry entry in archive.Entries)\n                    {\n                        if (entry.Name.Contains(\".split\"))\n                        {\n                            string baseName = Path.GetFileNameWithoutExtension(entry.Name);\n                            string basePath = Path.Combine(Path.GetDirectoryName(entry.FullName), baseName);\n                            if (!splitFiles.Contains(basePath))\n                            {\n                                splitFiles.Add(basePath);\n                                importFilesHash.Add(baseName);\n                            }\n                        }\n                        else\n                        {\n                            importFilesHash.Add(entry.Name);\n                        }\n                    }\n\n                    // merge split files and load the result\n                    foreach (string basePath in splitFiles)\n                    {\n                        try\n                        {\n                            Stream splitStream = new MemoryStream();\n                            int i = 0;\n                            while (true)\n                            {\n                                string path = $\"{basePath}.split{i++}\";\n                                ZipArchiveEntry entry = archive.GetEntry(path);\n                                if (entry == null)\n                                    break;\n                                using (Stream entryStream = entry.Open())\n                                {\n                                    entryStream.CopyTo(splitStream);\n                                }\n                            }\n                            splitStream.Seek(0, SeekOrigin.Begin);\n                            FileReader entryReader = new FileReader(basePath, splitStream);\n                            LoadFile(entryReader);\n                        }\n                        catch (Exception e)\n                        {\n                            Logger.Error($\"Error while reading zip split file {basePath}\", e);\n                        }\n                    }\n\n                    // load all entries\n                    foreach (ZipArchiveEntry entry in archive.Entries)\n                    {\n                        try\n                        {\n                            string dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), reader.FileName, entry.FullName);\n                            // create a new stream\n                            // - to store the deflated stream in\n                            // - to keep the data for later extraction\n                            Stream streamReader = new MemoryStream();\n                            using (Stream entryStream = entry.Open())\n                            {\n                                entryStream.CopyTo(streamReader);\n                            }\n                            streamReader.Position = 0;\n\n                            FileReader entryReader = new FileReader(dummyPath, streamReader);\n                            LoadFile(entryReader);\n                            if (entryReader.FileType == FileType.ResourceFile)\n                            {\n                                entryReader.Position = 0;\n                                if (!resourceFileReaders.ContainsKey(entry.Name))\n                                {\n                                    resourceFileReaders.Add(entry.Name, entryReader);\n                                }\n                            }\n                        }\n                        catch (Exception e)\n                        {\n                            Logger.Error($\"Error while reading zip entry {entry.FullName}\", e);\n                        }\n                    }\n                }\n            }\n            catch (Exception e)\n            {\n                Logger.Error($\"Error while reading zip file {reader.FileName}\", e);\n            }\n            finally\n            {\n                reader.Dispose();\n            }\n        }\n\n        public void CheckStrippedVersion(SerializedFile assetsFile)\n        {\n            if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion))\n            {\n                throw new Exception(\"The Unity version has been stripped, please set the version in the options\");\n            }\n            if (!string.IsNullOrEmpty(SpecifyUnityVersion))\n            {\n                assetsFile.SetVersion(SpecifyUnityVersion);\n            }\n        }\n\n        public void Clear()\n        {\n            foreach (var assetsFile in assetsFileList)\n            {\n                assetsFile.Objects.Clear();\n                assetsFile.reader.Close();\n            }\n            assetsFileList.Clear();\n\n            foreach (var resourceFileReader in resourceFileReaders)\n            {\n                resourceFileReader.Value.Close();\n            }\n            resourceFileReaders.Clear();\n\n            assetsFileIndexCache.Clear();\n        }\n\n        private void ReadAssets()\n        {\n            Logger.Info(\"Read assets...\");\n\n            var progressCount = assetsFileList.Sum(x => x.m_Objects.Count);\n            int i = 0;\n            Progress.Reset();\n            foreach (var assetsFile in assetsFileList)\n            {\n                foreach (var objectInfo in assetsFile.m_Objects)\n                {\n                    var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);\n                    try\n                    {\n                        Object obj;\n                        switch (objectReader.type)\n                        {\n                            case ClassIDType.Animation:\n                                obj = new Animation(objectReader);\n                                break;\n                            case ClassIDType.AnimationClip:\n                                obj = new AnimationClip(objectReader);\n                                break;\n                            case ClassIDType.Animator:\n                                obj = new Animator(objectReader);\n                                break;\n                            case ClassIDType.AnimatorController:\n                                obj = new AnimatorController(objectReader);\n                                break;\n                            case ClassIDType.AnimatorOverrideController:\n                                obj = new AnimatorOverrideController(objectReader);\n                                break;\n                            case ClassIDType.AssetBundle:\n                                obj = new AssetBundle(objectReader);\n                                break;\n                            case ClassIDType.AudioClip:\n                                obj = new AudioClip(objectReader);\n                                break;\n                            case ClassIDType.Avatar:\n                                obj = new Avatar(objectReader);\n                                break;\n                            case ClassIDType.Font:\n                                obj = new Font(objectReader);\n                                break;\n                            case ClassIDType.GameObject:\n                                obj = new GameObject(objectReader);\n                                break;\n                            case ClassIDType.Material:\n                                obj = new Material(objectReader);\n                                break;\n                            case ClassIDType.Mesh:\n                                obj = new Mesh(objectReader);\n                                break;\n                            case ClassIDType.MeshFilter:\n                                obj = new MeshFilter(objectReader);\n                                break;\n                            case ClassIDType.MeshRenderer:\n                                obj = new MeshRenderer(objectReader);\n                                break;\n                            case ClassIDType.MonoBehaviour:\n                                obj = new MonoBehaviour(objectReader);\n                                break;\n                            case ClassIDType.MonoScript:\n                                obj = new MonoScript(objectReader);\n                                break;\n                            case ClassIDType.MovieTexture:\n                                obj = new MovieTexture(objectReader);\n                                break;\n                            case ClassIDType.PlayerSettings:\n                                obj = new PlayerSettings(objectReader);\n                                break;\n                            case ClassIDType.RectTransform:\n                                obj = new RectTransform(objectReader);\n                                break;\n                            case ClassIDType.Shader:\n                                obj = new Shader(objectReader);\n                                break;\n                            case ClassIDType.SkinnedMeshRenderer:\n                                obj = new SkinnedMeshRenderer(objectReader);\n                                break;\n                            case ClassIDType.Sprite:\n                                obj = new Sprite(objectReader);\n                                break;\n                            case ClassIDType.SpriteAtlas:\n                                obj = new SpriteAtlas(objectReader);\n                                break;\n                            case ClassIDType.TextAsset:\n                                obj = new TextAsset(objectReader);\n                                break;\n                            case ClassIDType.Texture2D:\n                                obj = new Texture2D(objectReader);\n                                break;\n                            case ClassIDType.Transform:\n                                obj = new Transform(objectReader);\n                                break;\n                            case ClassIDType.VideoClip:\n                                obj = new VideoClip(objectReader);\n                                break;\n                            case ClassIDType.ResourceManager:\n                                obj = new ResourceManager(objectReader);\n                                break;\n                            default:\n                                obj = new Object(objectReader);\n                                break;\n                        }\n                        assetsFile.AddObject(obj);\n                    }\n                    catch (Exception e)\n                    {\n                        var sb = new StringBuilder();\n                        sb.AppendLine(\"Unable to load object\")\n                            .AppendLine($\"Assets {assetsFile.fileName}\")\n                            .AppendLine($\"Path {assetsFile.originalPath}\")\n                            .AppendLine($\"Type {objectReader.type}\")\n                            .AppendLine($\"PathID {objectInfo.m_PathID}\")\n                            .Append(e);\n                        Logger.Error(sb.ToString());\n                    }\n\n                    Progress.Report(++i, progressCount);\n                }\n            }\n        }\n\n        private void ProcessAssets()\n        {\n            Logger.Info(\"Process Assets...\");\n\n            foreach (var assetsFile in assetsFileList)\n            {\n                foreach (var obj in assetsFile.Objects)\n                {\n                    if (obj is GameObject m_GameObject)\n                    {\n                        foreach (var pptr in m_GameObject.m_Components)\n                        {\n                            if (pptr.TryGet(out var m_Component))\n                            {\n                                switch (m_Component)\n                                {\n                                    case Transform m_Transform:\n                                        m_GameObject.m_Transform = m_Transform;\n                                        break;\n                                    case MeshRenderer m_MeshRenderer:\n                                        m_GameObject.m_MeshRenderer = m_MeshRenderer;\n                                        break;\n                                    case MeshFilter m_MeshFilter:\n                                        m_GameObject.m_MeshFilter = m_MeshFilter;\n                                        break;\n                                    case SkinnedMeshRenderer m_SkinnedMeshRenderer:\n                                        m_GameObject.m_SkinnedMeshRenderer = m_SkinnedMeshRenderer;\n                                        break;\n                                    case Animator m_Animator:\n                                        m_GameObject.m_Animator = m_Animator;\n                                        break;\n                                    case Animation m_Animation:\n                                        m_GameObject.m_Animation = m_Animation;\n                                        break;\n                                }\n                            }\n                        }\n                    }\n                    else if (obj is SpriteAtlas m_SpriteAtlas)\n                    {\n                        foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)\n                        {\n                            if (m_PackedSprite.TryGet(out var m_Sprite))\n                            {\n                                if (m_Sprite.m_SpriteAtlas.IsNull)\n                                {\n                                    m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);\n                                }\n                                else\n                                {\n                                    m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);\n                                    if (m_SpriteAtlaOld.m_IsVariant)\n                                    {\n                                        m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/BigArrayPool.cs",
    "content": "﻿using System.Buffers;\n\nnamespace AssetStudio\n{\n    public static class BigArrayPool<T>\n    {\n        private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);\n        public static ArrayPool<T> Shared => s_shared;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/BitReader.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Bit reading helpers.</summary>\n\tinternal sealed class BitReader\n\t{\n\t\t/// <summary>\n\t\t/// Input byte buffer, consist of a ring-buffer and a \"slack\" region where bytes from the start of\n\t\t/// the ring-buffer are copied.\n\t\t/// </summary>\n\t\tprivate const int Capacity = 1024;\n\n\t\tprivate const int Slack = 16;\n\n\t\tprivate const int IntBufferSize = Capacity + Slack;\n\n\t\tprivate const int ByteReadSize = Capacity << 2;\n\n\t\tprivate const int ByteBufferSize = IntBufferSize << 2;\n\n\t\tprivate readonly byte[] byteBuffer = new byte[ByteBufferSize];\n\n\t\tprivate readonly int[] intBuffer = new int[IntBufferSize];\n\n\t\tprivate readonly Org.Brotli.Dec.IntReader intReader = new Org.Brotli.Dec.IntReader();\n\n\t\tprivate System.IO.Stream input;\n\n\t\t/// <summary>Input stream is finished.</summary>\n\t\tprivate bool endOfStreamReached;\n\n\t\t/// <summary>Pre-fetched bits.</summary>\n\t\tinternal long accumulator;\n\n\t\t/// <summary>Current bit-reading position in accumulator.</summary>\n\t\tinternal int bitOffset;\n\n\t\t/// <summary>Offset of next item in intBuffer.</summary>\n\t\tprivate int intOffset;\n\n\t\tprivate int tailBytes = 0;\n\n\t\t/* Number of bytes in unfinished \"int\" item. */\n\t\t/// <summary>Fills up the input buffer.</summary>\n\t\t/// <remarks>\n\t\t/// Fills up the input buffer.\n\t\t/// <p> No-op if there are at least 36 bytes present after current position.\n\t\t/// <p> After encountering the end of the input stream, 64 additional zero bytes are copied to the\n\t\t/// buffer.\n\t\t/// </remarks>\n\t\tinternal static void ReadMoreInput(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\t// TODO: Split to check and read; move read outside of decoding loop.\n\t\t\tif (br.intOffset <= Capacity - 9)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (br.endOfStreamReached)\n\t\t\t{\n\t\t\t\tif (IntAvailable(br) >= -2)\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"No more input\");\n\t\t\t}\n\t\t\tint readOffset = br.intOffset << 2;\n\t\t\tint bytesRead = ByteReadSize - readOffset;\n\t\t\tSystem.Array.Copy(br.byteBuffer, readOffset, br.byteBuffer, 0, bytesRead);\n\t\t\tbr.intOffset = 0;\n\t\t\ttry\n\t\t\t{\n\t\t\t\twhile (bytesRead < ByteReadSize)\n\t\t\t\t{\n\t\t\t\t\tint len = br.input.Read(br.byteBuffer, bytesRead, ByteReadSize - bytesRead);\n\t\t\t\t\t// EOF is -1 in Java, but 0 in C#.\n\t\t\t\t\tif (len <= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tbr.endOfStreamReached = true;\n\t\t\t\t\t\tbr.tailBytes = bytesRead;\n\t\t\t\t\t\tbytesRead += 3;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbytesRead += len;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (System.IO.IOException e)\n\t\t\t{\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Failed to read input\", e);\n\t\t\t}\n\t\t\tOrg.Brotli.Dec.IntReader.Convert(br.intReader, bytesRead >> 2);\n\t\t}\n\n\t\tinternal static void CheckHealth(Org.Brotli.Dec.BitReader br, bool endOfStream)\n\t\t{\n\t\t\tif (!br.endOfStreamReached)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tint byteOffset = (br.intOffset << 2) + ((br.bitOffset + 7) >> 3) - 8;\n\t\t\tif (byteOffset > br.tailBytes)\n\t\t\t{\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Read after end\");\n\t\t\t}\n\t\t\tif (endOfStream && (byteOffset != br.tailBytes))\n\t\t\t{\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Unused bytes after end\");\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>Advances the Read buffer by 5 bytes to make room for reading next 24 bits.</summary>\n\t\tinternal static void FillBitWindow(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tif (br.bitOffset >= 32)\n\t\t\t{\n\t\t\t\tbr.accumulator = ((long)br.intBuffer[br.intOffset++] << 32) | ((long)(((ulong)br.accumulator) >> 32));\n\t\t\t\tbr.bitOffset -= 32;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>Reads the specified number of bits from Read Buffer.</summary>\n\t\tinternal static int ReadBits(Org.Brotli.Dec.BitReader br, int n)\n\t\t{\n\t\t\tFillBitWindow(br);\n\t\t\tint val = (int)((long)(((ulong)br.accumulator) >> br.bitOffset)) & ((1 << n) - 1);\n\t\t\tbr.bitOffset += n;\n\t\t\treturn val;\n\t\t}\n\n\t\t/// <summary>Initialize bit reader.</summary>\n\t\t/// <remarks>\n\t\t/// Initialize bit reader.\n\t\t/// <p> Initialisation turns bit reader to a ready state. Also a number of bytes is prefetched to\n\t\t/// accumulator. Because of that this method may block until enough data could be read from input.\n\t\t/// </remarks>\n\t\t/// <param name=\"br\">BitReader POJO</param>\n\t\t/// <param name=\"input\">data source</param>\n\t\tinternal static void Init(Org.Brotli.Dec.BitReader br, System.IO.Stream input)\n\t\t{\n\t\t\tif (br.input != null)\n\t\t\t{\n\t\t\t\tthrow new System.InvalidOperationException(\"Bit reader already has associated input stream\");\n\t\t\t}\n\t\t\tOrg.Brotli.Dec.IntReader.Init(br.intReader, br.byteBuffer, br.intBuffer);\n\t\t\tbr.input = input;\n\t\t\tbr.accumulator = 0;\n\t\t\tbr.bitOffset = 64;\n\t\t\tbr.intOffset = Capacity;\n\t\t\tbr.endOfStreamReached = false;\n\t\t\tPrepare(br);\n\t\t}\n\n\t\tprivate static void Prepare(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tReadMoreInput(br);\n\t\t\tCheckHealth(br, false);\n\t\t\tFillBitWindow(br);\n\t\t\tFillBitWindow(br);\n\t\t}\n\n\t\tinternal static void Reload(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tif (br.bitOffset == 64)\n\t\t\t{\n\t\t\t\tPrepare(br);\n\t\t\t}\n\t\t}\n\n\t\t/// <exception cref=\"System.IO.IOException\"/>\n\t\tinternal static void Close(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tSystem.IO.Stream @is = br.input;\n\t\t\tbr.input = null;\n\t\t\tif (@is != null)\n\t\t\t{\n\t\t\t\t@is.Close();\n\t\t\t}\n\t\t}\n\n\t\tinternal static void JumpToByteBoundary(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tint padding = (64 - br.bitOffset) & 7;\n\t\t\tif (padding != 0)\n\t\t\t{\n\t\t\t\tint paddingBits = Org.Brotli.Dec.BitReader.ReadBits(br, padding);\n\t\t\t\tif (paddingBits != 0)\n\t\t\t\t{\n\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Corrupted padding bits\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tinternal static int IntAvailable(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tint limit = Capacity;\n\t\t\tif (br.endOfStreamReached)\n\t\t\t{\n\t\t\t\tlimit = (br.tailBytes + 3) >> 2;\n\t\t\t}\n\t\t\treturn limit - br.intOffset;\n\t\t}\n\n\t\tinternal static void CopyBytes(Org.Brotli.Dec.BitReader br, byte[] data, int offset, int length)\n\t\t{\n\t\t\tif ((br.bitOffset & 7) != 0)\n\t\t\t{\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Unaligned copyBytes\");\n\t\t\t}\n\t\t\t// Drain accumulator.\n\t\t\twhile ((br.bitOffset != 64) && (length != 0))\n\t\t\t{\n\t\t\t\tdata[offset++] = unchecked((byte)((long)(((ulong)br.accumulator) >> br.bitOffset)));\n\t\t\t\tbr.bitOffset += 8;\n\t\t\t\tlength--;\n\t\t\t}\n\t\t\tif (length == 0)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Get data from shadow buffer with \"sizeof(int)\" granularity.\n\t\t\tint copyInts = System.Math.Min(IntAvailable(br), length >> 2);\n\t\t\tif (copyInts > 0)\n\t\t\t{\n\t\t\t\tint readOffset = br.intOffset << 2;\n\t\t\t\tSystem.Array.Copy(br.byteBuffer, readOffset, data, offset, copyInts << 2);\n\t\t\t\toffset += copyInts << 2;\n\t\t\t\tlength -= copyInts << 2;\n\t\t\t\tbr.intOffset += copyInts;\n\t\t\t}\n\t\t\tif (length == 0)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Read tail bytes.\n\t\t\tif (IntAvailable(br) > 0)\n\t\t\t{\n\t\t\t\t// length = 1..3\n\t\t\t\tFillBitWindow(br);\n\t\t\t\twhile (length != 0)\n\t\t\t\t{\n\t\t\t\t\tdata[offset++] = unchecked((byte)((long)(((ulong)br.accumulator) >> br.bitOffset)));\n\t\t\t\t\tbr.bitOffset += 8;\n\t\t\t\t\tlength--;\n\t\t\t\t}\n\t\t\t\tCheckHealth(br, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Now it is possible to copy bytes directly.\n\t\t\ttry\n\t\t\t{\n\t\t\t\twhile (length > 0)\n\t\t\t\t{\n\t\t\t\t\tint len = br.input.Read(data, offset, length);\n\t\t\t\t\tif (len == -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Unexpected end of input\");\n\t\t\t\t\t}\n\t\t\t\t\toffset += len;\n\t\t\t\t\tlength -= len;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (System.IO.IOException e)\n\t\t\t{\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Failed to read input\", e);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/BrotliInputStream.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>\n\t/// <see cref=\"System.IO.Stream\"/>\n\t/// decorator that decompresses brotli data.\n\t/// <p> Not thread-safe.\n\t/// </summary>\n\tpublic class BrotliInputStream : System.IO.Stream\n\t{\n\t\tpublic const int DefaultInternalBufferSize = 16384;\n\n\t\t/// <summary>Internal buffer used for efficient byte-by-byte reading.</summary>\n\t\tprivate byte[] buffer;\n\n\t\t/// <summary>Number of decoded but still unused bytes in internal buffer.</summary>\n\t\tprivate int remainingBufferBytes;\n\n\t\t/// <summary>Next unused byte offset.</summary>\n\t\tprivate int bufferOffset;\n\n\t\t/// <summary>Decoder state.</summary>\n\t\tprivate readonly Org.Brotli.Dec.State state = new Org.Brotli.Dec.State();\n\n\t\t/// <summary>\n\t\t/// Creates a\n\t\t/// <see cref=\"System.IO.Stream\"/>\n\t\t/// wrapper that decompresses brotli data.\n\t\t/// <p> For byte-by-byte reading (\n\t\t/// <see cref=\"ReadByte()\"/>\n\t\t/// ) internal buffer with\n\t\t/// <see cref=\"DefaultInternalBufferSize\"/>\n\t\t/// size is allocated and used.\n\t\t/// <p> Will block the thread until first kilobyte of data of source is available.\n\t\t/// </summary>\n\t\t/// <param name=\"source\">underlying data source</param>\n\t\t/// <exception cref=\"System.IO.IOException\">in case of corrupted data or source stream problems</exception>\n\t\tpublic BrotliInputStream(System.IO.Stream source)\n\t\t\t: this(source, DefaultInternalBufferSize, null)\n\t\t{\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Creates a\n\t\t/// <see cref=\"System.IO.Stream\"/>\n\t\t/// wrapper that decompresses brotli data.\n\t\t/// <p> For byte-by-byte reading (\n\t\t/// <see cref=\"ReadByte()\"/>\n\t\t/// ) internal buffer of specified size is\n\t\t/// allocated and used.\n\t\t/// <p> Will block the thread until first kilobyte of data of source is available.\n\t\t/// </summary>\n\t\t/// <param name=\"source\">compressed data source</param>\n\t\t/// <param name=\"byteReadBufferSize\">\n\t\t/// size of internal buffer used in case of\n\t\t/// byte-by-byte reading\n\t\t/// </param>\n\t\t/// <exception cref=\"System.IO.IOException\">in case of corrupted data or source stream problems</exception>\n\t\tpublic BrotliInputStream(System.IO.Stream source, int byteReadBufferSize)\n\t\t\t: this(source, byteReadBufferSize, null)\n\t\t{\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Creates a\n\t\t/// <see cref=\"System.IO.Stream\"/>\n\t\t/// wrapper that decompresses brotli data.\n\t\t/// <p> For byte-by-byte reading (\n\t\t/// <see cref=\"ReadByte()\"/>\n\t\t/// ) internal buffer of specified size is\n\t\t/// allocated and used.\n\t\t/// <p> Will block the thread until first kilobyte of data of source is available.\n\t\t/// </summary>\n\t\t/// <param name=\"source\">compressed data source</param>\n\t\t/// <param name=\"byteReadBufferSize\">\n\t\t/// size of internal buffer used in case of\n\t\t/// byte-by-byte reading\n\t\t/// </param>\n\t\t/// <param name=\"customDictionary\">\n\t\t/// custom dictionary data;\n\t\t/// <see langword=\"null\"/>\n\t\t/// if not used\n\t\t/// </param>\n\t\t/// <exception cref=\"System.IO.IOException\">in case of corrupted data or source stream problems</exception>\n\t\tpublic BrotliInputStream(System.IO.Stream source, int byteReadBufferSize, byte[] customDictionary)\n\t\t{\n\t\t\tif (byteReadBufferSize <= 0)\n\t\t\t{\n\t\t\t\tthrow new System.ArgumentException(\"Bad buffer size:\" + byteReadBufferSize);\n\t\t\t}\n\t\t\telse if (source == null)\n\t\t\t{\n\t\t\t\tthrow new System.ArgumentException(\"source is null\");\n\t\t\t}\n\t\t\tthis.buffer = new byte[byteReadBufferSize];\n\t\t\tthis.remainingBufferBytes = 0;\n\t\t\tthis.bufferOffset = 0;\n\t\t\ttry\n\t\t\t{\n\t\t\t\tOrg.Brotli.Dec.State.SetInput(state, source);\n\t\t\t}\n\t\t\tcatch (Org.Brotli.Dec.BrotliRuntimeException ex)\n\t\t\t{\n\t\t\t\tthrow new System.IO.IOException(\"Brotli decoder initialization failed\", ex);\n\t\t\t}\n\t\t\tif (customDictionary != null)\n\t\t\t{\n\t\t\t\tOrg.Brotli.Dec.Decode.SetCustomDictionary(state, customDictionary);\n\t\t\t}\n\t\t}\n\n\t\t/// <summary><inheritDoc/></summary>\n\t\t/// <exception cref=\"System.IO.IOException\"/>\n\t\tpublic override void Close()\n\t\t{\n\t\t\tOrg.Brotli.Dec.State.Close(state);\n\t\t}\n\n\t\t/// <summary><inheritDoc/></summary>\n\t\t/// <exception cref=\"System.IO.IOException\"/>\n\t\tpublic override int ReadByte()\n\t\t{\n\t\t\tif (bufferOffset >= remainingBufferBytes)\n\t\t\t{\n\t\t\t\tremainingBufferBytes = Read(buffer, 0, buffer.Length);\n\t\t\t\tbufferOffset = 0;\n\t\t\t\tif (remainingBufferBytes == -1)\n\t\t\t\t{\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn buffer[bufferOffset++] & unchecked((int)(0xFF));\n\t\t}\n\n\t\t/// <summary><inheritDoc/></summary>\n\t\t/// <exception cref=\"System.IO.IOException\"/>\n\t\tpublic override int Read(byte[] destBuffer, int destOffset, int destLen)\n\t\t{\n\t\t\tif (destOffset < 0)\n\t\t\t{\n\t\t\t\tthrow new System.ArgumentException(\"Bad offset: \" + destOffset);\n\t\t\t}\n\t\t\telse if (destLen < 0)\n\t\t\t{\n\t\t\t\tthrow new System.ArgumentException(\"Bad length: \" + destLen);\n\t\t\t}\n\t\t\telse if (destOffset + destLen > destBuffer.Length)\n\t\t\t{\n\t\t\t\tthrow new System.ArgumentException(\"Buffer overflow: \" + (destOffset + destLen) + \" > \" + destBuffer.Length);\n\t\t\t}\n\t\t\telse if (destLen == 0)\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tint copyLen = System.Math.Max(remainingBufferBytes - bufferOffset, 0);\n\t\t\tif (copyLen != 0)\n\t\t\t{\n\t\t\t\tcopyLen = System.Math.Min(copyLen, destLen);\n\t\t\t\tSystem.Array.Copy(buffer, bufferOffset, destBuffer, destOffset, copyLen);\n\t\t\t\tbufferOffset += copyLen;\n\t\t\t\tdestOffset += copyLen;\n\t\t\t\tdestLen -= copyLen;\n\t\t\t\tif (destLen == 0)\n\t\t\t\t{\n\t\t\t\t\treturn copyLen;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry\n\t\t\t{\n\t\t\t\tstate.output = destBuffer;\n\t\t\t\tstate.outputOffset = destOffset;\n\t\t\t\tstate.outputLength = destLen;\n\t\t\t\tstate.outputUsed = 0;\n\t\t\t\tOrg.Brotli.Dec.Decode.Decompress(state);\n\t\t\t\tif (state.outputUsed == 0)\n\t\t\t\t{\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\treturn state.outputUsed + copyLen;\n\t\t\t}\n\t\t\tcatch (Org.Brotli.Dec.BrotliRuntimeException ex)\n\t\t\t{\n\t\t\t\tthrow new System.IO.IOException(\"Brotli stream decoding failed\", ex);\n\t\t\t}\n\t\t}\n\t\t// <{[INJECTED CODE]}>\n\t\tpublic override bool CanRead {\n\t\t\tget {return true;}\n\t\t}\n\n\t\tpublic override bool CanSeek {\n\t\t\tget {return false;}\n\t\t}\n\t\tpublic override long Length {\n\t\t\tget {throw new System.NotSupportedException();}\n\t\t}\n\t\tpublic override long Position {\n\t\t\tget {throw new System.NotSupportedException();}\n\t\t\tset {throw new System.NotSupportedException();}\n\t\t}\n\t\tpublic override long Seek(long offset, System.IO.SeekOrigin origin) {\n\t\t\tthrow new System.NotSupportedException();\n\t\t}\n\t\tpublic override void SetLength(long value){\n\t\t\tthrow new System.NotSupportedException();\n\t\t}\n\n\t\tpublic override bool CanWrite{get{return false;}}\n\t\tpublic override System.IAsyncResult BeginWrite(byte[] buffer, int offset,\n\t\t\t\tint count, System.AsyncCallback callback, object state) {\n\t\t\tthrow new System.NotSupportedException();\n\t\t}\n\t\tpublic override void Write(byte[] buffer, int offset, int count) {\n\t\t\tthrow new System.NotSupportedException();\n\t\t}\n\n\t\tpublic override void Flush() {}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/BrotliRuntimeException.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Unchecked exception used internally.</summary>\n\t[System.Serializable]\n\tinternal class BrotliRuntimeException : System.Exception\n\t{\n\t\tinternal BrotliRuntimeException(string message)\n\t\t\t: base(message)\n\t\t{\n\t\t}\n\n\t\tinternal BrotliRuntimeException(string message, System.Exception cause)\n\t\t\t: base(message, cause)\n\t\t{\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/Context.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Common context lookup table for all context modes.</summary>\n\tinternal sealed class Context\n\t{\n\t\tinternal static readonly int[] Lookup = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12, 44, 44, 44, 44, 44, 44, 44, 44\n\t\t\t, 44, 44, 32, 32, 24, 40, 28, 12, 12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12, 12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56, 60, 60, 60, 60\n\t\t\t, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, \n\t\t\t2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \n\t\t\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, \n\t\t\t1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \n\t\t\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \n\t\t\t0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \n\t\t\t3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, \n\t\t\t4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, \n\t\t\t6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \n\t\t\t16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, \n\t\t\t24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, \n\t\t\t32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, \n\t\t\t40, 40, 40, 40, 40, 40, 40, 40, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38\n\t\t\t, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, \n\t\t\t37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35\n\t\t\t, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, \n\t\t\t34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, \n\t\t\t10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, \n\t\t\t25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, \n\t\t\t40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, \n\t\t\t55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \n\t\t\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \n\t\t\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \n\t\t\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\n\n\t\tinternal static readonly int[] LookupOffsets = new int[] { 1024, 1536, 1280, 1536, 0, 256, 768, 512 };\n\t\t// CONTEXT_UTF8, last byte.\n\t\t// ASCII range.\n\t\t// UTF8 continuation byte range.\n\t\t// UTF8 lead byte range.\n\t\t// CONTEXT_UTF8 second last byte.\n\t\t// ASCII range.\n\t\t// UTF8 continuation byte range.\n\t\t// UTF8 lead byte range.\n\t\t// CONTEXT_SIGNED, second last byte.\n\t\t// CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits.\n\t\t// CONTEXT_LSB6, last byte.\n\t\t// CONTEXT_MSB6, last byte.\n\t\t// CONTEXT_{M,L}SB6, second last byte,\n\t\t// CONTEXT_LSB6\n\t\t// CONTEXT_MSB6\n\t\t// CONTEXT_UTF8\n\t\t// CONTEXT_SIGNED\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/Decode.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>API for Brotli decompression.</summary>\n\tinternal sealed class Decode\n\t{\n\t\tprivate const int DefaultCodeLength = 8;\n\n\t\tprivate const int CodeLengthRepeatCode = 16;\n\n\t\tprivate const int NumLiteralCodes = 256;\n\n\t\tprivate const int NumInsertAndCopyCodes = 704;\n\n\t\tprivate const int NumBlockLengthCodes = 26;\n\n\t\tprivate const int LiteralContextBits = 6;\n\n\t\tprivate const int DistanceContextBits = 2;\n\n\t\tprivate const int HuffmanTableBits = 8;\n\n\t\tprivate const int HuffmanTableMask = unchecked((int)(0xFF));\n\n\t\tprivate const int CodeLengthCodes = 18;\n\n\t\tprivate static readonly int[] CodeLengthCodeOrder = new int[] { 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15 };\n\n\t\tprivate const int NumDistanceShortCodes = 16;\n\n\t\tprivate static readonly int[] DistanceShortCodeIndexOffset = new int[] { 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };\n\n\t\tprivate static readonly int[] DistanceShortCodeValueOffset = new int[] { 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3 };\n\n\t\t/// <summary>Static Huffman code for the code length code lengths.</summary>\n\t\tprivate static readonly int[] FixedTable = new int[] { unchecked((int)(0x020000)), unchecked((int)(0x020004)), unchecked((int)(0x020003)), unchecked((int)(0x030002)), unchecked((int)(0x020000)), unchecked((int)(0x020004)), unchecked((int)(0x020003\n\t\t\t)), unchecked((int)(0x040001)), unchecked((int)(0x020000)), unchecked((int)(0x020004)), unchecked((int)(0x020003)), unchecked((int)(0x030002)), unchecked((int)(0x020000)), unchecked((int)(0x020004)), unchecked((int)(0x020003)), unchecked((int\n\t\t\t)(0x040005)) };\n\n\t\t/// <summary>Decodes a number in the range [0..255], by reading 1 - 11 bits.</summary>\n\t\tprivate static int DecodeVarLenUnsignedByte(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tif (Org.Brotli.Dec.BitReader.ReadBits(br, 1) != 0)\n\t\t\t{\n\t\t\t\tint n = Org.Brotli.Dec.BitReader.ReadBits(br, 3);\n\t\t\t\tif (n == 0)\n\t\t\t\t{\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn Org.Brotli.Dec.BitReader.ReadBits(br, n) + (1 << n);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\n\t\tprivate static void DecodeMetaBlockLength(Org.Brotli.Dec.BitReader br, Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tstate.inputEnd = Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1;\n\t\t\tstate.metaBlockLength = 0;\n\t\t\tstate.isUncompressed = false;\n\t\t\tstate.isMetadata = false;\n\t\t\tif (state.inputEnd && Org.Brotli.Dec.BitReader.ReadBits(br, 1) != 0)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tint sizeNibbles = Org.Brotli.Dec.BitReader.ReadBits(br, 2) + 4;\n\t\t\tif (sizeNibbles == 7)\n\t\t\t{\n\t\t\t\tstate.isMetadata = true;\n\t\t\t\tif (Org.Brotli.Dec.BitReader.ReadBits(br, 1) != 0)\n\t\t\t\t{\n\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Corrupted reserved bit\");\n\t\t\t\t}\n\t\t\t\tint sizeBytes = Org.Brotli.Dec.BitReader.ReadBits(br, 2);\n\t\t\t\tif (sizeBytes == 0)\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (int i = 0; i < sizeBytes; i++)\n\t\t\t\t{\n\t\t\t\t\tint bits = Org.Brotli.Dec.BitReader.ReadBits(br, 8);\n\t\t\t\t\tif (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Exuberant nibble\");\n\t\t\t\t\t}\n\t\t\t\t\tstate.metaBlockLength |= bits << (i * 8);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (int i = 0; i < sizeNibbles; i++)\n\t\t\t\t{\n\t\t\t\t\tint bits = Org.Brotli.Dec.BitReader.ReadBits(br, 4);\n\t\t\t\t\tif (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Exuberant nibble\");\n\t\t\t\t\t}\n\t\t\t\t\tstate.metaBlockLength |= bits << (i * 4);\n\t\t\t\t}\n\t\t\t}\n\t\t\tstate.metaBlockLength++;\n\t\t\tif (!state.inputEnd)\n\t\t\t{\n\t\t\t\tstate.isUncompressed = Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>Decodes the next Huffman code from bit-stream.</summary>\n\t\tprivate static int ReadSymbol(int[] table, int offset, Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tint val = (int)((long)(((ulong)br.accumulator) >> br.bitOffset));\n\t\t\toffset += val & HuffmanTableMask;\n\t\t\tint bits = table[offset] >> 16;\n\t\t\tint sym = table[offset] & unchecked((int)(0xFFFF));\n\t\t\tif (bits <= HuffmanTableBits)\n\t\t\t{\n\t\t\t\tbr.bitOffset += bits;\n\t\t\t\treturn sym;\n\t\t\t}\n\t\t\toffset += sym;\n\t\t\tint mask = (1 << bits) - 1;\n\t\t\toffset += (int)(((uint)(val & mask)) >> HuffmanTableBits);\n\t\t\tbr.bitOffset += ((table[offset] >> 16) + HuffmanTableBits);\n\t\t\treturn table[offset] & unchecked((int)(0xFFFF));\n\t\t}\n\n\t\tprivate static int ReadBlockLength(int[] table, int offset, Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\tint code = ReadSymbol(table, offset, br);\n\t\t\tint n = Org.Brotli.Dec.Prefix.BlockLengthNBits[code];\n\t\t\treturn Org.Brotli.Dec.Prefix.BlockLengthOffset[code] + Org.Brotli.Dec.BitReader.ReadBits(br, n);\n\t\t}\n\n\t\tprivate static int TranslateShortCodes(int code, int[] ringBuffer, int index)\n\t\t{\n\t\t\tif (code < NumDistanceShortCodes)\n\t\t\t{\n\t\t\t\tindex += DistanceShortCodeIndexOffset[code];\n\t\t\t\tindex &= 3;\n\t\t\t\treturn ringBuffer[index] + DistanceShortCodeValueOffset[code];\n\t\t\t}\n\t\t\treturn code - NumDistanceShortCodes + 1;\n\t\t}\n\n\t\tprivate static void MoveToFront(int[] v, int index)\n\t\t{\n\t\t\tint value = v[index];\n\t\t\tfor (; index > 0; index--)\n\t\t\t{\n\t\t\t\tv[index] = v[index - 1];\n\t\t\t}\n\t\t\tv[0] = value;\n\t\t}\n\n\t\tprivate static void InverseMoveToFrontTransform(byte[] v, int vLen)\n\t\t{\n\t\t\tint[] mtf = new int[256];\n\t\t\tfor (int i = 0; i < 256; i++)\n\t\t\t{\n\t\t\t\tmtf[i] = i;\n\t\t\t}\n\t\t\tfor (int i = 0; i < vLen; i++)\n\t\t\t{\n\t\t\t\tint index = v[i] & unchecked((int)(0xFF));\n\t\t\t\tv[i] = unchecked((byte)mtf[index]);\n\t\t\t\tif (index != 0)\n\t\t\t\t{\n\t\t\t\t\tMoveToFront(mtf, index);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate static void ReadHuffmanCodeLengths(int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths, Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tint symbol = 0;\n\t\t\tint prevCodeLen = DefaultCodeLength;\n\t\t\tint repeat = 0;\n\t\t\tint repeatCodeLen = 0;\n\t\t\tint space = 32768;\n\t\t\tint[] table = new int[32];\n\t\t\tOrg.Brotli.Dec.Huffman.BuildHuffmanTable(table, 0, 5, codeLengthCodeLengths, CodeLengthCodes);\n\t\t\twhile (symbol < numSymbols && space > 0)\n\t\t\t{\n\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\t\tint p = (int)(((long)(((ulong)br.accumulator) >> br.bitOffset))) & 31;\n\t\t\t\tbr.bitOffset += table[p] >> 16;\n\t\t\t\tint codeLen = table[p] & unchecked((int)(0xFFFF));\n\t\t\t\tif (codeLen < CodeLengthRepeatCode)\n\t\t\t\t{\n\t\t\t\t\trepeat = 0;\n\t\t\t\t\tcodeLengths[symbol++] = codeLen;\n\t\t\t\t\tif (codeLen != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tprevCodeLen = codeLen;\n\t\t\t\t\t\tspace -= 32768 >> codeLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tint extraBits = codeLen - 14;\n\t\t\t\t\tint newLen = 0;\n\t\t\t\t\tif (codeLen == CodeLengthRepeatCode)\n\t\t\t\t\t{\n\t\t\t\t\t\tnewLen = prevCodeLen;\n\t\t\t\t\t}\n\t\t\t\t\tif (repeatCodeLen != newLen)\n\t\t\t\t\t{\n\t\t\t\t\t\trepeat = 0;\n\t\t\t\t\t\trepeatCodeLen = newLen;\n\t\t\t\t\t}\n\t\t\t\t\tint oldRepeat = repeat;\n\t\t\t\t\tif (repeat > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\trepeat -= 2;\n\t\t\t\t\t\trepeat <<= extraBits;\n\t\t\t\t\t}\n\t\t\t\t\trepeat += Org.Brotli.Dec.BitReader.ReadBits(br, extraBits) + 3;\n\t\t\t\t\tint repeatDelta = repeat - oldRepeat;\n\t\t\t\t\tif (symbol + repeatDelta > numSymbols)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"symbol + repeatDelta > numSymbols\");\n\t\t\t\t\t}\n\t\t\t\t\t// COV_NF_LINE\n\t\t\t\t\tfor (int i = 0; i < repeatDelta; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tcodeLengths[symbol++] = repeatCodeLen;\n\t\t\t\t\t}\n\t\t\t\t\tif (repeatCodeLen != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tspace -= repeatDelta << (15 - repeatCodeLen);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (space != 0)\n\t\t\t{\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Unused space\");\n\t\t\t}\n\t\t\t// COV_NF_LINE\n\t\t\t// TODO: Pass max_symbol to Huffman table builder instead?\n\t\t\tOrg.Brotli.Dec.Utils.FillWithZeroes(codeLengths, symbol, numSymbols - symbol);\n\t\t}\n\n\t\t// TODO: Use specialized versions for smaller tables.\n\t\tinternal static void ReadHuffmanCode(int alphabetSize, int[] table, int offset, Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tbool ok = true;\n\t\t\tint simpleCodeOrSkip;\n\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t// TODO: Avoid allocation.\n\t\t\tint[] codeLengths = new int[alphabetSize];\n\t\t\tsimpleCodeOrSkip = Org.Brotli.Dec.BitReader.ReadBits(br, 2);\n\t\t\tif (simpleCodeOrSkip == 1)\n\t\t\t{\n\t\t\t\t// Read symbols, codes & code lengths directly.\n\t\t\t\tint maxBitsCounter = alphabetSize - 1;\n\t\t\t\tint maxBits = 0;\n\t\t\t\tint[] symbols = new int[4];\n\t\t\t\tint numSymbols = Org.Brotli.Dec.BitReader.ReadBits(br, 2) + 1;\n\t\t\t\twhile (maxBitsCounter != 0)\n\t\t\t\t{\n\t\t\t\t\tmaxBitsCounter >>= 1;\n\t\t\t\t\tmaxBits++;\n\t\t\t\t}\n\t\t\t\t// TODO: uncomment when codeLengths is reused.\n\t\t\t\t// Utils.fillWithZeroes(codeLengths, 0, alphabetSize);\n\t\t\t\tfor (int i = 0; i < numSymbols; i++)\n\t\t\t\t{\n\t\t\t\t\tsymbols[i] = Org.Brotli.Dec.BitReader.ReadBits(br, maxBits) % alphabetSize;\n\t\t\t\t\tcodeLengths[symbols[i]] = 2;\n\t\t\t\t}\n\t\t\t\tcodeLengths[symbols[0]] = 1;\n\t\t\t\tswitch (numSymbols)\n\t\t\t\t{\n\t\t\t\t\tcase 1:\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 2:\n\t\t\t\t\t{\n\t\t\t\t\t\tok = symbols[0] != symbols[1];\n\t\t\t\t\t\tcodeLengths[symbols[1]] = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 3:\n\t\t\t\t\t{\n\t\t\t\t\t\tok = symbols[0] != symbols[1] && symbols[0] != symbols[2] && symbols[1] != symbols[2];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 4:\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\tok = symbols[0] != symbols[1] && symbols[0] != symbols[2] && symbols[0] != symbols[3] && symbols[1] != symbols[2] && symbols[1] != symbols[3] && symbols[2] != symbols[3];\n\t\t\t\t\t\tif (Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcodeLengths[symbols[2]] = 3;\n\t\t\t\t\t\t\tcodeLengths[symbols[3]] = 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcodeLengths[symbols[0]] = 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Decode Huffman-coded code lengths.\n\t\t\t\tint[] codeLengthCodeLengths = new int[CodeLengthCodes];\n\t\t\t\tint space = 32;\n\t\t\t\tint numCodes = 0;\n\t\t\t\tfor (int i = simpleCodeOrSkip; i < CodeLengthCodes && space > 0; i++)\n\t\t\t\t{\n\t\t\t\t\tint codeLenIdx = CodeLengthCodeOrder[i];\n\t\t\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\t\t\tint p = (int)((long)(((ulong)br.accumulator) >> br.bitOffset)) & 15;\n\t\t\t\t\t// TODO: Demultiplex FIXED_TABLE.\n\t\t\t\t\tbr.bitOffset += FixedTable[p] >> 16;\n\t\t\t\t\tint v = FixedTable[p] & unchecked((int)(0xFFFF));\n\t\t\t\t\tcodeLengthCodeLengths[codeLenIdx] = v;\n\t\t\t\t\tif (v != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tspace -= (32 >> v);\n\t\t\t\t\t\tnumCodes++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tok = (numCodes == 1 || space == 0);\n\t\t\t\tReadHuffmanCodeLengths(codeLengthCodeLengths, alphabetSize, codeLengths, br);\n\t\t\t}\n\t\t\tif (!ok)\n\t\t\t{\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Can't readHuffmanCode\");\n\t\t\t}\n\t\t\t// COV_NF_LINE\n\t\t\tOrg.Brotli.Dec.Huffman.BuildHuffmanTable(table, offset, HuffmanTableBits, codeLengths, alphabetSize);\n\t\t}\n\n\t\tprivate static int DecodeContextMap(int contextMapSize, byte[] contextMap, Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\tint numTrees = DecodeVarLenUnsignedByte(br) + 1;\n\t\t\tif (numTrees == 1)\n\t\t\t{\n\t\t\t\tOrg.Brotli.Dec.Utils.FillWithZeroes(contextMap, 0, contextMapSize);\n\t\t\t\treturn numTrees;\n\t\t\t}\n\t\t\tbool useRleForZeros = Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1;\n\t\t\tint maxRunLengthPrefix = 0;\n\t\t\tif (useRleForZeros)\n\t\t\t{\n\t\t\t\tmaxRunLengthPrefix = Org.Brotli.Dec.BitReader.ReadBits(br, 4) + 1;\n\t\t\t}\n\t\t\tint[] table = new int[Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];\n\t\t\tReadHuffmanCode(numTrees + maxRunLengthPrefix, table, 0, br);\n\t\t\tfor (int i = 0; i < contextMapSize; )\n\t\t\t{\n\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\t\tint code = ReadSymbol(table, 0, br);\n\t\t\t\tif (code == 0)\n\t\t\t\t{\n\t\t\t\t\tcontextMap[i] = 0;\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\telse if (code <= maxRunLengthPrefix)\n\t\t\t\t{\n\t\t\t\t\tint reps = (1 << code) + Org.Brotli.Dec.BitReader.ReadBits(br, code);\n\t\t\t\t\twhile (reps != 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (i >= contextMapSize)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Corrupted context map\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// COV_NF_LINE\n\t\t\t\t\t\tcontextMap[i] = 0;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\treps--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcontextMap[i] = unchecked((byte)(code - maxRunLengthPrefix));\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1)\n\t\t\t{\n\t\t\t\tInverseMoveToFrontTransform(contextMap, contextMapSize);\n\t\t\t}\n\t\t\treturn numTrees;\n\t\t}\n\n\t\tprivate static void DecodeBlockTypeAndLength(Org.Brotli.Dec.State state, int treeType)\n\t\t{\n\t\t\tOrg.Brotli.Dec.BitReader br = state.br;\n\t\t\tint[] ringBuffers = state.blockTypeRb;\n\t\t\tint offset = treeType * 2;\n\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\tint blockType = ReadSymbol(state.blockTypeTrees, treeType * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);\n\t\t\tstate.blockLength[treeType] = ReadBlockLength(state.blockLenTrees, treeType * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);\n\t\t\tif (blockType == 1)\n\t\t\t{\n\t\t\t\tblockType = ringBuffers[offset + 1] + 1;\n\t\t\t}\n\t\t\telse if (blockType == 0)\n\t\t\t{\n\t\t\t\tblockType = ringBuffers[offset];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tblockType -= 2;\n\t\t\t}\n\t\t\tif (blockType >= state.numBlockTypes[treeType])\n\t\t\t{\n\t\t\t\tblockType -= state.numBlockTypes[treeType];\n\t\t\t}\n\t\t\tringBuffers[offset] = ringBuffers[offset + 1];\n\t\t\tringBuffers[offset + 1] = blockType;\n\t\t}\n\n\t\tprivate static void DecodeLiteralBlockSwitch(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tDecodeBlockTypeAndLength(state, 0);\n\t\t\tint literalBlockType = state.blockTypeRb[1];\n\t\t\tstate.contextMapSlice = literalBlockType << LiteralContextBits;\n\t\t\tstate.literalTreeIndex = state.contextMap[state.contextMapSlice] & unchecked((int)(0xFF));\n\t\t\tstate.literalTree = state.hGroup0.trees[state.literalTreeIndex];\n\t\t\tint contextMode = state.contextModes[literalBlockType];\n\t\t\tstate.contextLookupOffset1 = Org.Brotli.Dec.Context.LookupOffsets[contextMode];\n\t\t\tstate.contextLookupOffset2 = Org.Brotli.Dec.Context.LookupOffsets[contextMode + 1];\n\t\t}\n\n\t\tprivate static void DecodeCommandBlockSwitch(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tDecodeBlockTypeAndLength(state, 1);\n\t\t\tstate.treeCommandOffset = state.hGroup1.trees[state.blockTypeRb[3]];\n\t\t}\n\n\t\tprivate static void DecodeDistanceBlockSwitch(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tDecodeBlockTypeAndLength(state, 2);\n\t\t\tstate.distContextMapSlice = state.blockTypeRb[5] << DistanceContextBits;\n\t\t}\n\n\t\tprivate static void MaybeReallocateRingBuffer(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tint newSize = state.maxRingBufferSize;\n\t\t\tif ((long)newSize > state.expectedTotalSize)\n\t\t\t{\n\t\t\t\t/* TODO: Handle 2GB+ cases more gracefully. */\n\t\t\t\tint minimalNewSize = (int)state.expectedTotalSize + state.customDictionary.Length;\n\t\t\t\twhile ((newSize >> 1) > minimalNewSize)\n\t\t\t\t{\n\t\t\t\t\tnewSize >>= 1;\n\t\t\t\t}\n\t\t\t\tif (!state.inputEnd && newSize < 16384 && state.maxRingBufferSize >= 16384)\n\t\t\t\t{\n\t\t\t\t\tnewSize = 16384;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (newSize <= state.ringBufferSize)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tint ringBufferSizeWithSlack = newSize + Org.Brotli.Dec.Dictionary.MaxTransformedWordLength;\n\t\t\tbyte[] newBuffer = new byte[ringBufferSizeWithSlack];\n\t\t\tif (state.ringBuffer != null)\n\t\t\t{\n\t\t\t\tSystem.Array.Copy(state.ringBuffer, 0, newBuffer, 0, state.ringBufferSize);\n\t\t\t}\n\t\t\telse if (state.customDictionary.Length != 0)\n\t\t\t{\n\t\t\t\t/* Prepend custom dictionary, if any. */\n\t\t\t\tint length = state.customDictionary.Length;\n\t\t\t\tint offset = 0;\n\t\t\t\tif (length > state.maxBackwardDistance)\n\t\t\t\t{\n\t\t\t\t\toffset = length - state.maxBackwardDistance;\n\t\t\t\t\tlength = state.maxBackwardDistance;\n\t\t\t\t}\n\t\t\t\tSystem.Array.Copy(state.customDictionary, offset, newBuffer, 0, length);\n\t\t\t\tstate.pos = length;\n\t\t\t\tstate.bytesToIgnore = length;\n\t\t\t}\n\t\t\tstate.ringBuffer = newBuffer;\n\t\t\tstate.ringBufferSize = newSize;\n\t\t}\n\n\t\t/// <summary>Reads next metablock header.</summary>\n\t\t/// <param name=\"state\">decoding state</param>\n\t\tprivate static void ReadMetablockInfo(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tOrg.Brotli.Dec.BitReader br = state.br;\n\t\t\tif (state.inputEnd)\n\t\t\t{\n\t\t\t\tstate.nextRunningState = Org.Brotli.Dec.RunningState.Finished;\n\t\t\t\tstate.bytesToWrite = state.pos;\n\t\t\t\tstate.bytesWritten = 0;\n\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Write;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// TODO: Reset? Do we need this?\n\t\t\tstate.hGroup0.codes = null;\n\t\t\tstate.hGroup0.trees = null;\n\t\t\tstate.hGroup1.codes = null;\n\t\t\tstate.hGroup1.trees = null;\n\t\t\tstate.hGroup2.codes = null;\n\t\t\tstate.hGroup2.trees = null;\n\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\tDecodeMetaBlockLength(br, state);\n\t\t\tif (state.metaBlockLength == 0 && !state.isMetadata)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (state.isUncompressed || state.isMetadata)\n\t\t\t{\n\t\t\t\tOrg.Brotli.Dec.BitReader.JumpToByteBoundary(br);\n\t\t\t\tstate.runningState = state.isMetadata ? Org.Brotli.Dec.RunningState.ReadMetadata : Org.Brotli.Dec.RunningState.CopyUncompressed;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.CompressedBlockStart;\n\t\t\t}\n\t\t\tif (state.isMetadata)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstate.expectedTotalSize += state.metaBlockLength;\n\t\t\tif (state.ringBufferSize < state.maxRingBufferSize)\n\t\t\t{\n\t\t\t\tMaybeReallocateRingBuffer(state);\n\t\t\t}\n\t\t}\n\n\t\tprivate static void ReadMetablockHuffmanCodesAndContextMaps(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tOrg.Brotli.Dec.BitReader br = state.br;\n\t\t\tfor (int i = 0; i < 3; i++)\n\t\t\t{\n\t\t\t\tstate.numBlockTypes[i] = DecodeVarLenUnsignedByte(br) + 1;\n\t\t\t\tstate.blockLength[i] = 1 << 28;\n\t\t\t\tif (state.numBlockTypes[i] > 1)\n\t\t\t\t{\n\t\t\t\t\tReadHuffmanCode(state.numBlockTypes[i] + 2, state.blockTypeTrees, i * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);\n\t\t\t\t\tReadHuffmanCode(NumBlockLengthCodes, state.blockLenTrees, i * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);\n\t\t\t\t\tstate.blockLength[i] = ReadBlockLength(state.blockLenTrees, i * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);\n\t\t\t\t}\n\t\t\t}\n\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\tstate.distancePostfixBits = Org.Brotli.Dec.BitReader.ReadBits(br, 2);\n\t\t\tstate.numDirectDistanceCodes = NumDistanceShortCodes + (Org.Brotli.Dec.BitReader.ReadBits(br, 4) << state.distancePostfixBits);\n\t\t\tstate.distancePostfixMask = (1 << state.distancePostfixBits) - 1;\n\t\t\tint numDistanceCodes = state.numDirectDistanceCodes + (48 << state.distancePostfixBits);\n\t\t\t// TODO: Reuse?\n\t\t\tstate.contextModes = new byte[state.numBlockTypes[0]];\n\t\t\tfor (int i = 0; i < state.numBlockTypes[0]; )\n\t\t\t{\n\t\t\t\t/* Ensure that less than 256 bits read between readMoreInput. */\n\t\t\t\tint limit = System.Math.Min(i + 96, state.numBlockTypes[0]);\n\t\t\t\tfor (; i < limit; ++i)\n\t\t\t\t{\n\t\t\t\t\tstate.contextModes[i] = unchecked((byte)(Org.Brotli.Dec.BitReader.ReadBits(br, 2) << 1));\n\t\t\t\t}\n\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t}\n\t\t\t// TODO: Reuse?\n\t\t\tstate.contextMap = new byte[state.numBlockTypes[0] << LiteralContextBits];\n\t\t\tint numLiteralTrees = DecodeContextMap(state.numBlockTypes[0] << LiteralContextBits, state.contextMap, br);\n\t\t\tstate.trivialLiteralContext = true;\n\t\t\tfor (int j = 0; j < state.numBlockTypes[0] << LiteralContextBits; j++)\n\t\t\t{\n\t\t\t\tif (state.contextMap[j] != j >> LiteralContextBits)\n\t\t\t\t{\n\t\t\t\t\tstate.trivialLiteralContext = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// TODO: Reuse?\n\t\t\tstate.distContextMap = new byte[state.numBlockTypes[2] << DistanceContextBits];\n\t\t\tint numDistTrees = DecodeContextMap(state.numBlockTypes[2] << DistanceContextBits, state.distContextMap, br);\n\t\t\tOrg.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup0, NumLiteralCodes, numLiteralTrees);\n\t\t\tOrg.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup1, NumInsertAndCopyCodes, state.numBlockTypes[1]);\n\t\t\tOrg.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup2, numDistanceCodes, numDistTrees);\n\t\t\tOrg.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup0, br);\n\t\t\tOrg.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup1, br);\n\t\t\tOrg.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup2, br);\n\t\t\tstate.contextMapSlice = 0;\n\t\t\tstate.distContextMapSlice = 0;\n\t\t\tstate.contextLookupOffset1 = Org.Brotli.Dec.Context.LookupOffsets[state.contextModes[0]];\n\t\t\tstate.contextLookupOffset2 = Org.Brotli.Dec.Context.LookupOffsets[state.contextModes[0] + 1];\n\t\t\tstate.literalTreeIndex = 0;\n\t\t\tstate.literalTree = state.hGroup0.trees[0];\n\t\t\tstate.treeCommandOffset = state.hGroup1.trees[0];\n\t\t\t// TODO: == 0?\n\t\t\tstate.blockTypeRb[0] = state.blockTypeRb[2] = state.blockTypeRb[4] = 1;\n\t\t\tstate.blockTypeRb[1] = state.blockTypeRb[3] = state.blockTypeRb[5] = 0;\n\t\t}\n\n\t\tprivate static void CopyUncompressedData(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tOrg.Brotli.Dec.BitReader br = state.br;\n\t\t\tbyte[] ringBuffer = state.ringBuffer;\n\t\t\t// Could happen if block ends at ring buffer end.\n\t\t\tif (state.metaBlockLength <= 0)\n\t\t\t{\n\t\t\t\tOrg.Brotli.Dec.BitReader.Reload(br);\n\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.BlockStart;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tint chunkLength = System.Math.Min(state.ringBufferSize - state.pos, state.metaBlockLength);\n\t\t\tOrg.Brotli.Dec.BitReader.CopyBytes(br, ringBuffer, state.pos, chunkLength);\n\t\t\tstate.metaBlockLength -= chunkLength;\n\t\t\tstate.pos += chunkLength;\n\t\t\tif (state.pos == state.ringBufferSize)\n\t\t\t{\n\t\t\t\tstate.nextRunningState = Org.Brotli.Dec.RunningState.CopyUncompressed;\n\t\t\t\tstate.bytesToWrite = state.ringBufferSize;\n\t\t\t\tstate.bytesWritten = 0;\n\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Write;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tOrg.Brotli.Dec.BitReader.Reload(br);\n\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.BlockStart;\n\t\t}\n\n\t\tprivate static bool WriteRingBuffer(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\t/* Ignore custom dictionary bytes. */\n\t\t\tif (state.bytesToIgnore != 0)\n\t\t\t{\n\t\t\t\tstate.bytesWritten += state.bytesToIgnore;\n\t\t\t\tstate.bytesToIgnore = 0;\n\t\t\t}\n\t\t\tint toWrite = System.Math.Min(state.outputLength - state.outputUsed, state.bytesToWrite - state.bytesWritten);\n\t\t\tif (toWrite != 0)\n\t\t\t{\n\t\t\t\tSystem.Array.Copy(state.ringBuffer, state.bytesWritten, state.output, state.outputOffset + state.outputUsed, toWrite);\n\t\t\t\tstate.outputUsed += toWrite;\n\t\t\t\tstate.bytesWritten += toWrite;\n\t\t\t}\n\t\t\treturn state.outputUsed < state.outputLength;\n\t\t}\n\n\t\tinternal static void SetCustomDictionary(Org.Brotli.Dec.State state, byte[] data)\n\t\t{\n\t\t\tstate.customDictionary = (data == null) ? new byte[0] : data;\n\t\t}\n\n\t\t/// <summary>Actual decompress implementation.</summary>\n\t\tinternal static void Decompress(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tif (state.runningState == Org.Brotli.Dec.RunningState.Uninitialized)\n\t\t\t{\n\t\t\t\tthrow new System.InvalidOperationException(\"Can't decompress until initialized\");\n\t\t\t}\n\t\t\tif (state.runningState == Org.Brotli.Dec.RunningState.Closed)\n\t\t\t{\n\t\t\t\tthrow new System.InvalidOperationException(\"Can't decompress after close\");\n\t\t\t}\n\t\t\tOrg.Brotli.Dec.BitReader br = state.br;\n\t\t\tint ringBufferMask = state.ringBufferSize - 1;\n\t\t\tbyte[] ringBuffer = state.ringBuffer;\n\t\t\twhile (state.runningState != Org.Brotli.Dec.RunningState.Finished)\n\t\t\t{\n\t\t\t\tswitch (state.runningState)\n\t\t\t\t{\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.BlockStart:\n\t\t\t\t\t{\n\t\t\t\t\t\t// TODO: extract cases to methods for the better readability.\n\t\t\t\t\t\tif (state.metaBlockLength < 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Invalid metablock length\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tReadMetablockInfo(state);\n\t\t\t\t\t\t/* Ring-buffer would be reallocated here. */\n\t\t\t\t\t\tringBufferMask = state.ringBufferSize - 1;\n\t\t\t\t\t\tringBuffer = state.ringBuffer;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.CompressedBlockStart:\n\t\t\t\t\t{\n\t\t\t\t\t\tReadMetablockHuffmanCodesAndContextMaps(state);\n\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.MainLoop;\n\t\t\t\t\t\tgoto case Org.Brotli.Dec.RunningState.MainLoop;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.MainLoop:\n\t\t\t\t\t{\n\t\t\t\t\t\t// Fall through\n\t\t\t\t\t\tif (state.metaBlockLength <= 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.BlockStart;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t\t\t\tif (state.blockLength[1] == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDecodeCommandBlockSwitch(state);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.blockLength[1]--;\n\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\t\t\t\tint cmdCode = ReadSymbol(state.hGroup1.codes, state.treeCommandOffset, br);\n\t\t\t\t\t\tint rangeIdx = (int)(((uint)cmdCode) >> 6);\n\t\t\t\t\t\tstate.distanceCode = 0;\n\t\t\t\t\t\tif (rangeIdx >= 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trangeIdx -= 2;\n\t\t\t\t\t\t\tstate.distanceCode = -1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tint insertCode = Org.Brotli.Dec.Prefix.InsertRangeLut[rangeIdx] + (((int)(((uint)cmdCode) >> 3)) & 7);\n\t\t\t\t\t\tint copyCode = Org.Brotli.Dec.Prefix.CopyRangeLut[rangeIdx] + (cmdCode & 7);\n\t\t\t\t\t\tstate.insertLength = Org.Brotli.Dec.Prefix.InsertLengthOffset[insertCode] + Org.Brotli.Dec.BitReader.ReadBits(br, Org.Brotli.Dec.Prefix.InsertLengthNBits[insertCode]);\n\t\t\t\t\t\tstate.copyLength = Org.Brotli.Dec.Prefix.CopyLengthOffset[copyCode] + Org.Brotli.Dec.BitReader.ReadBits(br, Org.Brotli.Dec.Prefix.CopyLengthNBits[copyCode]);\n\t\t\t\t\t\tstate.j = 0;\n\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.InsertLoop;\n\t\t\t\t\t\tgoto case Org.Brotli.Dec.RunningState.InsertLoop;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.InsertLoop:\n\t\t\t\t\t{\n\t\t\t\t\t\t// Fall through\n\t\t\t\t\t\tif (state.trivialLiteralContext)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\twhile (state.j < state.insertLength)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t\t\t\t\t\tif (state.blockLength[0] == 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tDecodeLiteralBlockSwitch(state);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tstate.blockLength[0]--;\n\t\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\t\t\t\t\t\tringBuffer[state.pos] = unchecked((byte)ReadSymbol(state.hGroup0.codes, state.literalTree, br));\n\t\t\t\t\t\t\t\tstate.j++;\n\t\t\t\t\t\t\t\tif (state.pos++ == ringBufferMask)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstate.nextRunningState = Org.Brotli.Dec.RunningState.InsertLoop;\n\t\t\t\t\t\t\t\t\tstate.bytesToWrite = state.ringBufferSize;\n\t\t\t\t\t\t\t\t\tstate.bytesWritten = 0;\n\t\t\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Write;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint prevByte1 = ringBuffer[(state.pos - 1) & ringBufferMask] & unchecked((int)(0xFF));\n\t\t\t\t\t\t\tint prevByte2 = ringBuffer[(state.pos - 2) & ringBufferMask] & unchecked((int)(0xFF));\n\t\t\t\t\t\t\twhile (state.j < state.insertLength)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t\t\t\t\t\tif (state.blockLength[0] == 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tDecodeLiteralBlockSwitch(state);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tint literalTreeIndex = state.contextMap[state.contextMapSlice + (Org.Brotli.Dec.Context.Lookup[state.contextLookupOffset1 + prevByte1] | Org.Brotli.Dec.Context.Lookup[state.contextLookupOffset2 + prevByte2])] & unchecked((int)(0xFF));\n\t\t\t\t\t\t\t\tstate.blockLength[0]--;\n\t\t\t\t\t\t\t\tprevByte2 = prevByte1;\n\t\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\t\t\t\t\t\tprevByte1 = ReadSymbol(state.hGroup0.codes, state.hGroup0.trees[literalTreeIndex], br);\n\t\t\t\t\t\t\t\tringBuffer[state.pos] = unchecked((byte)prevByte1);\n\t\t\t\t\t\t\t\tstate.j++;\n\t\t\t\t\t\t\t\tif (state.pos++ == ringBufferMask)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstate.nextRunningState = Org.Brotli.Dec.RunningState.InsertLoop;\n\t\t\t\t\t\t\t\t\tstate.bytesToWrite = state.ringBufferSize;\n\t\t\t\t\t\t\t\t\tstate.bytesWritten = 0;\n\t\t\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Write;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (state.runningState != Org.Brotli.Dec.RunningState.InsertLoop)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.metaBlockLength -= state.insertLength;\n\t\t\t\t\t\tif (state.metaBlockLength <= 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.MainLoop;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (state.distanceCode < 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t\t\t\t\tif (state.blockLength[2] == 0)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tDecodeDistanceBlockSwitch(state);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstate.blockLength[2]--;\n\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.FillBitWindow(br);\n\t\t\t\t\t\t\tstate.distanceCode = ReadSymbol(state.hGroup2.codes, state.hGroup2.trees[state.distContextMap[state.distContextMapSlice + (state.copyLength > 4 ? 3 : state.copyLength - 2)] & unchecked((int)(0xFF))], br);\n\t\t\t\t\t\t\tif (state.distanceCode >= state.numDirectDistanceCodes)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstate.distanceCode -= state.numDirectDistanceCodes;\n\t\t\t\t\t\t\t\tint postfix = state.distanceCode & state.distancePostfixMask;\n\t\t\t\t\t\t\t\tstate.distanceCode = (int)(((uint)state.distanceCode) >> state.distancePostfixBits);\n\t\t\t\t\t\t\t\tint n = ((int)(((uint)state.distanceCode) >> 1)) + 1;\n\t\t\t\t\t\t\t\tint offset = ((2 + (state.distanceCode & 1)) << n) - 4;\n\t\t\t\t\t\t\t\tstate.distanceCode = state.numDirectDistanceCodes + postfix + ((offset + Org.Brotli.Dec.BitReader.ReadBits(br, n)) << state.distancePostfixBits);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Convert the distance code to the actual distance by possibly looking up past distances\n\t\t\t\t\t\t// from the ringBuffer.\n\t\t\t\t\t\tstate.distance = TranslateShortCodes(state.distanceCode, state.distRb, state.distRbIdx);\n\t\t\t\t\t\tif (state.distance < 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Negative distance\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// COV_NF_LINE\n\t\t\t\t\t\tif (state.maxDistance != state.maxBackwardDistance && state.pos < state.maxBackwardDistance)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.maxDistance = state.pos;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.maxDistance = state.maxBackwardDistance;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.copyDst = state.pos;\n\t\t\t\t\t\tif (state.distance > state.maxDistance)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Transform;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (state.distanceCode > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.distRb[state.distRbIdx & 3] = state.distance;\n\t\t\t\t\t\t\tstate.distRbIdx++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (state.copyLength > state.metaBlockLength)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Invalid backward reference\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// COV_NF_LINE\n\t\t\t\t\t\tstate.j = 0;\n\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.CopyLoop;\n\t\t\t\t\t\tgoto case Org.Brotli.Dec.RunningState.CopyLoop;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.CopyLoop:\n\t\t\t\t\t{\n\t\t\t\t\t\t// fall through\n\t\t\t\t\t\tint src = (state.pos - state.distance) & ringBufferMask;\n\t\t\t\t\t\tint dst = state.pos;\n\t\t\t\t\t\tint copyLength = state.copyLength - state.j;\n\t\t\t\t\t\tif ((src + copyLength < ringBufferMask) && (dst + copyLength < ringBufferMask))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int k = 0; k < copyLength; ++k)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tringBuffer[dst++] = ringBuffer[src++];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstate.j += copyLength;\n\t\t\t\t\t\t\tstate.metaBlockLength -= copyLength;\n\t\t\t\t\t\t\tstate.pos += copyLength;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (; state.j < state.copyLength; )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tringBuffer[state.pos] = ringBuffer[(state.pos - state.distance) & ringBufferMask];\n\t\t\t\t\t\t\t\tstate.metaBlockLength--;\n\t\t\t\t\t\t\t\tstate.j++;\n\t\t\t\t\t\t\t\tif (state.pos++ == ringBufferMask)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstate.nextRunningState = Org.Brotli.Dec.RunningState.CopyLoop;\n\t\t\t\t\t\t\t\t\tstate.bytesToWrite = state.ringBufferSize;\n\t\t\t\t\t\t\t\t\tstate.bytesWritten = 0;\n\t\t\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Write;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (state.runningState == Org.Brotli.Dec.RunningState.CopyLoop)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.MainLoop;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.Transform:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (state.copyLength >= Org.Brotli.Dec.Dictionary.MinWordLength && state.copyLength <= Org.Brotli.Dec.Dictionary.MaxWordLength)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint offset = Org.Brotli.Dec.Dictionary.OffsetsByLength[state.copyLength];\n\t\t\t\t\t\t\tint wordId = state.distance - state.maxDistance - 1;\n\t\t\t\t\t\t\tint shift = Org.Brotli.Dec.Dictionary.SizeBitsByLength[state.copyLength];\n\t\t\t\t\t\t\tint mask = (1 << shift) - 1;\n\t\t\t\t\t\t\tint wordIdx = wordId & mask;\n\t\t\t\t\t\t\tint transformIdx = (int)(((uint)wordId) >> shift);\n\t\t\t\t\t\t\toffset += wordIdx * state.copyLength;\n\t\t\t\t\t\t\tif (transformIdx < Org.Brotli.Dec.Transform.Transforms.Length)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint len = Org.Brotli.Dec.Transform.TransformDictionaryWord(ringBuffer, state.copyDst, Org.Brotli.Dec.Dictionary.GetData(), offset, state.copyLength, Org.Brotli.Dec.Transform.Transforms[transformIdx]);\n\t\t\t\t\t\t\t\tstate.copyDst += len;\n\t\t\t\t\t\t\t\tstate.pos += len;\n\t\t\t\t\t\t\t\tstate.metaBlockLength -= len;\n\t\t\t\t\t\t\t\tif (state.copyDst >= state.ringBufferSize)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstate.nextRunningState = Org.Brotli.Dec.RunningState.CopyWrapBuffer;\n\t\t\t\t\t\t\t\t\tstate.bytesToWrite = state.ringBufferSize;\n\t\t\t\t\t\t\t\t\tstate.bytesWritten = 0;\n\t\t\t\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Write;\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Invalid backward reference\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// COV_NF_LINE\n\t\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Invalid backward reference\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// COV_NF_LINE\n\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.MainLoop;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.CopyWrapBuffer:\n\t\t\t\t\t{\n\t\t\t\t\t\tSystem.Array.Copy(ringBuffer, state.ringBufferSize, ringBuffer, 0, state.copyDst - state.ringBufferSize);\n\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.MainLoop;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.ReadMetadata:\n\t\t\t\t\t{\n\t\t\t\t\t\twhile (state.metaBlockLength > 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.ReadMoreInput(br);\n\t\t\t\t\t\t\t// Optimize\n\t\t\t\t\t\t\tOrg.Brotli.Dec.BitReader.ReadBits(br, 8);\n\t\t\t\t\t\t\tstate.metaBlockLength--;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.BlockStart;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.CopyUncompressed:\n\t\t\t\t\t{\n\t\t\t\t\t\tCopyUncompressedData(state);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase Org.Brotli.Dec.RunningState.Write:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!WriteRingBuffer(state))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Output buffer is full.\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (state.pos >= state.maxBackwardDistance)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstate.maxDistance = state.maxBackwardDistance;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.pos &= ringBufferMask;\n\t\t\t\t\t\tstate.runningState = state.nextRunningState;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Unexpected state \" + state.runningState);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (state.runningState == Org.Brotli.Dec.RunningState.Finished)\n\t\t\t{\n\t\t\t\tif (state.metaBlockLength < 0)\n\t\t\t\t{\n\t\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Invalid metablock length\");\n\t\t\t\t}\n\t\t\t\tOrg.Brotli.Dec.BitReader.JumpToByteBoundary(br);\n\t\t\t\tOrg.Brotli.Dec.BitReader.CheckHealth(state.br, true);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/Dictionary.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Collection of static dictionary words.</summary>\n\t/// <remarks>\n\t/// Collection of static dictionary words.\n\t/// <p>Dictionary content is loaded from binary resource when\n\t/// <see cref=\"GetData()\"/>\n\t/// is executed for the\n\t/// first time. Consequently, it saves memory and CPU in case dictionary is not required.\n\t/// <p>One possible drawback is that multiple threads that need dictionary data may be blocked (only\n\t/// once in each classworld). To avoid this, it is enough to call\n\t/// <see cref=\"GetData()\"/>\n\t/// proactively.\n\t/// </remarks>\n\tinternal sealed class Dictionary\n\t{\n\t\t/// <summary>\"Initialization-on-demand holder idiom\" implementation.</summary>\n\t\t/// <remarks>\n\t\t/// \"Initialization-on-demand holder idiom\" implementation.\n\t\t/// <p>This static class definition is not initialized until the JVM determines that it must be\n\t\t/// executed (when the static method\n\t\t/// <see cref=\"GetData()\"/>\n\t\t/// is invoked).\n\t\t/// </remarks>\n\t\tprivate class DataHolder0\n\t\t{\n\t\t\tinternal static string GetData()\n\t\t\t{\n\t\t\t\treturn \"timedownlifeleftbackcodedatashowonlysitecityopenjustlikefreeworktextyearoverbodyloveformbookplaylivelinehelphomesidemorewordlongthemviewfindpagedaysfullheadtermeachareafromtruemarkableuponhighdatelandnewsevennextcasebothpostusedmadehandherewhatnameLinkblogsizebaseheldmakemainuser') +holdendswithNewsreadweresigntakehavegameseencallpathwellplusmenufilmpartjointhislistgoodneedwayswestjobsmindalsologorichuseslastteamarmyfoodkingwilleastwardbestfirePageknowaway.pngmovethanloadgiveselfnotemuchfeedmanyrockicononcelookhidediedHomerulehostajaxinfoclublawslesshalfsomesuchzone100%onescareTimeracebluefourweekfacehopegavehardlostwhenparkkeptpassshiproomHTMLplanTypedonesavekeepflaglinksoldfivetookratetownjumpthusdarkcardfilefearstaykillthatfallautoever.comtalkshopvotedeepmoderestturnbornbandfellroseurl(skinrolecomeactsagesmeetgold.jpgitemvaryfeltthensenddropViewcopy1.0\\\"</a>stopelseliestourpack.gifpastcss?graymean&gt;rideshotlatesaidroadvar feeljohnrickportfast'UA-dead</b>poorbilltypeU.S.woodmust2px;Inforankwidewantwalllead[0];paulwavesure$('#waitmassarmsgoesgainlangpaid!-- lockunitrootwalkfirmwifexml\\\"songtest20pxkindrowstoolfontmailsafestarmapscorerainflowbabyspansays4px;6px;artsfootrealwikiheatsteptriporg/lakeweaktoldFormcastfansbankveryrunsjulytask1px;goalgrewslowedgeid=\\\"sets5px;.js?40pxif (soonseatnonetubezerosentreedfactintogiftharm18pxcamehillboldzoomvoideasyringfillpeakinitcost3px;jacktagsbitsrolleditknewnear<!--growJSONdutyNamesaleyou lotspainjazzcoldeyesfishwww.risktabsprev10pxrise25pxBlueding300,ballfordearnwildbox.fairlackverspairjunetechif(!pickevil$(\\\"#warmlorddoespull,000ideadrawhugespotfundburnhrefcellkeystickhourlossfuel12pxsuitdealRSS\\\"agedgreyGET\\\"easeaimsgirlaids8px;navygridtips#999warsladycars); }php?helltallwhomzh:\\u00E5*/\\r\\n 100hall.\\n\\nA7px;pushchat0px;crew*/</hash75pxflatrare && tellcampontolaidmissskiptentfinemalegetsplot400,\\r\\n\\r\\ncoolfeet.php<br>ericmostguidbelldeschairmathatom/img&#82luckcent000;tinygonehtmlselldrugFREEnodenick?id=losenullvastwindRSS wearrelybeensamedukenasacapewishgulfT23:hitsslotgatekickblurthey15px''););\\\">msiewinsbirdsortbetaseekT18:ordstreemall60pxfarm\\u00E2\\u0080\\u0099sboys[0].');\\\"POSTbearkids);}}marytend(UK)quadzh:\\u00E6-siz----prop');\\rliftT19:viceandydebt>RSSpoolneckblowT16:doorevalT17:letsfailoralpollnovacolsgene \\u00E2\\u0080\\u0094softrometillross<h3>pourfadepink<tr>mini)|!(minezh:\\u00E8barshear00);milk -->ironfreddiskwentsoilputs/js/holyT22:ISBNT20:adamsees<h2>json', 'contT21: RSSloopasiamoon</p>soulLINEfortcartT14:<h1>80px!--<9px;T04:mike:46ZniceinchYorkricezh:\\u00E4'));puremageparatonebond:37Z_of_']);000,zh:\\u00E7tankyardbowlbush:56ZJava30px\\n|}\\n%C3%:34ZjeffEXPIcashvisagolfsnowzh:\\u00E9quer.csssickmeatmin.binddellhirepicsrent:36ZHTTP-201fotowolfEND xbox:54ZBODYdick;\\n}\\nexit:35Zvarsbeat'});diet999;anne}}</[i].Langkm\\u00C2\\u00B2wiretoysaddssealalex;\\n\\t}echonine.org005)tonyjewssandlegsroof000) 200winegeardogsbootgarycutstyletemption.xmlcockgang$('.50pxPh.Dmiscalanloandeskmileryanunixdisc);}\\ndustclip).\\n\\n70px-200DVDs7]><tapedemoi++)wageeurophiloptsholeFAQsasin-26TlabspetsURL bulkcook;}\\r\\nHEAD[0])abbrjuan(198leshtwin</i>sonyguysfuckpipe|-\\n!002)ndow[1];[];\\nLog salt\\r\\n\\t\\tbangtrimbath){\\r\\n00px\\n});ko:\\u00ECfeesad>\\rs:// [];tollplug(){\\n{\\r\\n .js'200pdualboat.JPG);\\n}quot);\\n\\n');\\n\\r\\n}\\r201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037201320122011201020092008200720062005200420032002200120001999199819971996199519941993199219911990198919881987198619851984198319821981198019791978197719761975197419731972197119701969196819671966196519641963196219611960195919581957195619551954195319521951195010001024139400009999comom\\u00C3\\u00A1sesteestaperotodohacecadaa\\u00C3\\u00B1obiend\\u00C3\\u00ADaas\\u00C3\\u00ADvidacasootroforosolootracualdijosidograntipotemadebealgoqu\\u00C3\\u00A9estonadatrespococasabajotodasinoaguapuesunosantediceluisellamayozonaamorpisoobraclicellodioshoracasi\\u00D0\\u00B7\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u0080\\u00D0\\u00B0\\u00D1\\u0080\\u00D1\\u0083\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B6\\u00D0\\u00B5\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u0085\\u00D0\\u009D\\u00D0\\u00B0\\u00D0\\u00B5\\u00D0\\u00B5\\u00D0\\u00B1\\u00D1\\u008B\\u00D0\\u00BC\\u00D1\\u008B\\u00D0\\u0092\\u00D1\\u008B\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00B2\\u00D1\\u008B\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u009D\\u00D0\\u00BE\\u00D0\\u00BE\\u00D0\\u00B1\\u00D0\\u009F\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B8\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00A0\\u00D0\\u00A4\\u00D0\\u009D\\u00D0\\u00B5\\u00D0\\u009C\\u00D1\\u008B\\u00D1\\u0082\\u00D1\\u008B\\u00D0\\u009E\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u0097\\u00D0\\u00B0\\u00D0\\u0094\\u00D0\\u00B0\\u00D0\\u009D\\u00D1\\u0083\\u00D0\\u009E\\u00D0\\u00B1\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u0098\\u00D0\\u00B7\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u00BD\\u00D1\\u0083\\u00D0\\u00BC\\u00D0\\u00BC\\u00D0\\u00A2\\u00D1\\u008B\\u00D1\\u0083\\u00D0\\u00B6\\u00D9\\u0081\\u00D9\\u008A\\u00D8\\u00A3\\u00D9\\u0086\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00B9\\u00D9\\u0083\\u00D9\\u0084\\u00D8\\u00A3\\u00D9\\u0088\\u00D8\\u00B1\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0081\\u00D9\\u0089\\u00D9\\u0087\\u00D9\\u0088\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0084\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0088\\u00D9\\u0084\\u00D9\\u0087\\u00D8\\u00A8\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A5\\u00D9\\u0086\\u00D9\\u0087\\u00D9\\u008A\\u00D8\\u00A3\\u00D9\\u008A\\u00D9\\u0082\\u00D8\\u00AF\\u00D9\\u0087\\u00D9\\u0084\\u00D8\\u00AB\\u00D9\\u0085\\u00D8\\u00A8\\u00D9\\u0087\\u00D9\\u0084\\u00D9\\u0088\\u00D9\\u0084\\u00D9\\u008A\\u00D8\\u00A8\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u008A\\u00D8\\u00A8\\u00D9\\u0083\\u00D8\\u00B4\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00A3\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00A8\\u00D9\\u008A\\u00D9\\u0084\\u00D9\\u0086\\u00D8\\u00AD\\u00D8\\u00A8\\u00D9\\u0087\\u00D9\\u0085\\u00D9\\u0085\\u00D8\\u00B4\\u00D9\\u0088\\u00D8\\u00B4firstvideolightworldmediawhitecloseblackrightsmallbooksplacemusicfieldorderpointvalueleveltableboardhousegroupworksyearsstatetodaywaterstartstyledeathpowerphonenighterrorinputabouttermstitletoolseventlocaltimeslargewordsgamesshortspacefocusclearmodelblockguideradiosharewomenagainmoneyimagenamesyounglineslatercolorgreenfront&amp;watchforcepricerulesbeginaftervisitissueareasbelowindextotalhourslabelprintpressbuiltlinksspeedstudytradefoundsenseundershownformsrangeaddedstillmovedtakenaboveflashfixedoftenotherviewschecklegalriveritemsquickshapehumanexistgoingmoviethirdbasicpeacestagewidthloginideaswrotepagesusersdrivestorebreaksouthvoicesitesmonthwherebuildwhichearthforumthreesportpartyClicklowerlivesclasslayerentrystoryusagesoundcourtyour birthpopuptypesapplyImagebeinguppernoteseveryshowsmeansextramatchtrackknownearlybegansuperpapernorthlearngivennamedendedTermspartsGroupbrandusingwomanfalsereadyaudiotakeswhile.com/livedcasesdailychildgreatjudgethoseunitsneverbroadcoastcoverapplefilescyclesceneplansclickwritequeenpieceemailframeolderphotolimitcachecivilscaleenterthemetheretouchboundroyalaskedwholesincestock namefaithheartemptyofferscopeownedmightalbumthinkbloodarraymajortrustcanonunioncountvalidstoneStyleLoginhappyoccurleft:freshquitefilmsgradeneedsurbanfightbasishoverauto;route.htmlmixedfinalYour slidetopicbrownalonedrawnsplitreachRightdatesmarchquotegoodsLinksdoubtasyncthumballowchiefyouthnovel10px;serveuntilhandsCheckSpacequeryjamesequaltwice0,000Startpanelsongsroundeightshiftworthpostsleadsweeksavoidthesemilesplanesmartalphaplantmarksratesplaysclaimsalestextsstarswrong</h3>thing.org/multiheardPowerstandtokensolid(thisbringshipsstafftriedcallsfullyfactsagentThis //-->adminegyptEvent15px;Emailtrue\\\"crossspentblogsbox\\\">notedleavechinasizesguest</h4>robotheavytrue,sevengrandcrimesignsawaredancephase><!--en_US&#39;200px_namelatinenjoyajax.ationsmithU.S. holdspeterindianav\\\">chainscorecomesdoingpriorShare1990sromanlistsjapanfallstrialowneragree</h2>abusealertopera\\\"-//WcardshillsteamsPhototruthclean.php?saintmetallouismeantproofbriefrow\\\">genretrucklooksValueFrame.net/-->\\n<try {\\nvar makescostsplainadultquesttrainlaborhelpscausemagicmotortheir250pxleaststepsCountcouldglasssidesfundshotelawardmouthmovesparisgivesdutchtexasfruitnull,||[];top\\\">\\n<!--POST\\\"ocean<br/>floorspeakdepth sizebankscatchchart20px;aligndealswould50px;url=\\\"parksmouseMost ...</amongbrainbody none;basedcarrydraftreferpage_home.meterdelaydreamprovejoint</tr>drugs<!-- aprilidealallenexactforthcodeslogicView seemsblankports (200saved_linkgoalsgrantgreekhomesringsrated30px;whoseparse();\\\" Blocklinuxjonespixel');\\\">);if(-leftdavidhorseFocusraiseboxesTrackement</em>bar\\\">.src=toweralt=\\\"cablehenry24px;setupitalysharpminortastewantsthis.resetwheelgirls/css/100%;clubsstuffbiblevotes 1000korea});\\r\\nbandsqueue= {};80px;cking{\\r\\n\\t\\taheadclockirishlike ratiostatsForm\\\"yahoo)[0];Aboutfinds</h1>debugtasksURL =cells})();12px;primetellsturns0x600.jpg\\\"spainbeachtaxesmicroangel--></giftssteve-linkbody.});\\n\\tmount (199FAQ</rogerfrankClass28px;feeds<h1><scotttests22px;drink) || lewisshall#039; for lovedwaste00px;ja:\\u00E3\\u0082simon<fontreplymeetsuntercheaptightBrand) != dressclipsroomsonkeymobilmain.Name platefunnytreescom/\\\"1.jpgwmodeparamSTARTleft idden, 201);\\n}\\nform.viruschairtransworstPagesitionpatch<!--\\no-cacfirmstours,000 asiani++){adobe')[0]id=10both;menu .2.mi.png\\\"kevincoachChildbruce2.jpgURL)+.jpg|suitesliceharry120\\\" sweettr>\\r\\nname=diegopage swiss-->\\n\\n#fff;\\\">Log.com\\\"treatsheet) && 14px;sleepntentfiledja:\\u00E3\\u0083id=\\\"cName\\\"worseshots-box-delta\\n&lt;bears:48Z<data-rural</a> spendbakershops= \\\"\\\";php\\\">ction13px;brianhellosize=o=%2F joinmaybe<img img\\\">, fjsimg\\\" \\\")[0]MTopBType\\\"newlyDanskczechtrailknows</h5>faq\\\">zh-cn10);\\n-1\\\");type=bluestrulydavis.js';>\\r\\n<!steel you h2>\\r\\nform jesus100% menu.\\r\\n\\t\\r\\nwalesrisksumentddingb-likteachgif\\\" vegasdanskeestishqipsuomisobredesdeentretodospuedea\\u00C3\\u00B1osest\\u00C3\\u00A1tienehastaotrospartedondenuevohacerformamismomejormundoaqu\\u00C3\\u00ADd\\u00C3\\u00ADass\\u00C3\\u00B3loayudafechatodastantomenosdatosotrassitiomuchoahoralugarmayorestoshorastenerantesfotosestaspa\\u00C3\\u00ADsnuevasaludforosmedioquienmesespoderchileser\\u00C3\\u00A1vecesdecirjos\\u00C3\\u00A9estarventagrupohechoellostengoamigocosasnivelgentemismaairesjuliotemashaciafavorjuniolibrepuntobuenoautorabrilbuenatextomarzosaberlistaluegoc\\u00C3\\u00B3moenerojuegoper\\u00C3\\u00BAhaberestoynuncamujervalorfueralibrogustaigualvotoscasosgu\\u00C3\\u00ADapuedosomosavisousteddebennochebuscafaltaeurosseriedichocursoclavecasasle\\u00C3\\u00B3nplazolargoobrasvistaapoyojuntotratavistocrearcampohemoscincocargopisosordenhacen\\u00C3\\u00A1readiscopedrocercapuedapapelmenor\\u00C3\\u00BAtilclarojorgecalleponertardenadiemarcasigueellassiglocochemotosmadreclaserestoni\\u00C3\\u00B1oquedapasarbancohijosviajepablo\\u00C3\\u00A9stevienereinodejarfondocanalnorteletracausatomarmanoslunesautosvillavendopesartipostengamarcollevapadreunidovamoszonasambosbandamariaabusomuchasubirriojavivirgradochicaall\\u00C3\\u00ADjovendichaestantalessalirsuelopesosfinesllamabusco\\u00C3\\u00A9stalleganegroplazahumorpagarjuntadobleislasbolsaba\\u00C3\\u00B1ohablalucha\\u00C3\\u0081readicenjugarnotasvalleall\\u00C3\\u00A1cargadolorabajoest\\u00C3\\u00A9gustomentemariofirmacostofichaplatahogarartesleyesaquelmuseobasespocosmitadcielochicomiedoganarsantoetapadebesplayaredessietecortecoreadudasdeseoviejodeseaaguas&quot;domaincommonstatuseventsmastersystemactionbannerremovescrollupdateglobalmediumfilternumberchangeresultpublicscreenchoosenormaltravelissuessourcetargetspringmodulemobileswitchphotosborderregionitselfsocialactivecolumnrecordfollowtitle>eitherlengthfamilyfriendlayoutauthorcreatereviewsummerserverplayedplayerexpandpolicyformatdoublepointsseriespersonlivingdesignmonthsforcesuniqueweightpeopleenergynaturesearchfigurehavingcustomoffsetletterwindowsubmitrendergroupsuploadhealthmethodvideosschoolfutureshadowdebatevaluesObjectothersrightsleaguechromesimplenoticesharedendingseasonreportonlinesquarebuttonimagesenablemovinglatestwinterFranceperiodstrongrepeatLondondetailformeddemandsecurepassedtoggleplacesdevicestaticcitiesstreamyellowattackstreetflighthiddeninfo\\\">openedusefulvalleycausesleadersecretseconddamagesportsexceptratingsignedthingseffectfieldsstatesofficevisualeditorvolumeReportmuseummoviesparentaccessmostlymother\\\" id=\\\"marketgroundchancesurveybeforesymbolmomentspeechmotioninsidematterCenterobjectexistsmiddleEuropegrowthlegacymannerenoughcareeransweroriginportalclientselectrandomclosedtopicscomingfatheroptionsimplyraisedescapechosenchurchdefinereasoncorneroutputmemoryiframepolicemodelsNumberduringoffersstyleskilledlistedcalledsilvermargindeletebetterbrowselimitsGlobalsinglewidgetcenterbudgetnowrapcreditclaimsenginesafetychoicespirit-stylespreadmakingneededrussiapleaseextentScriptbrokenallowschargedividefactormember-basedtheoryconfigaroundworkedhelpedChurchimpactshouldalwayslogo\\\" bottomlist\\\">){var prefixorangeHeader.push(couplegardenbridgelaunchReviewtakingvisionlittledatingButtonbeautythemesforgotSearchanchoralmostloadedChangereturnstringreloadMobileincomesupplySourceordersviewed&nbsp;courseAbout island<html cookiename=\\\"amazonmodernadvicein</a>: The dialoghousesBEGIN MexicostartscentreheightaddingIslandassetsEmpireSchooleffortdirectnearlymanualSelect.\\n\\nOnejoinedmenu\\\">PhilipawardshandleimportOfficeregardskillsnationSportsdegreeweekly (e.g.behinddoctorloggedunited</b></beginsplantsassistartistissued300px|canadaagencyschemeremainBrazilsamplelogo\\\">beyond-scaleacceptservedmarineFootercamera</h1>\\n_form\\\"leavesstress\\\" />\\r\\n.gif\\\" onloadloaderOxfordsistersurvivlistenfemaleDesignsize=\\\"appealtext\\\">levelsthankshigherforcedanimalanyoneAfricaagreedrecentPeople<br />wonderpricesturned|| {};main\\\">inlinesundaywrap\\\">failedcensusminutebeaconquotes150px|estateremoteemail\\\"linkedright;signalformal1.htmlsignupprincefloat:.png\\\" forum.AccesspaperssoundsextendHeightsliderUTF-8\\\"&amp; Before. WithstudioownersmanageprofitjQueryannualparamsboughtfamousgooglelongeri++) {israelsayingdecidehome\\\">headerensurebranchpiecesblock;statedtop\\\"><racingresize--&gt;pacitysexualbureau.jpg\\\" 10,000obtaintitlesamount, Inc.comedymenu\\\" lyricstoday.indeedcounty_logo.FamilylookedMarketlse ifPlayerturkey);var forestgivingerrorsDomain}else{insertBlog</footerlogin.fasteragents<body 10px 0pragmafridayjuniordollarplacedcoversplugin5,000 page\\\">boston.test(avatartested_countforumsschemaindex,filledsharesreaderalert(appearSubmitline\\\">body\\\">\\n* TheThoughseeingjerseyNews</verifyexpertinjurywidth=CookieSTART across_imagethreadnativepocketbox\\\">\\nSystem DavidcancertablesprovedApril reallydriveritem\\\">more\\\">boardscolorscampusfirst || [];media.guitarfinishwidth:showedOther .php\\\" assumelayerswilsonstoresreliefswedenCustomeasily your String\\n\\nWhiltaylorclear:resortfrenchthough\\\") + \\\"<body>buyingbrandsMembername\\\">oppingsector5px;\\\">vspacepostermajor coffeemartinmaturehappen</nav>kansaslink\\\">Images=falsewhile hspace0&amp; \\n\\nIn  powerPolski-colorjordanBottomStart -count2.htmlnews\\\">01.jpgOnline-rightmillerseniorISBN 00,000 guidesvalue)ectionrepair.xml\\\"  rights.html-blockregExp:hoverwithinvirginphones</tr>\\rusing \\n\\tvar >');\\n\\t</td>\\n</tr>\\nbahasabrasilgalegomagyarpolskisrpski\\u00D8\\u00B1\\u00D8\\u00AF\\u00D9\\u0088\\u00E4\\u00B8\\u00AD\\u00E6\\u0096\\u0087\\u00E7\\u00AE\\u0080\\u00E4\\u00BD\\u0093\\u00E7\\u00B9\\u0081\\u00E9\\u00AB\\u0094\\u00E4\\u00BF\\u00A1\\u00E6\\u0081\\u00AF\\u00E4\\u00B8\\u00AD\\u00E5\\u009B\\u00BD\\u00E6\\u0088\\u0091\\u00E4\\u00BB\\u00AC\\u00E4\\u00B8\\u0080\\u00E4\\u00B8\\u00AA\\u00E5\\u0085\\u00AC\\u00E5\\u008F\\u00B8\\u00E7\\u00AE\\u00A1\\u00E7\\u0090\\u0086\\u00E8\\u00AE\\u00BA\\u00E5\\u009D\\u009B\\u00E5\\u008F\\u00AF\\u00E4\\u00BB\\u00A5\\u00E6\\u009C\\u008D\\u00E5\\u008A\\u00A1\\u00E6\\u0097\\u00B6\\u00E9\\u0097\\u00B4\\u00E4\\u00B8\\u00AA\\u00E4\\u00BA\\u00BA\\u00E4\\u00BA\\u00A7\\u00E5\\u0093\\u0081\\u00E8\\u0087\\u00AA\\u00E5\\u00B7\\u00B1\\u00E4\\u00BC\\u0081\\u00E4\\u00B8\\u009A\\u00E6\\u009F\\u00A5\\u00E7\\u009C\\u008B\\u00E5\\u00B7\\u00A5\\u00E4\\u00BD\\u009C\\u00E8\\u0081\\u0094\\u00E7\\u00B3\\u00BB\\u00E6\\u00B2\\u00A1\\u00E6\\u009C\\u0089\\u00E7\\u00BD\\u0091\\u00E7\\u00AB\\u0099\\u00E6\\u0089\\u0080\\u00E6\\u009C\\u0089\\u00E8\\u00AF\\u0084\\u00E8\\u00AE\\u00BA\\u00E4\\u00B8\\u00AD\\u00E5\\u00BF\\u0083\\u00E6\\u0096\\u0087\\u00E7\\u00AB\\u00A0\\u00E7\\u0094\\u00A8\\u00E6\\u0088\\u00B7\\u00E9\\u00A6\\u0096\\u00E9\\u00A1\\u00B5\\u00E4\\u00BD\\u009C\\u00E8\\u0080\\u0085\\u00E6\\u008A\\u0080\\u00E6\\u009C\\u00AF\\u00E9\\u0097\\u00AE\\u00E9\\u00A2\\u0098\\u00E7\\u009B\\u00B8\\u00E5\\u0085\\u00B3\\u00E4\\u00B8\\u008B\\u00E8\\u00BD\\u00BD\\u00E6\\u0090\\u009C\\u00E7\\u00B4\\u00A2\\u00E4\\u00BD\\u00BF\\u00E7\\u0094\\u00A8\\u00E8\\u00BD\\u00AF\\u00E4\\u00BB\\u00B6\\u00E5\\u009C\\u00A8\\u00E7\\u00BA\\u00BF\\u00E4\\u00B8\\u00BB\\u00E9\\u00A2\\u0098\\u00E8\\u00B5\\u0084\\u00E6\\u0096\\u0099\\u00E8\\u00A7\\u0086\\u00E9\\u00A2\\u0091\\u00E5\\u009B\\u009E\\u00E5\\u00A4\\u008D\\u00E6\\u00B3\\u00A8\\u00E5\\u0086\\u008C\\u00E7\\u00BD\\u0091\\u00E7\\u00BB\\u009C\\u00E6\\u0094\\u00B6\\u00E8\\u0097\\u008F\\u00E5\\u0086\\u0085\\u00E5\\u00AE\\u00B9\\u00E6\\u008E\\u00A8\\u00E8\\u008D\\u0090\\u00E5\\u00B8\\u0082\\u00E5\\u009C\\u00BA\\u00E6\\u00B6\\u0088\\u00E6\\u0081\\u00AF\\u00E7\\u00A9\\u00BA\\u00E9\\u0097\\u00B4\\u00E5\\u008F\\u0091\\u00E5\\u00B8\\u0083\\u00E4\\u00BB\\u0080\\u00E4\\u00B9\\u0088\\u00E5\\u00A5\\u00BD\\u00E5\\u008F\\u008B\\u00E7\\u0094\\u009F\\u00E6\\u00B4\\u00BB\\u00E5\\u009B\\u00BE\\u00E7\\u0089\\u0087\\u00E5\\u008F\\u0091\\u00E5\\u00B1\\u0095\\u00E5\\u00A6\\u0082\\u00E6\\u009E\\u009C\\u00E6\\u0089\\u008B\\u00E6\\u009C\\u00BA\\u00E6\\u0096\\u00B0\\u00E9\\u0097\\u00BB\\u00E6\\u009C\\u0080\\u00E6\\u0096\\u00B0\\u00E6\\u0096\\u00B9\\u00E5\\u00BC\\u008F\\u00E5\\u008C\\u0097\\u00E4\\u00BA\\u00AC\\u00E6\\u008F\\u0090\\u00E4\\u00BE\\u009B\\u00E5\\u0085\\u00B3\\u00E4\\u00BA\\u008E\\u00E6\\u009B\\u00B4\\u00E5\\u00A4\\u009A\\u00E8\\u00BF\\u0099\\u00E4\\u00B8\\u00AA\\u00E7\\u00B3\\u00BB\\u00E7\\u00BB\\u009F\\u00E7\\u009F\\u00A5\\u00E9\\u0081\\u0093\\u00E6\\u00B8\\u00B8\\u00E6\\u0088\\u008F\\u00E5\\u00B9\\u00BF\\u00E5\\u0091\\u008A\\u00E5\\u0085\\u00B6\\u00E4\\u00BB\\u0096\\u00E5\\u008F\\u0091\\u00E8\\u00A1\\u00A8\\u00E5\\u00AE\\u0089\\u00E5\\u0085\\u00A8\\u00E7\\u00AC\\u00AC\\u00E4\\u00B8\\u0080\\u00E4\\u00BC\\u009A\\u00E5\\u0091\\u0098\\u00E8\\u00BF\\u009B\\u00E8\\u00A1\\u008C\\u00E7\\u0082\\u00B9\\u00E5\\u0087\\u00BB\\u00E7\\u0089\\u0088\\u00E6\\u009D\\u0083\\u00E7\\u0094\\u00B5\\u00E5\\u00AD\\u0090\\u00E4\\u00B8\\u0096\\u00E7\\u0095\\u008C\\u00E8\\u00AE\\u00BE\\u00E8\\u00AE\\u00A1\\u00E5\\u0085\\u008D\\u00E8\\u00B4\\u00B9\\u00E6\\u0095\\u0099\\u00E8\\u0082\\u00B2\\u00E5\\u008A\\u00A0\\u00E5\\u0085\\u00A5\\u00E6\\u00B4\\u00BB\\u00E5\\u008A\\u00A8\\u00E4\\u00BB\\u0096\\u00E4\\u00BB\\u00AC\\u00E5\\u0095\\u0086\\u00E5\\u0093\\u0081\\u00E5\\u008D\\u009A\\u00E5\\u00AE\\u00A2\\u00E7\\u008E\\u00B0\\u00E5\\u009C\\u00A8\\u00E4\\u00B8\\u008A\\u00E6\\u00B5\\u00B7\\u00E5\\u00A6\\u0082\\u00E4\\u00BD\\u0095\\u00E5\\u00B7\\u00B2\\u00E7\\u00BB\\u008F\\u00E7\\u0095\\u0099\\u00E8\\u00A8\\u0080\\u00E8\\u00AF\\u00A6\\u00E7\\u00BB\\u0086\\u00E7\\u00A4\\u00BE\\u00E5\\u008C\\u00BA\\u00E7\\u0099\\u00BB\\u00E5\\u00BD\\u0095\\u00E6\\u009C\\u00AC\\u00E7\\u00AB\\u0099\\u00E9\\u009C\\u0080\\u00E8\\u00A6\\u0081\\u00E4\\u00BB\\u00B7\\u00E6\\u00A0\\u00BC\\u00E6\\u0094\\u00AF\\u00E6\\u008C\\u0081\\u00E5\\u009B\\u00BD\\u00E9\\u0099\\u0085\\u00E9\\u0093\\u00BE\\u00E6\\u008E\\u00A5\\u00E5\\u009B\\u00BD\\u00E5\\u00AE\\u00B6\\u00E5\\u00BB\\u00BA\\u00E8\\u00AE\\u00BE\\u00E6\\u009C\\u008B\\u00E5\\u008F\\u008B\\u00E9\\u0098\\u0085\\u00E8\\u00AF\\u00BB\\u00E6\\u00B3\\u0095\\u00E5\\u00BE\\u008B\\u00E4\\u00BD\\u008D\\u00E7\\u00BD\\u00AE\\u00E7\\u00BB\\u008F\\u00E6\\u00B5\\u008E\\u00E9\\u0080\\u0089\\u00E6\\u008B\\u00A9\\u00E8\\u00BF\\u0099\\u00E6\\u00A0\\u00B7\\u00E5\\u00BD\\u0093\\u00E5\\u0089\\u008D\\u00E5\\u0088\\u0086\\u00E7\\u00B1\\u00BB\\u00E6\\u008E\\u0092\\u00E8\\u00A1\\u008C\\u00E5\\u009B\\u00A0\\u00E4\\u00B8\\u00BA\\u00E4\\u00BA\\u00A4\\u00E6\\u0098\\u0093\\u00E6\\u009C\\u0080\\u00E5\\u0090\\u008E\\u00E9\\u009F\\u00B3\\u00E4\\u00B9\\u0090\\u00E4\\u00B8\\u008D\\u00E8\\u0083\\u00BD\\u00E9\\u0080\\u009A\\u00E8\\u00BF\\u0087\\u00E8\\u00A1\\u008C\\u00E4\\u00B8\\u009A\\u00E7\\u00A7\\u0091\\u00E6\\u008A\\u0080\\u00E5\\u008F\\u00AF\\u00E8\\u0083\\u00BD\\u00E8\\u00AE\\u00BE\\u00E5\\u00A4\\u0087\\u00E5\\u0090\\u0088\\u00E4\\u00BD\\u009C\\u00E5\\u00A4\\u00A7\\u00E5\\u00AE\\u00B6\\u00E7\\u00A4\\u00BE\\u00E4\\u00BC\\u009A\\u00E7\\u00A0\\u0094\\u00E7\\u00A9\\u00B6\\u00E4\\u00B8\\u0093\\u00E4\\u00B8\\u009A\\u00E5\\u0085\\u00A8\\u00E9\\u0083\\u00A8\\u00E9\\u00A1\\u00B9\\u00E7\\u009B\\u00AE\\u00E8\\u00BF\\u0099\\u00E9\\u0087\\u008C\\u00E8\\u00BF\\u0098\\u00E6\\u0098\\u00AF\\u00E5\\u00BC\\u0080\\u00E5\\u00A7\\u008B\\u00E6\\u0083\\u0085\\u00E5\\u0086\\u00B5\\u00E7\\u0094\\u00B5\\u00E8\\u0084\\u0091\\u00E6\\u0096\\u0087\\u00E4\\u00BB\\u00B6\\u00E5\\u0093\\u0081\\u00E7\\u0089\\u008C\\u00E5\\u00B8\\u00AE\\u00E5\\u008A\\u00A9\\u00E6\\u0096\\u0087\\u00E5\\u008C\\u0096\\u00E8\\u00B5\\u0084\\u00E6\\u00BA\\u0090\\u00E5\\u00A4\\u00A7\\u00E5\\u00AD\\u00A6\\u00E5\\u00AD\\u00A6\\u00E4\\u00B9\\u00A0\\u00E5\\u009C\\u00B0\\u00E5\\u009D\\u0080\\u00E6\\u00B5\\u008F\\u00E8\\u00A7\\u0088\\u00E6\\u008A\\u0095\\u00E8\\u00B5\\u0084\\u00E5\\u00B7\\u00A5\\u00E7\\u00A8\\u008B\\u00E8\\u00A6\\u0081\\u00E6\\u00B1\\u0082\\u00E6\\u0080\\u008E\\u00E4\\u00B9\\u0088\\u00E6\\u0097\\u00B6\\u00E5\\u0080\\u0099\\u00E5\\u008A\\u009F\\u00E8\\u0083\\u00BD\\u00E4\\u00B8\\u00BB\\u00E8\\u00A6\\u0081\\u00E7\\u009B\\u00AE\\u00E5\\u0089\\u008D\\u00E8\\u00B5\\u0084\\u00E8\\u00AE\\u00AF\\u00E5\\u009F\\u008E\\u00E5\\u00B8\\u0082\\u00E6\\u0096\\u00B9\\u00E6\\u00B3\\u0095\\u00E7\\u0094\\u00B5\\u00E5\\u00BD\\u00B1\\u00E6\\u008B\\u009B\\u00E8\\u0081\\u0098\\u00E5\\u00A3\\u00B0\\u00E6\\u0098\\u008E\\u00E4\\u00BB\\u00BB\\u00E4\\u00BD\\u0095\\u00E5\\u0081\\u00A5\\u00E5\\u00BA\\u00B7\\u00E6\\u0095\\u00B0\\u00E6\\u008D\\u00AE\\u00E7\\u00BE\\u008E\\u00E5\\u009B\\u00BD\\u00E6\\u00B1\\u00BD\\u00E8\\u00BD\\u00A6\\u00E4\\u00BB\\u008B\\u00E7\\u00BB\\u008D\\u00E4\\u00BD\\u0086\\u00E6\\u0098\\u00AF\\u00E4\\u00BA\\u00A4\\u00E6\\u00B5\\u0081\\u00E7\\u0094\\u009F\\u00E4\\u00BA\\u00A7\\u00E6\\u0089\\u0080\\u00E4\\u00BB\\u00A5\\u00E7\\u0094\\u00B5\\u00E8\\u00AF\\u009D\\u00E6\\u0098\\u00BE\\u00E7\\u00A4\\u00BA\\u00E4\\u00B8\\u0080\\u00E4\\u00BA\\u009B\\u00E5\\u008D\\u0095\\u00E4\\u00BD\\u008D\\u00E4\\u00BA\\u00BA\\u00E5\\u0091\\u0098\\u00E5\\u0088\\u0086\\u00E6\\u009E\\u0090\\u00E5\\u009C\\u00B0\\u00E5\\u009B\\u00BE\\u00E6\\u0097\\u0085\\u00E6\\u00B8\\u00B8\\u00E5\\u00B7\\u00A5\\u00E5\\u0085\\u00B7\\u00E5\\u00AD\\u00A6\\u00E7\\u0094\\u009F\\u00E7\\u00B3\\u00BB\\u00E5\\u0088\\u0097\\u00E7\\u00BD\\u0091\\u00E5\\u008F\\u008B\\u00E5\\u00B8\\u0096\\u00E5\\u00AD\\u0090\\u00E5\\u00AF\\u0086\\u00E7\\u00A0\\u0081\\u00E9\\u00A2\\u0091\\u00E9\\u0081\\u0093\\u00E6\\u008E\\u00A7\\u00E5\\u0088\\u00B6\\u00E5\\u009C\\u00B0\\u00E5\\u008C\\u00BA\\u00E5\\u009F\\u00BA\\u00E6\\u009C\\u00AC\\u00E5\\u0085\\u00A8\\u00E5\\u009B\\u00BD\\u00E7\\u00BD\\u0091\\u00E4\\u00B8\\u008A\\u00E9\\u0087\\u008D\\u00E8\\u00A6\\u0081\\u00E7\\u00AC\\u00AC\\u00E4\\u00BA\\u008C\\u00E5\\u0096\\u009C\\u00E6\\u00AC\\u00A2\\u00E8\\u00BF\\u009B\\u00E5\\u0085\\u00A5\\u00E5\\u008F\\u008B\\u00E6\\u0083\\u0085\\u00E8\\u00BF\\u0099\\u00E4\\u00BA\\u009B\\u00E8\\u0080\\u0083\\u00E8\\u00AF\\u0095\\u00E5\\u008F\\u0091\\u00E7\\u008E\\u00B0\\u00E5\\u009F\\u00B9\\u00E8\\u00AE\\u00AD\\u00E4\\u00BB\\u00A5\\u00E4\\u00B8\\u008A\\u00E6\\u0094\\u00BF\\u00E5\\u00BA\\u009C\\u00E6\\u0088\\u0090\\u00E4\\u00B8\\u00BA\\u00E7\\u008E\\u00AF\\u00E5\\u00A2\\u0083\\u00E9\\u00A6\\u0099\\u00E6\\u00B8\\u00AF\\u00E5\\u0090\\u008C\\u00E6\\u0097\\u00B6\\u00E5\\u00A8\\u00B1\\u00E4\\u00B9\\u0090\\u00E5\\u008F\\u0091\\u00E9\\u0080\\u0081\\u00E4\\u00B8\\u0080\\u00E5\\u00AE\\u009A\\u00E5\\u00BC\\u0080\\u00E5\\u008F\\u0091\\u00E4\\u00BD\\u009C\\u00E5\\u0093\\u0081\\u00E6\\u00A0\\u0087\\u00E5\\u0087\\u0086\\u00E6\\u00AC\\u00A2\\u00E8\\u00BF\\u008E\\u00E8\\u00A7\\u00A3\\u00E5\\u0086\\u00B3\\u00E5\\u009C\\u00B0\\u00E6\\u0096\\u00B9\\u00E4\\u00B8\\u0080\\u00E4\\u00B8\\u008B\\u00E4\\u00BB\\u00A5\\u00E5\\u008F\\u008A\\u00E8\\u00B4\\u00A3\\u00E4\\u00BB\\u00BB\\u00E6\\u0088\\u0096\\u00E8\\u0080\\u0085\\u00E5\\u00AE\\u00A2\\u00E6\\u0088\\u00B7\\u00E4\\u00BB\\u00A3\\u00E8\\u00A1\\u00A8\\u00E7\\u00A7\\u00AF\\u00E5\\u0088\\u0086\\u00E5\\u00A5\\u00B3\\u00E4\\u00BA\\u00BA\\u00E6\\u0095\\u00B0\\u00E7\\u00A0\\u0081\\u00E9\\u0094\\u0080\\u00E5\\u0094\\u00AE\\u00E5\\u0087\\u00BA\\u00E7\\u008E\\u00B0\\u00E7\\u00A6\\u00BB\\u00E7\\u00BA\\u00BF\\u00E5\\u00BA\\u0094\\u00E7\\u0094\\u00A8\\u00E5\\u0088\\u0097\\u00E8\\u00A1\\u00A8\\u00E4\\u00B8\\u008D\\u00E5\\u0090\\u008C\\u00E7\\u00BC\\u0096\\u00E8\\u00BE\\u0091\\u00E7\\u00BB\\u009F\\u00E8\\u00AE\\u00A1\\u00E6\\u009F\\u00A5\\u00E8\\u00AF\\u00A2\\u00E4\\u00B8\\u008D\\u00E8\\u00A6\\u0081\\u00E6\\u009C\\u0089\\u00E5\\u0085\\u00B3\\u00E6\\u009C\\u00BA\\u00E6\\u009E\\u0084\\u00E5\\u00BE\\u0088\\u00E5\\u00A4\\u009A\\u00E6\\u0092\\u00AD\\u00E6\\u0094\\u00BE\\u00E7\\u00BB\\u0084\\u00E7\\u00BB\\u0087\\u00E6\\u0094\\u00BF\\u00E7\\u00AD\\u0096\\u00E7\\u009B\\u00B4\\u00E6\\u008E\\u00A5\\u00E8\\u0083\\u00BD\\u00E5\\u008A\\u009B\\u00E6\\u009D\\u00A5\\u00E6\\u00BA\\u0090\\u00E6\\u0099\\u0082\\u00E9\\u0096\\u0093\\u00E7\\u009C\\u008B\\u00E5\\u0088\\u00B0\\u00E7\\u0083\\u00AD\\u00E9\\u0097\\u00A8\\u00E5\\u0085\\u00B3\\u00E9\\u0094\\u00AE\\u00E4\\u00B8\\u0093\\u00E5\\u008C\\u00BA\\u00E9\\u009D\\u009E\\u00E5\\u00B8\\u00B8\\u00E8\\u008B\\u00B1\\u00E8\\u00AF\\u00AD\\u00E7\\u0099\\u00BE\\u00E5\\u00BA\\u00A6\\u00E5\\u00B8\\u008C\\u00E6\\u009C\\u009B\\u00E7\\u00BE\\u008E\\u00E5\\u00A5\\u00B3\\u00E6\\u00AF\\u0094\\u00E8\\u00BE\\u0083\\u00E7\\u009F\\u00A5\\u00E8\\u00AF\\u0086\\u00E8\\u00A7\\u0084\\u00E5\\u00AE\\u009A\\u00E5\\u00BB\\u00BA\\u00E8\\u00AE\\u00AE\\u00E9\\u0083\\u00A8\\u00E9\\u0097\\u00A8\\u00E6\\u0084\\u008F\\u00E8\\u00A7\\u0081\\u00E7\\u00B2\\u00BE\\u00E5\\u00BD\\u00A9\\u00E6\\u0097\\u00A5\\u00E6\\u009C\\u00AC\\u00E6\\u008F\\u0090\\u00E9\\u00AB\\u0098\\u00E5\\u008F\\u0091\\u00E8\\u00A8\\u0080\\u00E6\\u0096\\u00B9\\u00E9\\u009D\\u00A2\\u00E5\\u009F\\u00BA\\u00E9\\u0087\\u0091\\u00E5\\u00A4\\u0084\\u00E7\\u0090\\u0086\\u00E6\\u009D\\u0083\\u00E9\\u0099\\u0090\\u00E5\\u00BD\\u00B1\\u00E7\\u0089\\u0087\\u00E9\\u0093\\u00B6\\u00E8\\u00A1\\u008C\\u00E8\\u00BF\\u0098\\u00E6\\u009C\\u0089\\u00E5\\u0088\\u0086\\u00E4\\u00BA\\u00AB\\u00E7\\u0089\\u00A9\\u00E5\\u0093\\u0081\\u00E7\\u00BB\\u008F\\u00E8\\u0090\\u00A5\\u00E6\\u00B7\\u00BB\\u00E5\\u008A\\u00A0\\u00E4\\u00B8\\u0093\\u00E5\\u00AE\\u00B6\\u00E8\\u00BF\\u0099\\u00E7\\u00A7\\u008D\\u00E8\\u00AF\\u009D\\u00E9\\u00A2\\u0098\\u00E8\\u00B5\\u00B7\\u00E6\\u009D\\u00A5\\u00E4\\u00B8\\u009A\\u00E5\\u008A\\u00A1\\u00E5\\u0085\\u00AC\\u00E5\\u0091\\u008A\\u00E8\\u00AE\\u00B0\\u00E5\\u00BD\\u0095\\u00E7\\u00AE\\u0080\\u00E4\\u00BB\\u008B\\u00E8\\u00B4\\u00A8\\u00E9\\u0087\\u008F\\u00E7\\u0094\\u00B7\\u00E4\\u00BA\\u00BA\\u00E5\\u00BD\\u00B1\\u00E5\\u0093\\u008D\\u00E5\\u00BC\\u0095\\u00E7\\u0094\\u00A8\\u00E6\\u008A\\u00A5\\u00E5\\u0091\\u008A\\u00E9\\u0083\\u00A8\\u00E5\\u0088\\u0086\\u00E5\\u00BF\\u00AB\\u00E9\\u0080\\u009F\\u00E5\\u0092\\u00A8\\u00E8\\u00AF\\u00A2\\u00E6\\u0097\\u00B6\\u00E5\\u00B0\\u009A\\u00E6\\u00B3\\u00A8\\u00E6\\u0084\\u008F\\u00E7\\u0094\\u00B3\\u00E8\\u00AF\\u00B7\\u00E5\\u00AD\\u00A6\\u00E6\\u00A0\\u00A1\\u00E5\\u00BA\\u0094\\u00E8\\u00AF\\u00A5\\u00E5\\u008E\\u0086\\u00E5\\u008F\\u00B2\\u00E5\\u008F\\u00AA\\u00E6\\u0098\\u00AF\\u00E8\\u00BF\\u0094\\u00E5\\u009B\\u009E\\u00E8\\u00B4\\u00AD\\u00E4\\u00B9\\u00B0\\u00E5\\u0090\\u008D\\u00E7\\u00A7\\u00B0\\u00E4\\u00B8\\u00BA\\u00E4\\u00BA\\u0086\\u00E6\\u0088\\u0090\\u00E5\\u008A\\u009F\\u00E8\\u00AF\\u00B4\\u00E6\\u0098\\u008E\\u00E4\\u00BE\\u009B\\u00E5\\u00BA\\u0094\\u00E5\\u00AD\\u00A9\\u00E5\\u00AD\\u0090\\u00E4\\u00B8\\u0093\\u00E9\\u00A2\\u0098\\u00E7\\u00A8\\u008B\\u00E5\\u00BA\\u008F\\u00E4\\u00B8\\u0080\\u00E8\\u0088\\u00AC\\u00E6\\u009C\\u0083\\u00E5\\u0093\\u00A1\\u00E5\\u008F\\u00AA\\u00E6\\u009C\\u0089\\u00E5\\u0085\\u00B6\\u00E5\\u00AE\\u0083\\u00E4\\u00BF\\u009D\\u00E6\\u008A\\u00A4\\u00E8\\u0080\\u008C\\u00E4\\u00B8\\u0094\\u00E4\\u00BB\\u008A\\u00E5\\u00A4\\u00A9\\u00E7\\u00AA\\u0097\\u00E5\\u008F\\u00A3\\u00E5\\u008A\\u00A8\\u00E6\\u0080\\u0081\\u00E7\\u008A\\u00B6\\u00E6\\u0080\\u0081\\u00E7\\u0089\\u00B9\\u00E5\\u0088\\u00AB\\u00E8\\u00AE\\u00A4\\u00E4\\u00B8\\u00BA\\u00E5\\u00BF\\u0085\\u00E9\\u00A1\\u00BB\\u00E6\\u009B\\u00B4\\u00E6\\u0096\\u00B0\\u00E5\\u00B0\\u008F\\u00E8\\u00AF\\u00B4\\u00E6\\u0088\\u0091\\u00E5\\u0080\\u0091\\u00E4\\u00BD\\u009C\\u00E4\\u00B8\\u00BA\\u00E5\\u00AA\\u0092\\u00E4\\u00BD\\u0093\\u00E5\\u008C\\u0085\\u00E6\\u008B\\u00AC\\u00E9\\u0082\\u00A3\\u00E4\\u00B9\\u0088\\u00E4\\u00B8\\u0080\\u00E6\\u00A0\\u00B7\\u00E5\\u009B\\u00BD\\u00E5\\u0086\\u0085\\u00E6\\u0098\\u00AF\\u00E5\\u0090\\u00A6\\u00E6\\u00A0\\u00B9\\u00E6\\u008D\\u00AE\\u00E7\\u0094\\u00B5\\u00E8\\u00A7\\u0086\\u00E5\\u00AD\\u00A6\\u00E9\\u0099\\u00A2\\u00E5\\u0085\\u00B7\\u00E6\\u009C\\u0089\\u00E8\\u00BF\\u0087\\u00E7\\u00A8\\u008B\\u00E7\\u0094\\u00B1\\u00E4\\u00BA\\u008E\\u00E4\\u00BA\\u00BA\\u00E6\\u0089\\u008D\\u00E5\\u0087\\u00BA\\u00E6\\u009D\\u00A5\\u00E4\\u00B8\\u008D\\u00E8\\u00BF\\u0087\\u00E6\\u00AD\\u00A3\\u00E5\\u009C\\u00A8\\u00E6\\u0098\\u008E\\u00E6\\u0098\\u009F\\u00E6\\u0095\\u0085\\u00E4\\u00BA\\u008B\\u00E5\\u0085\\u00B3\\u00E7\\u00B3\\u00BB\\u00E6\\u00A0\\u0087\\u00E9\\u00A2\\u0098\\u00E5\\u0095\\u0086\\u00E5\\u008A\\u00A1\\u00E8\\u00BE\\u0093\\u00E5\\u0085\\u00A5\\u00E4\\u00B8\\u0080\\u00E7\\u009B\\u00B4\\u00E5\\u009F\\u00BA\\u00E7\\u00A1\\u0080\\u00E6\\u0095\\u0099\\u00E5\\u00AD\\u00A6\\u00E4\\u00BA\\u0086\\u00E8\\u00A7\\u00A3\\u00E5\\u00BB\\u00BA\\u00E7\\u00AD\\u0091\\u00E7\\u00BB\\u0093\\u00E6\\u009E\\u009C\\u00E5\\u0085\\u00A8\\u00E7\\u0090\\u0083\\u00E9\\u0080\\u009A\\u00E7\\u009F\\u00A5\\u00E8\\u00AE\\u00A1\\u00E5\\u0088\\u0092\\u00E5\\u00AF\\u00B9\\u00E4\\u00BA\\u008E\\u00E8\\u0089\\u00BA\\u00E6\\u009C\\u00AF\\u00E7\\u009B\\u00B8\\u00E5\\u0086\\u008C\\u00E5\\u008F\\u0091\\u00E7\\u0094\\u009F\\u00E7\\u009C\\u009F\\u00E7\\u009A\\u0084\\u00E5\\u00BB\\u00BA\\u00E7\\u00AB\\u008B\\u00E7\\u00AD\\u0089\\u00E7\\u00BA\\u00A7\\u00E7\\u00B1\\u00BB\\u00E5\\u009E\\u008B\\u00E7\\u00BB\\u008F\\u00E9\\u00AA\\u008C\\u00E5\\u00AE\\u009E\\u00E7\\u008E\\u00B0\\u00E5\\u0088\\u00B6\\u00E4\\u00BD\\u009C\\u00E6\\u009D\\u00A5\\u00E8\\u0087\\u00AA\\u00E6\\u00A0\\u0087\\u00E7\\u00AD\\u00BE\\u00E4\\u00BB\\u00A5\\u00E4\\u00B8\\u008B\\u00E5\\u008E\\u009F\\u00E5\\u0088\\u009B\\u00E6\\u0097\\u00A0\\u00E6\\u00B3\\u0095\\u00E5\\u0085\\u00B6\\u00E4\\u00B8\\u00AD\\u00E5\\u0080\\u008B\\u00E4\\u00BA\\u00BA\\u00E4\\u00B8\\u0080\\u00E5\\u0088\\u0087\\u00E6\\u008C\\u0087\\u00E5\\u008D\\u0097\\u00E5\\u0085\\u00B3\\u00E9\\u0097\\u00AD\\u00E9\\u009B\\u0086\\u00E5\\u009B\\u00A2\\u00E7\\u00AC\\u00AC\\u00E4\\u00B8\\u0089\\u00E5\\u0085\\u00B3\\u00E6\\u00B3\\u00A8\\u00E5\\u009B\\u00A0\\u00E6\\u00AD\\u00A4\\u00E7\\u0085\\u00A7\\u00E7\\u0089\\u0087\\u00E6\\u00B7\\u00B1\\u00E5\\u009C\\u00B3\\u00E5\\u0095\\u0086\\u00E4\\u00B8\\u009A\\u00E5\\u00B9\\u00BF\\u00E5\\u00B7\\u009E\\u00E6\\u0097\\u00A5\\u00E6\\u009C\\u009F\\u00E9\\u00AB\\u0098\\u00E7\\u00BA\\u00A7\\u00E6\\u009C\\u0080\\u00E8\\u00BF\\u0091\\u00E7\\u00BB\\u00BC\\u00E5\\u0090\\u0088\\u00E8\\u00A1\\u00A8\\u00E7\\u00A4\\u00BA\\u00E4\\u00B8\\u0093\\u00E8\\u00BE\\u0091\\u00E8\\u00A1\\u008C\\u00E4\\u00B8\\u00BA\\u00E4\\u00BA\\u00A4\\u00E9\\u0080\\u009A\\u00E8\\u00AF\\u0084\\u00E4\\u00BB\\u00B7\\u00E8\\u00A7\\u0089\\u00E5\\u00BE\\u0097\\u00E7\\u00B2\\u00BE\\u00E5\\u008D\\u008E\\u00E5\\u00AE\\u00B6\\u00E5\\u00BA\\u00AD\\u00E5\\u00AE\\u008C\\u00E6\\u0088\\u0090\\u00E6\\u0084\\u009F\\u00E8\\u00A7\\u0089\\u00E5\\u00AE\\u0089\\u00E8\\u00A3\\u0085\\u00E5\\u00BE\\u0097\\u00E5\\u0088\\u00B0\\u00E9\\u0082\\u00AE\\u00E4\\u00BB\\u00B6\\u00E5\\u0088\\u00B6\\u00E5\\u00BA\\u00A6\\u00E9\\u00A3\\u009F\\u00E5\\u0093\\u0081\\u00E8\\u0099\\u00BD\\u00E7\\u0084\\u00B6\\u00E8\\u00BD\\u00AC\\u00E8\\u00BD\\u00BD\\u00E6\\u008A\\u00A5\\u00E4\\u00BB\\u00B7\\u00E8\\u00AE\\u00B0\\u00E8\\u0080\\u0085\\u00E6\\u0096\\u00B9\\u00E6\\u00A1\\u0088\\u00E8\\u00A1\\u008C\\u00E6\\u0094\\u00BF\\u00E4\\u00BA\\u00BA\\u00E6\\u00B0\\u0091\\u00E7\\u0094\\u00A8\\u00E5\\u0093\\u0081\\u00E4\\u00B8\\u009C\\u00E8\\u00A5\\u00BF\\u00E6\\u008F\\u0090\\u00E5\\u0087\\u00BA\\u00E9\\u0085\\u0092\\u00E5\\u00BA\\u0097\\u00E7\\u0084\\u00B6\\u00E5\\u0090\\u008E\\u00E4\\u00BB\\u0098\\u00E6\\u00AC\\u00BE\\u00E7\\u0083\\u00AD\\u00E7\\u0082\\u00B9\\u00E4\\u00BB\\u00A5\\u00E5\\u0089\\u008D\\u00E5\\u00AE\\u008C\\u00E5\\u0085\\u00A8\\u00E5\\u008F\\u0091\\u00E5\\u00B8\\u0096\\u00E8\\u00AE\\u00BE\\u00E7\\u00BD\\u00AE\\u00E9\\u00A2\\u0086\\u00E5\\u00AF\\u00BC\\u00E5\\u00B7\\u00A5\\u00E4\\u00B8\\u009A\\u00E5\\u008C\\u00BB\\u00E9\\u0099\\u00A2\\u00E7\\u009C\\u008B\\u00E7\\u009C\\u008B\\u00E7\\u00BB\\u008F\\u00E5\\u0085\\u00B8\\u00E5\\u008E\\u009F\\u00E5\\u009B\\u00A0\\u00E5\\u00B9\\u00B3\\u00E5\\u008F\\u00B0\\u00E5\\u0090\\u0084\\u00E7\\u00A7\\u008D\\u00E5\\u00A2\\u009E\\u00E5\\u008A\\u00A0\\u00E6\\u009D\\u0090\\u00E6\\u0096\\u0099\\u00E6\\u0096\\u00B0\\u00E5\\u00A2\\u009E\\u00E4\\u00B9\\u008B\\u00E5\\u0090\\u008E\\u00E8\\u0081\\u008C\\u00E4\\u00B8\\u009A\\u00E6\\u0095\\u0088\\u00E6\\u009E\\u009C\\u00E4\\u00BB\\u008A\\u00E5\\u00B9\\u00B4\\u00E8\\u00AE\\u00BA\\u00E6\\u0096\\u0087\\u00E6\\u0088\\u0091\\u00E5\\u009B\\u00BD\\u00E5\\u0091\\u008A\\u00E8\\u00AF\\u0089\\u00E7\\u0089\\u0088\\u00E4\\u00B8\\u00BB\\u00E4\\u00BF\\u00AE\\u00E6\\u0094\\u00B9\\u00E5\\u008F\\u0082\\u00E4\\u00B8\\u008E\\u00E6\\u0089\\u0093\\u00E5\\u008D\\u00B0\\u00E5\\u00BF\\u00AB\\u00E4\\u00B9\\u0090\\u00E6\\u009C\\u00BA\\u00E6\\u00A2\\u00B0\\u00E8\\u00A7\\u0082\\u00E7\\u0082\\u00B9\\u00E5\\u00AD\\u0098\\u00E5\\u009C\\u00A8\\u00E7\\u00B2\\u00BE\\u00E7\\u00A5\\u009E\\u00E8\\u008E\\u00B7\\u00E5\\u00BE\\u0097\\u00E5\\u0088\\u00A9\\u00E7\\u0094\\u00A8\\u00E7\\u00BB\\u00A7\\u00E7\\u00BB\\u00AD\\u00E4\\u00BD\\u00A0\\u00E4\\u00BB\\u00AC\\u00E8\\u00BF\\u0099\\u00E4\\u00B9\\u0088\\u00E6\\u00A8\\u00A1\\u00E5\\u00BC\\u008F\\u00E8\\u00AF\\u00AD\\u00E8\\u00A8\\u0080\\u00E8\\u0083\\u00BD\\u00E5\\u00A4\\u009F\\u00E9\\u009B\\u0085\\u00E8\\u0099\\u008E\\u00E6\\u0093\\u008D\\u00E4\\u00BD\\u009C\\u00E9\\u00A3\\u008E\\u00E6\\u00A0\\u00BC\\u00E4\\u00B8\\u0080\\u00E8\\u00B5\\u00B7\\u00E7\\u00A7\\u0091\\u00E5\\u00AD\\u00A6\\u00E4\\u00BD\\u0093\\u00E8\\u0082\\u00B2\\u00E7\\u009F\\u00AD\\u00E4\\u00BF\\u00A1\\u00E6\\u009D\\u00A1\\u00E4\\u00BB\\u00B6\\u00E6\\u00B2\\u00BB\\u00E7\\u0096\\u0097\\u00E8\\u00BF\\u0090\\u00E5\\u008A\\u00A8\\u00E4\\u00BA\\u00A7\\u00E4\\u00B8\\u009A\\u00E4\\u00BC\\u009A\\u00E8\\u00AE\\u00AE\\u00E5\\u00AF\\u00BC\\u00E8\\u0088\\u00AA\\u00E5\\u0085\\u0088\\u00E7\\u0094\\u009F\\u00E8\\u0081\\u0094\\u00E7\\u009B\\u009F\\u00E5\\u008F\\u00AF\\u00E6\\u0098\\u00AF\\u00E5\\u0095\\u008F\\u00E9\\u00A1\\u008C\\u00E7\\u00BB\\u0093\\u00E6\\u009E\\u0084\\u00E4\\u00BD\\u009C\\u00E7\\u0094\\u00A8\\u00E8\\u00B0\\u0083\\u00E6\\u009F\\u00A5\\u00E8\\u00B3\\u0087\\u00E6\\u0096\\u0099\\u00E8\\u0087\\u00AA\\u00E5\\u008A\\u00A8\\u00E8\\u00B4\\u009F\\u00E8\\u00B4\\u00A3\\u00E5\\u0086\\u009C\\u00E4\\u00B8\\u009A\\u00E8\\u00AE\\u00BF\\u00E9\\u0097\\u00AE\\u00E5\\u00AE\\u009E\\u00E6\\u0096\\u00BD\\u00E6\\u008E\\u00A5\\u00E5\\u008F\\u0097\\u00E8\\u00AE\\u00A8\\u00E8\\u00AE\\u00BA\\u00E9\\u0082\\u00A3\\u00E4\\u00B8\\u00AA\\u00E5\\u008F\\u008D\\u00E9\\u00A6\\u0088\\u00E5\\u008A\\u00A0\\u00E5\\u00BC\\u00BA\\u00E5\\u00A5\\u00B3\\u00E6\\u0080\\u00A7\\u00E8\\u008C\\u0083\\u00E5\\u009B\\u00B4\\u00E6\\u009C\\u008D\\u00E5\\u008B\\u0099\\u00E4\\u00BC\\u0091\\u00E9\\u0097\\u00B2\\u00E4\\u00BB\\u008A\\u00E6\\u0097\\u00A5\\u00E5\\u00AE\\u00A2\\u00E6\\u009C\\u008D\\u00E8\\u00A7\\u0080\\u00E7\\u009C\\u008B\\u00E5\\u008F\\u0082\\u00E5\\u008A\\u00A0\\u00E7\\u009A\\u0084\\u00E8\\u00AF\\u009D\\u00E4\\u00B8\\u0080\\u00E7\\u0082\\u00B9\\u00E4\\u00BF\\u009D\\u00E8\\u00AF\\u0081\\u00E5\\u009B\\u00BE\\u00E4\\u00B9\\u00A6\\u00E6\\u009C\\u0089\\u00E6\\u0095\\u0088\\u00E6\\u00B5\\u008B\\u00E8\\u00AF\\u0095\\u00E7\\u00A7\\u00BB\\u00E5\\u008A\\u00A8\\u00E6\\u0089\\u008D\\u00E8\\u0083\\u00BD\\u00E5\\u0086\\u00B3\\u00E5\\u00AE\\u009A\\u00E8\\u0082\\u00A1\\u00E7\\u00A5\\u00A8\\u00E4\\u00B8\\u008D\\u00E6\\u0096\\u00AD\\u00E9\\u009C\\u0080\\u00E6\\u00B1\\u0082\\u00E4\\u00B8\\u008D\\u00E5\\u00BE\\u0097\\u00E5\\u008A\\u009E\\u00E6\\u00B3\\u0095\\u00E4\\u00B9\\u008B\\u00E9\\u0097\\u00B4\\u00E9\\u0087\\u0087\\u00E7\\u0094\\u00A8\\u00E8\\u0090\\u00A5\\u00E9\\u0094\\u0080\\u00E6\\u008A\\u0095\\u00E8\\u00AF\\u0089\\u00E7\\u009B\\u00AE\\u00E6\\u00A0\\u0087\\u00E7\\u0088\\u00B1\\u00E6\\u0083\\u0085\\u00E6\\u0091\\u0084\\u00E5\\u00BD\\u00B1\\u00E6\\u009C\\u0089\\u00E4\\u00BA\\u009B\\u00E8\\u00A4\\u0087\\u00E8\\u00A3\\u00BD\\u00E6\\u0096\\u0087\\u00E5\\u00AD\\u00A6\\u00E6\\u009C\\u00BA\\u00E4\\u00BC\\u009A\\u00E6\\u0095\\u00B0\\u00E5\\u00AD\\u0097\\u00E8\\u00A3\\u0085\\u00E4\\u00BF\\u00AE\\u00E8\\u00B4\\u00AD\\u00E7\\u0089\\u00A9\\u00E5\\u0086\\u009C\\u00E6\\u009D\\u0091\\u00E5\\u0085\\u00A8\\u00E9\\u009D\\u00A2\\u00E7\\u00B2\\u00BE\\u00E5\\u0093\\u0081\\u00E5\\u0085\\u00B6\\u00E5\\u00AE\\u009E\\u00E4\\u00BA\\u008B\\u00E6\\u0083\\u0085\\u00E6\\u00B0\\u00B4\\u00E5\\u00B9\\u00B3\\u00E6\\u008F\\u0090\\u00E7\\u00A4\\u00BA\\u00E4\\u00B8\\u008A\\u00E5\\u00B8\\u0082\\u00E8\\u00B0\\u00A2\\u00E8\\u00B0\\u00A2\\u00E6\\u0099\\u00AE\\u00E9\\u0080\\u009A\\u00E6\\u0095\\u0099\\u00E5\\u00B8\\u0088\\u00E4\\u00B8\\u008A\\u00E4\\u00BC\\u00A0\\u00E7\\u00B1\\u00BB\\u00E5\\u0088\\u00AB\\u00E6\\u00AD\\u008C\\u00E6\\u009B\\u00B2\\u00E6\\u008B\\u00A5\\u00E6\\u009C\\u0089\\u00E5\\u0088\\u009B\\u00E6\\u0096\\u00B0\\u00E9\\u0085\\u008D\\u00E4\\u00BB\\u00B6\\u00E5\\u008F\\u00AA\\u00E8\\u00A6\\u0081\\u00E6\\u0097\\u00B6\\u00E4\\u00BB\\u00A3\\u00E8\\u00B3\\u0087\\u00E8\\u00A8\\u008A\\u00E8\\u00BE\\u00BE\\u00E5\\u0088\\u00B0\\u00E4\\u00BA\\u00BA\\u00E7\\u0094\\u009F\\u00E8\\u00AE\\u00A2\\u00E9\\u0098\\u0085\\u00E8\\u0080\\u0081\\u00E5\\u00B8\\u0088\\u00E5\\u00B1\\u0095\\u00E7\\u00A4\\u00BA\\u00E5\\u00BF\\u0083\\u00E7\\u0090\\u0086\\u00E8\\u00B4\\u00B4\\u00E5\\u00AD\\u0090\\u00E7\\u00B6\\u00B2\\u00E7\\u00AB\\u0099\\u00E4\\u00B8\\u00BB\\u00E9\\u00A1\\u008C\\u00E8\\u0087\\u00AA\\u00E7\\u0084\\u00B6\\u00E7\\u00BA\\u00A7\\u00E5\\u0088\\u00AB\\u00E7\\u00AE\\u0080\\u00E5\\u008D\\u0095\\u00E6\\u0094\\u00B9\\u00E9\\u009D\\u00A9\\u00E9\\u0082\\u00A3\\u00E4\\u00BA\\u009B\\u00E6\\u009D\\u00A5\\u00E8\\u00AF\\u00B4\\u00E6\\u0089\\u0093\\u00E5\\u00BC\\u0080\\u00E4\\u00BB\\u00A3\\u00E7\\u00A0\\u0081\\u00E5\\u0088\\u00A0\\u00E9\\u0099\\u00A4\\u00E8\\u00AF\\u0081\\u00E5\\u0088\\u00B8\\u00E8\\u008A\\u0082\\u00E7\\u009B\\u00AE\\u00E9\\u0087\\u008D\\u00E7\\u0082\\u00B9\\u00E6\\u00AC\\u00A1\\u00E6\\u0095\\u00B8\\u00E5\\u00A4\\u009A\\u00E5\\u00B0\\u0091\\u00E8\\u00A7\\u0084\\u00E5\\u0088\\u0092\\u00E8\\u00B5\\u0084\\u00E9\\u0087\\u0091\\u00E6\\u0089\\u00BE\\u00E5\\u0088\\u00B0\\u00E4\\u00BB\\u00A5\\u00E5\\u0090\\u008E\\u00E5\\u00A4\\u00A7\\u00E5\\u0085\\u00A8\\u00E4\\u00B8\\u00BB\\u00E9\\u00A1\\u00B5\\u00E6\\u009C\\u0080\\u00E4\\u00BD\\u00B3\\u00E5\\u009B\\u009E\\u00E7\\u00AD\\u0094\\u00E5\\u00A4\\u00A9\\u00E4\\u00B8\\u008B\\u00E4\\u00BF\\u009D\\u00E9\\u009A\\u009C\\u00E7\\u008E\\u00B0\\u00E4\\u00BB\\u00A3\\u00E6\\u00A3\\u0080\\u00E6\\u009F\\u00A5\\u00E6\\u008A\\u0095\\u00E7\\u00A5\\u00A8\\u00E5\\u00B0\\u008F\\u00E6\\u0097\\u00B6\\u00E6\\u00B2\\u0092\\u00E6\\u009C\\u0089\\u00E6\\u00AD\\u00A3\\u00E5\\u00B8\\u00B8\\u00E7\\u0094\\u009A\\u00E8\\u0087\\u00B3\\u00E4\\u00BB\\u00A3\\u00E7\\u0090\\u0086\\u00E7\\u009B\\u00AE\\u00E5\\u00BD\\u0095\\u00E5\\u0085\\u00AC\\u00E5\\u00BC\\u0080\\u00E5\\u00A4\\u008D\\u00E5\\u0088\\u00B6\\u00E9\\u0087\\u0091\\u00E8\\u009E\\u008D\\u00E5\\u00B9\\u00B8\\u00E7\\u00A6\\u008F\\u00E7\\u0089\\u0088\\u00E6\\u009C\\u00AC\\u00E5\\u00BD\\u00A2\\u00E6\\u0088\\u0090\\u00E5\\u0087\\u0086\\u00E5\\u00A4\\u0087\\u00E8\\u00A1\\u008C\\u00E6\\u0083\\u0085\\u00E5\\u009B\\u009E\\u00E5\\u0088\\u00B0\\u00E6\\u0080\\u009D\\u00E6\\u0083\\u00B3\\u00E6\\u0080\\u008E\\u00E6\\u00A0\\u00B7\\u00E5\\u008D\\u008F\\u00E8\\u00AE\\u00AE\\u00E8\\u00AE\\u00A4\\u00E8\\u00AF\\u0081\\u00E6\\u009C\\u0080\\u00E5\\u00A5\\u00BD\\u00E4\\u00BA\\u00A7\\u00E7\\u0094\\u009F\\u00E6\\u008C\\u0089\\u00E7\\u0085\\u00A7\\u00E6\\u009C\\u008D\\u00E8\\u00A3\\u0085\\u00E5\\u00B9\\u00BF\\u00E4\\u00B8\\u009C\\u00E5\\u008A\\u00A8\\u00E6\\u00BC\\u00AB\\u00E9\\u0087\\u0087\\u00E8\\u00B4\\u00AD\\u00E6\\u0096\\u00B0\\u00E6\\u0089\\u008B\\u00E7\\u00BB\\u0084\\u00E5\\u009B\\u00BE\\u00E9\\u009D\\u00A2\\u00E6\\u009D\\u00BF\\u00E5\\u008F\\u0082\\u00E8\\u0080\\u0083\\u00E6\\u0094\\u00BF\\u00E6\\u00B2\\u00BB\\u00E5\\u00AE\\u00B9\\u00E6\\u0098\\u0093\\u00E5\\u00A4\\u00A9\\u00E5\\u009C\\u00B0\\u00E5\\u008A\\u00AA\\u00E5\\u008A\\u009B\\u00E4\\u00BA\\u00BA\\u00E4\\u00BB\\u00AC\\u00E5\\u008D\\u0087\\u00E7\\u00BA\\u00A7\\u00E9\\u0080\\u009F\\u00E5\\u00BA\\u00A6\\u00E4\\u00BA\\u00BA\\u00E7\\u0089\\u00A9\\u00E8\\u00B0\\u0083\\u00E6\\u0095\\u00B4\\u00E6\\u00B5\\u0081\\u00E8\\u00A1\\u008C\\u00E9\\u0080\\u00A0\\u00E6\\u0088\\u0090\\u00E6\\u0096\\u0087\\u00E5\\u00AD\\u0097\\u00E9\\u009F\\u00A9\\u00E5\\u009B\\u00BD\\u00E8\\u00B4\\u00B8\\u00E6\\u0098\\u0093\\u00E5\\u00BC\\u0080\\u00E5\\u00B1\\u0095\\u00E7\\u009B\\u00B8\\u00E9\\u0097\\u009C\\u00E8\\u00A1\\u00A8\\u00E7\\u008E\\u00B0\\u00E5\\u00BD\\u00B1\\u00E8\\u00A7\\u0086\\u00E5\\u00A6\\u0082\\u00E6\\u00AD\\u00A4\\u00E7\\u00BE\\u008E\\u00E5\\u00AE\\u00B9\\u00E5\\u00A4\\u00A7\\u00E5\\u00B0\\u008F\\u00E6\\u008A\\u00A5\\u00E9\\u0081\\u0093\\u00E6\\u009D\\u00A1\\u00E6\\u00AC\\u00BE\\u00E5\\u00BF\\u0083\\u00E6\\u0083\\u0085\\u00E8\\u00AE\\u00B8\\u00E5\\u00A4\\u009A\\u00E6\\u00B3\\u0095\\u00E8\\u00A7\\u0084\\u00E5\\u00AE\\u00B6\\u00E5\\u00B1\\u0085\\u00E4\\u00B9\\u00A6\\u00E5\\u00BA\\u0097\\u00E8\\u00BF\\u009E\\u00E6\\u008E\\u00A5\\u00E7\\u00AB\\u008B\\u00E5\\u008D\\u00B3\\u00E4\\u00B8\\u00BE\\u00E6\\u008A\\u00A5\\u00E6\\u008A\\u0080\\u00E5\\u00B7\\u00A7\\u00E5\\u00A5\\u00A5\\u00E8\\u00BF\\u0090\\u00E7\\u0099\\u00BB\\u00E5\\u0085\\u00A5\\u00E4\\u00BB\\u00A5\\u00E6\\u009D\\u00A5\\u00E7\\u0090\\u0086\\u00E8\\u00AE\\u00BA\\u00E4\\u00BA\\u008B\\u00E4\\u00BB\\u00B6\\u00E8\\u0087\\u00AA\\u00E7\\u0094\\u00B1\\u00E4\\u00B8\\u00AD\\u00E5\\u008D\\u008E\\u00E5\\u008A\\u009E\\u00E5\\u0085\\u00AC\\u00E5\\u00A6\\u0088\\u00E5\\u00A6\\u0088\\u00E7\\u009C\\u009F\\u00E6\\u00AD\\u00A3\\u00E4\\u00B8\\u008D\\u00E9\\u0094\\u0099\\u00E5\\u0085\\u00A8\\u00E6\\u0096\\u0087\\u00E5\\u0090\\u0088\\u00E5\\u0090\\u008C\\u00E4\\u00BB\\u00B7\\u00E5\\u0080\\u00BC\\u00E5\\u0088\\u00AB\\u00E4\\u00BA\\u00BA\\u00E7\\u009B\\u0091\\u00E7\\u009D\\u00A3\\u00E5\\u0085\\u00B7\\u00E4\\u00BD\\u0093\\u00E4\\u00B8\\u0096\\u00E7\\u00BA\\u00AA\\u00E5\\u009B\\u00A2\\u00E9\\u0098\\u009F\\u00E5\\u0088\\u009B\\u00E4\\u00B8\\u009A\\u00E6\\u0089\\u00BF\\u00E6\\u008B\\u0085\\u00E5\\u00A2\\u009E\\u00E9\\u0095\\u00BF\\u00E6\\u009C\\u0089\\u00E4\\u00BA\\u00BA\\u00E4\\u00BF\\u009D\\u00E6\\u008C\\u0081\\u00E5\\u0095\\u0086\\u00E5\\u00AE\\u00B6\\u00E7\\u00BB\\u00B4\\u00E4\\u00BF\\u00AE\\u00E5\\u008F\\u00B0\\u00E6\\u00B9\\u00BE\\u00E5\\u00B7\\u00A6\\u00E5\\u008F\\u00B3\\u00E8\\u0082\\u00A1\\u00E4\\u00BB\\u00BD\\u00E7\\u00AD\\u0094\\u00E6\\u00A1\\u0088\\u00E5\\u00AE\\u009E\\u00E9\\u0099\\u0085\\u00E7\\u0094\\u00B5\\u00E4\\u00BF\\u00A1\\u00E7\\u00BB\\u008F\\u00E7\\u0090\\u0086\\u00E7\\u0094\\u009F\\u00E5\\u0091\\u00BD\\u00E5\\u00AE\\u00A3\\u00E4\\u00BC\\u00A0\\u00E4\\u00BB\\u00BB\\u00E5\\u008A\\u00A1\\u00E6\\u00AD\\u00A3\\u00E5\\u00BC\\u008F\\u00E7\\u0089\\u00B9\\u00E8\\u0089\\u00B2\\u00E4\\u00B8\\u008B\\u00E6\\u009D\\u00A5\\u00E5\\u008D\\u008F\\u00E4\\u00BC\\u009A\\u00E5\\u008F\\u00AA\\u00E8\\u0083\\u00BD\\u00E5\\u00BD\\u0093\\u00E7\\u0084\\u00B6\\u00E9\\u0087\\u008D\\u00E6\\u0096\\u00B0\\u00E5\\u0085\\u00A7\\u00E5\\u00AE\\u00B9\\u00E6\\u008C\\u0087\\u00E5\\u00AF\\u00BC\\u00E8\\u00BF\\u0090\\u00E8\\u00A1\\u008C\\u00E6\\u0097\\u00A5\\u00E5\\u00BF\\u0097\\u00E8\\u00B3\\u00A3\\u00E5\\u00AE\\u00B6\\u00E8\\u00B6\\u0085\\u00E8\\u00BF\\u0087\\u00E5\\u009C\\u009F\\u00E5\\u009C\\u00B0\\u00E6\\u00B5\\u0099\\u00E6\\u00B1\\u009F\\u00E6\\u0094\\u00AF\\u00E4\\u00BB\\u0098\\u00E6\\u008E\\u00A8\\u00E5\\u0087\\u00BA\\u00E7\\u00AB\\u0099\\u00E9\\u0095\\u00BF\\u00E6\\u009D\\u00AD\\u00E5\\u00B7\\u009E\\u00E6\\u0089\\u00A7\\u00E8\\u00A1\\u008C\\u00E5\\u0088\\u00B6\\u00E9\\u0080\\u00A0\\u00E4\\u00B9\\u008B\\u00E4\\u00B8\\u0080\\u00E6\\u008E\\u00A8\\u00E5\\u00B9\\u00BF\\u00E7\\u008E\\u00B0\\u00E5\\u009C\\u00BA\\u00E6\\u008F\\u008F\\u00E8\\u00BF\\u00B0\\u00E5\\u008F\\u0098\\u00E5\\u008C\\u0096\\u00E4\\u00BC\\u00A0\\u00E7\\u00BB\\u009F\\u00E6\\u00AD\\u008C\\u00E6\\u0089\\u008B\\u00E4\\u00BF\\u009D\\u00E9\\u0099\\u00A9\\u00E8\\u00AF\\u00BE\\u00E7\\u00A8\\u008B\\u00E5\\u008C\\u00BB\\u00E7\\u0096\\u0097\\u00E7\\u00BB\\u008F\\u00E8\\u00BF\\u0087\\u00E8\\u00BF\\u0087\\u00E5\\u008E\\u00BB\\u00E4\\u00B9\\u008B\\u00E5\\u0089\\u008D\\u00E6\\u0094\\u00B6\\u00E5\\u0085\\u00A5\\u00E5\\u00B9\\u00B4\\u00E5\\u00BA\\u00A6\\u00E6\\u009D\\u0082\\u00E5\\u00BF\\u0097\\u00E7\\u00BE\\u008E\\u00E4\\u00B8\\u00BD\\u00E6\\u009C\\u0080\\u00E9\\u00AB\\u0098\\u00E7\\u0099\\u00BB\\u00E9\\u0099\\u0086\\u00E6\\u009C\\u00AA\\u00E6\\u009D\\u00A5\\u00E5\\u008A\\u00A0\\u00E5\\u00B7\\u00A5\\u00E5\\u0085\\u008D\\u00E8\\u00B4\\u00A3\\u00E6\\u0095\\u0099\\u00E7\\u00A8\\u008B\\u00E7\\u0089\\u0088\\u00E5\\u009D\\u0097\\u00E8\\u00BA\\u00AB\\u00E4\\u00BD\\u0093\\u00E9\\u0087\\u008D\\u00E5\\u00BA\\u0086\\u00E5\\u0087\\u00BA\\u00E5\\u0094\\u00AE\\u00E6\\u0088\\u0090\\u00E6\\u009C\\u00AC\\u00E5\\u00BD\\u00A2\\u00E5\\u00BC\\u008F\\u00E5\\u009C\\u009F\\u00E8\\u00B1\\u0086\\u00E5\\u0087\\u00BA\\u00E5\\u0083\\u00B9\\u00E4\\u00B8\\u009C\\u00E6\\u0096\\u00B9\\u00E9\\u0082\\u00AE\\u00E7\\u00AE\\u00B1\\u00E5\\u008D\\u0097\\u00E4\\u00BA\\u00AC\\u00E6\\u00B1\\u0082\\u00E8\\u0081\\u008C\\u00E5\\u008F\\u0096\\u00E5\\u00BE\\u0097\\u00E8\\u0081\\u008C\\u00E4\\u00BD\\u008D\\u00E7\\u009B\\u00B8\\u00E4\\u00BF\\u00A1\\u00E9\\u00A1\\u00B5\\u00E9\\u009D\\u00A2\\u00E5\\u0088\\u0086\\u00E9\\u0092\\u009F\\u00E7\\u00BD\\u0091\\u00E9\\u00A1\\u00B5\\u00E7\\u00A1\\u00AE\\u00E5\\u00AE\\u009A\\u00E5\\u009B\\u00BE\\u00E4\\u00BE\\u008B\\u00E7\\u00BD\\u0091\\u00E5\\u009D\\u0080\\u00E7\\u00A7\\u00AF\\u00E6\\u009E\\u0081\\u00E9\\u0094\\u0099\\u00E8\\u00AF\\u00AF\\u00E7\\u009B\\u00AE\\u00E7\\u009A\\u0084\\u00E5\\u00AE\\u009D\\u00E8\\u00B4\\u009D\\u00E6\\u009C\\u00BA\\u00E5\\u0085\\u00B3\\u00E9\\u00A3\\u008E\\u00E9\\u0099\\u00A9\\u00E6\\u008E\\u0088\\u00E6\\u009D\\u0083\\u00E7\\u0097\\u0085\\u00E6\\u00AF\\u0092\\u00E5\\u00AE\\u00A0\\u00E7\\u0089\\u00A9\\u00E9\\u0099\\u00A4\\u00E4\\u00BA\\u0086\\u00E8\\u00A9\\u0095\\u00E8\\u00AB\\u0096\\u00E7\\u0096\\u00BE\\u00E7\\u0097\\u0085\\u00E5\\u008F\\u008A\\u00E6\\u0097\\u00B6\\u00E6\\u00B1\\u0082\\u00E8\\u00B4\\u00AD\\u00E7\\u00AB\\u0099\\u00E7\\u0082\\u00B9\\u00E5\\u0084\\u00BF\\u00E7\\u00AB\\u00A5\\u00E6\\u00AF\\u008F\\u00E5\\u00A4\\u00A9\\u00E4\\u00B8\\u00AD\\u00E5\\u00A4\\u00AE\\u00E8\\u00AE\\u00A4\\u00E8\\u00AF\\u0086\\u00E6\\u00AF\\u008F\\u00E4\\u00B8\\u00AA\\u00E5\\u00A4\\u00A9\\u00E6\\u00B4\\u00A5\\u00E5\\u00AD\\u0097\\u00E4\\u00BD\\u0093\\u00E5\\u008F\\u00B0\\u00E7\\u0081\\u00A3\\u00E7\\u00BB\\u00B4\\u00E6\\u008A\\u00A4\\u00E6\\u009C\\u00AC\\u00E9\\u00A1\\u00B5\\u00E4\\u00B8\\u00AA\\u00E6\\u0080\\u00A7\\u00E5\\u00AE\\u0098\\u00E6\\u0096\\u00B9\\u00E5\\u00B8\\u00B8\\u00E8\\u00A7\\u0081\\u00E7\\u009B\\u00B8\\u00E6\\u009C\\u00BA\\u00E6\\u0088\\u0098\\u00E7\\u0095\\u00A5\\u00E5\\u00BA\\u0094\\u00E5\\u00BD\\u0093\\u00E5\\u00BE\\u008B\\u00E5\\u00B8\\u0088\\u00E6\\u0096\\u00B9\\u00E4\\u00BE\\u00BF\\u00E6\\u00A0\\u00A1\\u00E5\\u009B\\u00AD\\u00E8\\u0082\\u00A1\\u00E5\\u00B8\\u0082\\u00E6\\u0088\\u00BF\\u00E5\\u00B1\\u008B\\u00E6\\u00A0\\u008F\\u00E7\\u009B\\u00AE\\u00E5\\u0091\\u0098\\u00E5\\u00B7\\u00A5\\u00E5\\u00AF\\u00BC\\u00E8\\u0087\\u00B4\\u00E7\\u00AA\\u0081\\u00E7\\u0084\\u00B6\\u00E9\\u0081\\u0093\\u00E5\\u0085\\u00B7\\u00E6\\u009C\\u00AC\\u00E7\\u00BD\\u0091\\u00E7\\u00BB\\u0093\\u00E5\\u0090\\u0088\\u00E6\\u00A1\\u00A3\\u00E6\\u00A1\\u0088\\u00E5\\u008A\\u00B3\\u00E5\\u008A\\u00A8\\u00E5\\u008F\\u00A6\\u00E5\\u00A4\\u0096\\u00E7\\u00BE\\u008E\\u00E5\\u0085\\u0083\\u00E5\\u00BC\\u0095\\u00E8\\u00B5\\u00B7\\u00E6\\u0094\\u00B9\\u00E5\\u008F\\u0098\\u00E7\\u00AC\\u00AC\\u00E5\\u009B\\u009B\\u00E4\\u00BC\\u009A\\u00E8\\u00AE\\u00A1\\u00E8\\u00AA\\u00AA\\u00E6\\u0098\\u008E\\u00E9\\u009A\\u0090\\u00E7\\u00A7\\u0081\\u00E5\\u00AE\\u009D\\u00E5\\u00AE\\u009D\\u00E8\\u00A7\\u0084\\u00E8\\u008C\\u0083\\u00E6\\u00B6\\u0088\\u00E8\\u00B4\\u00B9\\u00E5\\u0085\\u00B1\\u00E5\\u0090\\u008C\\u00E5\\u00BF\\u0098\\u00E8\\u00AE\\u00B0\\u00E4\\u00BD\\u0093\\u00E7\\u00B3\\u00BB\\u00E5\\u00B8\\u00A6\\u00E6\\u009D\\u00A5\\u00E5\\u0090\\u008D\\u00E5\\u00AD\\u0097\\u00E7\\u0099\\u00BC\\u00E8\\u00A1\\u00A8\\u00E5\\u00BC\\u0080\\u00E6\\u0094\\u00BE\\u00E5\\u008A\\u00A0\\u00E7\\u009B\\u009F\\u00E5\\u008F\\u0097\\u00E5\\u0088\\u00B0\\u00E4\\u00BA\\u008C\\u00E6\\u0089\\u008B\\u00E5\\u00A4\\u00A7\\u00E9\\u0087\\u008F\\u00E6\\u0088\\u0090\\u00E4\\u00BA\\u00BA\\u00E6\\u0095\\u00B0\\u00E9\\u0087\\u008F\\u00E5\\u0085\\u00B1\\u00E4\\u00BA\\u00AB\\u00E5\\u008C\\u00BA\\u00E5\\u009F\\u009F\\u00E5\\u00A5\\u00B3\\u00E5\\u00AD\\u00A9\\u00E5\\u008E\\u009F\\u00E5\\u0088\\u0099\\u00E6\\u0089\\u0080\\u00E5\\u009C\\u00A8\\u00E7\\u00BB\\u0093\\u00E6\\u009D\\u009F\\u00E9\\u0080\\u009A\\u00E4\\u00BF\\u00A1\\u00E8\\u00B6\\u0085\\u00E7\\u00BA\\u00A7\\u00E9\\u0085\\u008D\\u00E7\\u00BD\\u00AE\\u00E5\\u00BD\\u0093\\u00E6\\u0097\\u00B6\\u00E4\\u00BC\\u0098\\u00E7\\u00A7\\u0080\\u00E6\\u0080\\u00A7\\u00E6\\u0084\\u009F\\u00E6\\u0088\\u00BF\\u00E4\\u00BA\\u00A7\\u00E9\\u0081\\u008A\\u00E6\\u0088\\u00B2\\u00E5\\u0087\\u00BA\\u00E5\\u008F\\u00A3\\u00E6\\u008F\\u0090\\u00E4\\u00BA\\u00A4\\u00E5\\u00B0\\u00B1\\u00E4\\u00B8\\u009A\\u00E4\\u00BF\\u009D\\u00E5\\u0081\\u00A5\\u00E7\\u00A8\\u008B\\u00E5\\u00BA\\u00A6\\u00E5\\u008F\\u0082\\u00E6\\u0095\\u00B0\\u00E4\\u00BA\\u008B\\u00E4\\u00B8\\u009A\\u00E6\\u0095\\u00B4\\u00E4\\u00B8\\u00AA\\u00E5\\u00B1\\u00B1\\u00E4\\u00B8\\u009C\\u00E6\\u0083\\u0085\\u00E6\\u0084\\u009F\\u00E7\\u0089\\u00B9\\u00E6\\u00AE\\u008A\\u00E5\\u0088\\u0086\\u00E9\\u00A1\\u009E\\u00E6\\u0090\\u009C\\u00E5\\u00B0\\u008B\\u00E5\\u00B1\\u009E\\u00E4\\u00BA\\u008E\\u00E9\\u0097\\u00A8\\u00E6\\u0088\\u00B7\\u00E8\\u00B4\\u00A2\\u00E5\\u008A\\u00A1\\u00E5\\u00A3\\u00B0\\u00E9\\u009F\\u00B3\\u00E5\\u008F\\u008A\\u00E5\\u0085\\u00B6\\u00E8\\u00B4\\u00A2\\u00E7\\u00BB\\u008F\\u00E5\\u009D\\u009A\\u00E6\\u008C\\u0081\\u00E5\\u00B9\\u00B2\\u00E9\\u0083\\u00A8\\u00E6\\u0088\\u0090\\u00E7\\u00AB\\u008B\\u00E5\\u0088\\u00A9\\u00E7\\u009B\\u008A\\u00E8\\u0080\\u0083\\u00E8\\u0099\\u0091\\u00E6\\u0088\\u0090\\u00E9\\u0083\\u00BD\\u00E5\\u008C\\u0085\\u00E8\\u00A3\\u0085\\u00E7\\u0094\\u00A8\\u00E6\\u0088\\u00B6\\u00E6\\u00AF\\u0094\\u00E8\\u00B5\\u009B\\u00E6\\u0096\\u0087\\u00E6\\u0098\\u008E\\u00E6\\u008B\\u009B\\u00E5\\u0095\\u0086\\u00E5\\u00AE\\u008C\\u00E6\\u0095\\u00B4\\u00E7\\u009C\\u009F\\u00E6\\u0098\\u00AF\\u00E7\\u009C\\u00BC\\u00E7\\u009D\\u009B\\u00E4\\u00BC\\u0099\\u00E4\\u00BC\\u00B4\\u00E5\\u00A8\\u0081\\u00E6\\u009C\\u009B\\u00E9\\u00A2\\u0086\\u00E5\\u009F\\u009F\\u00E5\\u008D\\u00AB\\u00E7\\u0094\\u009F\\u00E4\\u00BC\\u0098\\u00E6\\u0083\\u00A0\\u00E8\\u00AB\\u0096\\u00E5\\u00A3\\u0087\\u00E5\\u0085\\u00AC\\u00E5\\u0085\\u00B1\\u00E8\\u0089\\u00AF\\u00E5\\u00A5\\u00BD\\u00E5\\u0085\\u0085\\u00E5\\u0088\\u0086\\u00E7\\u00AC\\u00A6\\u00E5\\u0090\\u0088\\u00E9\\u0099\\u0084\\u00E4\\u00BB\\u00B6\\u00E7\\u0089\\u00B9\\u00E7\\u0082\\u00B9\\u00E4\\u00B8\\u008D\\u00E5\\u008F\\u00AF\\u00E8\\u008B\\u00B1\\u00E6\\u0096\\u0087\\u00E8\\u00B5\\u0084\\u00E4\\u00BA\\u00A7\\u00E6\\u00A0\\u00B9\\u00E6\\u009C\\u00AC\\u00E6\\u0098\\u008E\\u00E6\\u0098\\u00BE\\u00E5\\u00AF\\u0086\\u00E7\\u00A2\\u00BC\\u00E5\\u0085\\u00AC\\u00E4\\u00BC\\u0097\\u00E6\\u00B0\\u0091\\u00E6\\u0097\\u008F\\u00E6\\u009B\\u00B4\\u00E5\\u008A\\u00A0\\u00E4\\u00BA\\u00AB\\u00E5\\u008F\\u0097\\u00E5\\u0090\\u008C\\u00E5\\u00AD\\u00A6\\u00E5\\u0090\\u00AF\\u00E5\\u008A\\u00A8\\u00E9\\u0080\\u0082\\u00E5\\u0090\\u0088\\u00E5\\u008E\\u009F\\u00E6\\u009D\\u00A5\\u00E9\\u0097\\u00AE\\u00E7\\u00AD\\u0094\\u00E6\\u009C\\u00AC\\u00E6\\u0096\\u0087\\u00E7\\u00BE\\u008E\\u00E9\\u00A3\\u009F\\u00E7\\u00BB\\u00BF\\u00E8\\u0089\\u00B2\\u00E7\\u00A8\\u00B3\\u00E5\\u00AE\\u009A\\u00E7\\u00BB\\u0088\\u00E4\\u00BA\\u008E\\u00E7\\u0094\\u009F\\u00E7\\u0089\\u00A9\\u00E4\\u00BE\\u009B\\u00E6\\u00B1\\u0082\\u00E6\\u0090\\u009C\\u00E7\\u008B\\u0090\\u00E5\\u008A\\u009B\\u00E9\\u0087\\u008F\\u00E4\\u00B8\\u00A5\\u00E9\\u0087\\u008D\\u00E6\\u00B0\\u00B8\\u00E8\\u00BF\\u009C\\u00E5\\u0086\\u0099\\u00E7\\u009C\\u009F\\u00E6\\u009C\\u0089\\u00E9\\u0099\\u0090\\u00E7\\u00AB\\u009E\\u00E4\\u00BA\\u0089\\u00E5\\u00AF\\u00B9\\u00E8\\u00B1\\u00A1\\u00E8\\u00B4\\u00B9\\u00E7\\u0094\\u00A8\\u00E4\\u00B8\\u008D\\u00E5\\u00A5\\u00BD\\u00E7\\u00BB\\u009D\\u00E5\\u00AF\\u00B9\\u00E5\\u008D\\u0081\\u00E5\\u0088\\u0086\\u00E4\\u00BF\\u0083\\u00E8\\u00BF\\u009B\\u00E7\\u0082\\u00B9\\u00E8\\u00AF\\u0084\\u00E5\\u00BD\\u00B1\\u00E9\\u009F\\u00B3\\u00E4\\u00BC\\u0098\\u00E5\\u008A\\u00BF\\u00E4\\u00B8\\u008D\\u00E5\\u00B0\\u0091\\u00E6\\u00AC\\u00A3\\u00E8\\u00B5\\u008F\\u00E5\\u00B9\\u00B6\\u00E4\\u00B8\\u0094\\u00E6\\u009C\\u0089\\u00E7\\u0082\\u00B9\\u00E6\\u0096\\u00B9\\u00E5\\u0090\\u0091\\u00E5\\u0085\\u00A8\\u00E6\\u0096\\u00B0\\u00E4\\u00BF\\u00A1\\u00E7\\u0094\\u00A8\\u00E8\\u00AE\\u00BE\\u00E6\\u0096\\u00BD\\u00E5\\u00BD\\u00A2\\u00E8\\u00B1\\u00A1\\u00E8\\u00B5\\u0084\\u00E6\\u00A0\\u00BC\\u00E7\\u00AA\\u0081\\u00E7\\u00A0\\u00B4\\u00E9\\u009A\\u008F\\u00E7\\u009D\\u0080\\u00E9\\u0087\\u008D\\u00E5\\u00A4\\u00A7\\u00E4\\u00BA\\u008E\\u00E6\\u0098\\u00AF\\u00E6\\u00AF\\u0095\\u00E4\\u00B8\\u009A\\u00E6\\u0099\\u00BA\\u00E8\\u0083\\u00BD\\u00E5\\u008C\\u0096\\u00E5\\u00B7\\u00A5\\u00E5\\u00AE\\u008C\\u00E7\\u00BE\\u008E\\u00E5\\u0095\\u0086\\u00E5\\u009F\\u008E\\u00E7\\u00BB\\u009F\\u00E4\\u00B8\\u0080\\u00E5\\u0087\\u00BA\\u00E7\\u0089\\u0088\\u00E6\\u0089\\u0093\\u00E9\\u0080\\u00A0\\u00E7\\u0094\\u00A2\\u00E5\\u0093\\u0081\\u00E6\\u00A6\\u0082\\u00E5\\u0086\\u00B5\\u00E7\\u0094\\u00A8\\u00E4\\u00BA\\u008E\\u00E4\\u00BF\\u009D\\u00E7\\u0095\\u0099\\u00E5\\u009B\\u00A0\\u00E7\\u00B4\\u00A0\\u00E4\\u00B8\\u00AD\\u00E5\\u009C\\u008B\\u00E5\\u00AD\\u0098\\u00E5\\u0082\\u00A8\\u00E8\\u00B4\\u00B4\\u00E5\\u009B\\u00BE\\u00E6\\u009C\\u0080\\u00E6\\u0084\\u009B\\u00E9\\u0095\\u00BF\\u00E6\\u009C\\u009F\\u00E5\\u008F\\u00A3\\u00E4\\u00BB\\u00B7\\u00E7\\u0090\\u0086\\u00E8\\u00B4\\u00A2\\u00E5\\u009F\\u00BA\\u00E5\\u009C\\u00B0\\u00E5\\u00AE\\u0089\\u00E6\\u008E\\u0092\\u00E6\\u00AD\\u00A6\\u00E6\\u00B1\\u0089\\u00E9\\u0087\\u008C\\u00E9\\u009D\\u00A2\\u00E5\\u0088\\u009B\\u00E5\\u00BB\\u00BA\\u00E5\\u00A4\\u00A9\\u00E7\\u00A9\\u00BA\\u00E9\\u00A6\\u0096\\u00E5\\u0085\\u0088\\u00E5\\u00AE\\u008C\\u00E5\\u0096\\u0084\\u00E9\\u00A9\\u00B1\\u00E5\\u008A\\u00A8\\u00E4\\u00B8\\u008B\\u00E9\\u009D\\u00A2\\u00E4\\u00B8\\u008D\\u00E5\\u0086\\u008D\\u00E8\\u00AF\\u009A\\u00E4\\u00BF\\u00A1\\u00E6\\u0084\\u008F\\u00E4\\u00B9\\u0089\\u00E9\\u0098\\u00B3\\u00E5\\u0085\\u0089\\u00E8\\u008B\\u00B1\\u00E5\\u009B\\u00BD\\u00E6\\u00BC\\u0082\\u00E4\\u00BA\\u00AE\\u00E5\\u0086\\u009B\\u00E4\\u00BA\\u008B\\u00E7\\u008E\\u00A9\\u00E5\\u00AE\\u00B6\\u00E7\\u00BE\\u00A4\\u00E4\\u00BC\\u0097\\u00E5\\u0086\\u009C\\u00E6\\u00B0\\u0091\\u00E5\\u008D\\u00B3\\u00E5\\u008F\\u00AF\\u00E5\\u0090\\u008D\\u00E7\\u00A8\\u00B1\\u00E5\\u00AE\\u00B6\\u00E5\\u0085\\u00B7\\u00E5\\u008A\\u00A8\\u00E7\\u0094\\u00BB\\u00E6\\u0083\\u00B3\\u00E5\\u0088\\u00B0\\u00E6\\u00B3\\u00A8\\u00E6\\u0098\\u008E\\u00E5\\u00B0\\u008F\\u00E5\\u00AD\\u00A6\\u00E6\\u0080\\u00A7\\u00E8\\u0083\\u00BD\\u00E8\\u0080\\u0083\\u00E7\\u00A0\\u0094\\u00E7\\u00A1\\u00AC\\u00E4\\u00BB\\u00B6\\u00E8\\u00A7\\u0082\\u00E7\\u009C\\u008B\\u00E6\\u00B8\\u0085\\u00E6\\u00A5\\u009A\\u00E6\\u0090\\u009E\\u00E7\\u00AC\\u0091\\u00E9\\u00A6\\u0096\\u00E9\\u00A0\\u0081\\u00E9\\u00BB\\u0084\\u00E9\\u0087\\u0091\\u00E9\\u0080\\u0082\\u00E7\\u0094\\u00A8\\u00E6\\u00B1\\u009F\\u00E8\\u008B\\u008F\\u00E7\\u009C\\u009F\\u00E5\\u00AE\\u009E\\u00E4\\u00B8\\u00BB\\u00E7\\u00AE\\u00A1\\u00E9\\u0098\\u00B6\\u00E6\\u00AE\\u00B5\\u00E8\\u00A8\\u00BB\\u00E5\\u0086\\u008A\\u00E7\\u00BF\\u00BB\\u00E8\\u00AF\\u0091\\u00E6\\u009D\\u0083\\u00E5\\u0088\\u00A9\\u00E5\\u0081\\u009A\\u00E5\\u00A5\\u00BD\\u00E4\\u00BC\\u00BC\\u00E4\\u00B9\\u008E\\u00E9\\u0080\\u009A\\u00E8\\u00AE\\u00AF\\u00E6\\u0096\\u00BD\\u00E5\\u00B7\\u00A5\\u00E7\\u008B\\u0080\\u00E6\\u0085\\u008B\\u00E4\\u00B9\\u009F\\u00E8\\u00AE\\u00B8\\u00E7\\u008E\\u00AF\\u00E4\\u00BF\\u009D\\u00E5\\u009F\\u00B9\\u00E5\\u0085\\u00BB\\u00E6\\u00A6\\u0082\\u00E5\\u00BF\\u00B5\\u00E5\\u00A4\\u00A7\\u00E5\\u009E\\u008B\\u00E6\\u009C\\u00BA\\u00E7\\u00A5\\u00A8\\u00E7\\u0090\\u0086\\u00E8\\u00A7\\u00A3\\u00E5\\u008C\\u00BF\\u00E5\\u0090\\u008Dcuandoenviarmadridbuscariniciotiempoporquecuentaestadopuedenjuegoscontraest\\u00C3\\u00A1nnombretienenperfilmaneraamigosciudadcentroaunquepuedesdentroprimerprecioseg\\u00C3\\u00BAnbuenosvolverpuntossemanahab\\u00C3\\u00ADaagostonuevosunidoscarlosequiponi\\u00C3\\u00B1osmuchosalgunacorreoimagenpartirarribamar\\u00C3\\u00ADahombreempleoverdadcambiomuchasfueronpasadol\\u00C3\\u00ADneaparecenuevascursosestabaquierolibroscuantoaccesomiguelvarioscuatrotienesgruposser\\u00C3\\u00A1neuropamediosfrenteacercadem\\u00C3\\u00A1sofertacochesmodeloitalialetrasalg\\u00C3\\u00BAncompracualesexistecuerposiendoprensallegarviajesdineromurciapodr\\u00C3\\u00A1puestodiariopuebloquieremanuelpropiocrisisciertoseguromuertefuentecerrargrandeefectopartesmedidapropiaofrecetierrae-mailvariasformasfuturoobjetoseguirriesgonormasmismos\\u00C3\\u00BAnicocaminositiosraz\\u00C3\\u00B3ndebidopruebatoledoten\\u00C3\\u00ADajes\\u00C3\\u00BAsesperococinaorigentiendacientoc\\u00C3\\u00A1dizhablarser\\u00C3\\u00ADalatinafuerzaestiloguerraentrar\\u00C3\\u00A9xitol\\u00C3\\u00B3pezagendav\\u00C3\\u00ADdeoevitarpaginametrosjavierpadresf\\u00C3\\u00A1cilcabeza\\u00C3\\u00A1reassalidaenv\\u00C3\\u00ADojap\\u00C3\\u00B3nabusosbienestextosllevarpuedanfuertecom\\u00C3\\u00BAnclaseshumanotenidobilbaounidadest\\u00C3\\u00A1seditarcreado\\u00D0\\u00B4\\u00D0\\u00BB\\u00D1\\u008F\\u00D1\\u0087\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B2\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B5\\u00D1\\u0089\\u00D0\\u00B5\\u00D1\\u0083\\u00D0\\u00B6\\u00D0\\u00B5\\u00D0\\u009A\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B1\\u00D0\\u00B5\\u00D0\\u00B7\\u00D0\\u00B1\\u00D1\\u008B\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u0092\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00AD\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BD\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00BB\\u00D0\\u00B5\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00B3\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u0094\\u00D0\\u00BB\\u00D1\\u008F\\u00D0\\u009F\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u0085\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BA\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B2\\u00D0\\u00BE\\u00D1\\u0082\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00A1\\u00D0\\u00A8\\u00D0\\u0090\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u008F\\u00D0\\u00A7\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u0083\\u00D0\\u00A2\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B4\\u00D0\\u00B2\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00BC\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00B8\\u00D1\\u008D\\u00D1\\u0082\\u00D1\\u0083\\u00D0\\u0092\\u00D0\\u00B0\\u00D0\\u00BC\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0085\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D1\\u0082\\u00D1\\u0083\\u00D1\\u0082\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00B4\\u00D0\\u00B4\\u00D0\\u00BD\\u00D1\\u008F\\u00D0\\u0092\\u00D0\\u00BE\\u00D1\\u0082\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u0092\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00BC\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00BC\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0082\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00B1\\u00D0\\u009E\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B8\\u00D1\\u0080\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00B5\\u00D0\\u009E\\u00D0\\u009E\\u00D0\\u009E\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u0086\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u009E\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00B4\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00B4\\u00D0\\u00B2\\u00D0\\u00B5\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0083\\u00D0\\u00B4\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0094\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AD\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00BEjagran\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A5\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A5\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0098\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B5\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0093\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0080\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u0089\\u00D8\\u00A5\\u00D9\\u0084\\u00D9\\u0089\\u00D9\\u0087\\u00D8\\u00B0\\u00D8\\u00A7\\u00D8\\u00A2\\u00D8\\u00AE\\u00D8\\u00B1\\u00D8\\u00B9\\u00D8\\u00AF\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0089\\u00D9\\u0087\\u00D8\\u00B0\\u00D9\\u0087\\u00D8\\u00B5\\u00D9\\u0088\\u00D8\\u00B1\\u00D8\\u00BA\\u00D9\\u008A\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0086\\u00D9\\u0088\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00A8\\u00D9\\u008A\\u00D9\\u0086\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00B6\\u00D8\\u00B0\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0087\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u008A\\u00D9\\u0088\\u00D9\\u0085\\u00D9\\u0082\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0086\\u00D8\\u00AD\\u00D8\\u00AA\\u00D9\\u0089\\u00D9\\u0082\\u00D8\\u00A8\\u00D9\\u0084\\u00D9\\u0088\\u00D8\\u00AD\\u00D8\\u00A9\\u00D8\\u00A7\\u00D8\\u00AE\\u00D8\\u00B1\\u00D9\\u0081\\u00D9\\u0082\\u00D8\\u00B7\\u00D8\\u00B9\\u00D8\\u00A8\\u00D8\\u00AF\\u00D8\\u00B1\\u00D9\\u0083\\u00D9\\u0086\\u00D8\\u00A5\\u00D8\\u00B0\\u00D8\\u00A7\\u00D9\\u0083\\u00D9\\u0085\\u00D8\\u00A7\\u00D8\\u00A7\\u00D8\\u00AD\\u00D8\\u00AF\\u00D8\\u00A5\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0081\\u00D9\\u008A\\u00D9\\u0087\\u00D8\\u00A8\\u00D8\\u00B9\\u00D8\\u00B6\\u00D9\\u0083\\u00D9\\u008A\\u00D9\\u0081\\u00D8\\u00A8\\u00D8\\u00AD\\u00D8\\u00AB\\u00D9\\u0088\\u00D9\\u0085\\u00D9\\u0086\\u00D9\\u0088\\u00D9\\u0087\\u00D9\\u0088\\u00D8\\u00A3\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00AC\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00B3\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B9\\u00D9\\u0086\\u00D8\\u00AF\\u00D9\\u0084\\u00D9\\u008A\\u00D8\\u00B3\\u00D8\\u00B9\\u00D8\\u00A8\\u00D8\\u00B1\\u00D8\\u00B5\\u00D9\\u0084\\u00D9\\u0089\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00B0\\u00D8\\u00A8\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00A3\\u00D9\\u0086\\u00D9\\u0087\\u00D9\\u0085\\u00D8\\u00AB\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00AD\\u00D9\\u008A\\u00D8\\u00AB\\u00D9\\u0085\\u00D8\\u00B5\\u00D8\\u00B1\\u00D8\\u00B4\\u00D8\\u00B1\\u00D8\\u00AD\\u00D8\\u00AD\\u00D9\\u0088\\u00D9\\u0084\\u00D9\\u0088\\u00D9\\u0081\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00B0\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B1\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0081\\u00D8\\u00A3\\u00D8\\u00A8\\u00D9\\u0088\\u00D8\\u00AE\\u00D8\\u00A7\\u00D8\\u00B5\\u00D8\\u00A3\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0086\\u00D9\\u0087\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u008A\\u00D8\\u00B9\\u00D8\\u00B6\\u00D9\\u0088\\u00D9\\u0088\\u00D9\\u0082\\u00D8\\u00AF\\u00D8\\u00A7\\u00D8\\u00A8\\u00D9\\u0086\\u00D8\\u00AE\\u00D9\\u008A\\u00D8\\u00B1\\u00D8\\u00A8\\u00D9\\u0086\\u00D8\\u00AA\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D8\\u00A1\\u00D9\\u0088\\u00D9\\u0087\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00A8\\u00D9\\u0088\\u00D9\\u0082\\u00D8\\u00B5\\u00D8\\u00B5\\u00D9\\u0088\\u00D9\\u0085\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0082\\u00D9\\u0085\\u00D8\\u00A3\\u00D8\\u00AD\\u00D8\\u00AF\\u00D9\\u0086\\u00D8\\u00AD\\u00D9\\u0086\\u00D8\\u00B9\\u00D8\\u00AF\\u00D9\\u0085\\u00D8\\u00B1\\u00D8\\u00A3\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AD\\u00D8\\u00A9\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A8\\u00D8\\u00AF\\u00D9\\u0088\\u00D9\\u0086\\u00D9\\u008A\\u00D8\\u00AC\\u00D8\\u00A8\\u00D9\\u0085\\u00D9\\u0086\\u00D9\\u0087\\u00D8\\u00AA\\u00D8\\u00AD\\u00D8\\u00AA\\u00D8\\u00AC\\u00D9\\u0087\\u00D8\\u00A9\\u00D8\\u00B3\\u00D9\\u0086\\u00D8\\u00A9\\u00D9\\u008A\\u00D8\\u00AA\\u00D9\\u0085\\u00D9\\u0083\\u00D8\\u00B1\\u00D8\\u00A9\\u00D8\\u00BA\\u00D8\\u00B2\\u00D8\\u00A9\\u00D9\\u0086\\u00D9\\u0081\\u00D8\\u00B3\\u00D8\\u00A8\\u00D9\\u008A\\u00D8\\u00AA\\u00D9\\u0084\\u00D9\\u0084\\u00D9\\u0087\\u00D9\\u0084\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00AA\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0082\\u00D9\\u0084\\u00D8\\u00A8\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00A7\\u00D8\\u00B9\\u00D9\\u0086\\u00D9\\u0087\\u00D8\\u00A3\\u00D9\\u0088\\u00D9\\u0084\\u00D8\\u00B4\\u00D9\\u008A\\u00D8\\u00A1\\u00D9\\u0086\\u00D9\\u0088\\u00D8\\u00B1\\u00D8\\u00A3\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0081\\u00D9\\u008A\\u00D9\\u0083\\u00D8\\u00A8\\u00D9\\u0083\\u00D9\\u0084\\u00D8\\u00B0\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00B1\\u00D8\\u00AA\\u00D8\\u00A8\\u00D8\\u00A8\\u00D8\\u00A3\\u00D9\\u0086\\u00D9\\u0087\\u00D9\\u0085\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0086\\u00D9\\u0083\\u00D8\\u00A8\\u00D9\\u008A\\u00D8\\u00B9\\u00D9\\u0081\\u00D9\\u0082\\u00D8\\u00AF\\u00D8\\u00AD\\u00D8\\u00B3\\u00D9\\u0086\\u00D9\\u0084\\u00D9\\u0087\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00A3\\u00D9\\u0087\\u00D9\\u0084\\u00D8\\u00B4\\u00D9\\u0087\\u00D8\\u00B1\\u00D9\\u0082\\u00D8\\u00B7\\u00D8\\u00B1\\u00D8\\u00B7\\u00D9\\u0084\\u00D8\\u00A8profileservicedefaulthimselfdetailscontentsupportstartedmessagesuccessfashion<title>countryaccountcreatedstoriesresultsrunningprocesswritingobjectsvisiblewelcomearticleunknownnetworkcompanydynamicbrowserprivacyproblemServicerespectdisplayrequestreservewebsitehistoryfriendsoptionsworkingversionmillionchannelwindow.addressvisitedweathercorrectproductedirectforwardyou canremovedsubjectcontrolarchivecurrentreadinglibrarylimitedmanagerfurthersummarymachineminutesprivatecontextprogramsocietynumberswrittenenabledtriggersourcesloadingelementpartnerfinallyperfectmeaningsystemskeepingculture&quot;,journalprojectsurfaces&quot;expiresreviewsbalanceEnglishContentthroughPlease opinioncontactaverageprimaryvillageSpanishgallerydeclinemeetingmissionpopularqualitymeasuregeneralspeciessessionsectionwriterscounterinitialreportsfiguresmembersholdingdisputeearlierexpressdigitalpictureAnothermarriedtrafficleadingchangedcentralvictoryimages/reasonsstudiesfeaturelistingmust beschoolsVersionusuallyepisodeplayinggrowingobviousoverlaypresentactions</ul>\\r\\nwrapperalreadycertainrealitystorageanotherdesktopofferedpatternunusualDigitalcapitalWebsitefailureconnectreducedAndroiddecadesregular &amp; animalsreleaseAutomatgettingmethodsnothingPopularcaptionletterscapturesciencelicensechangesEngland=1&amp;History = new CentralupdatedSpecialNetworkrequirecommentwarningCollegetoolbarremainsbecauseelectedDeutschfinanceworkersquicklybetweenexactlysettingdiseaseSocietyweaponsexhibit&lt;!--Controlclassescoveredoutlineattacksdevices(windowpurposetitle=\\\"Mobile killingshowingItaliandroppedheavilyeffects-1']);\\nconfirmCurrentadvancesharingopeningdrawingbillionorderedGermanyrelated</form>includewhetherdefinedSciencecatalogArticlebuttonslargestuniformjourneysidebarChicagoholidayGeneralpassage,&quot;animatefeelingarrivedpassingnaturalroughly.\\n\\nThe but notdensityBritainChineselack oftributeIreland\\\" data-factorsreceivethat isLibraryhusbandin factaffairsCharlesradicalbroughtfindinglanding:lang=\\\"return leadersplannedpremiumpackageAmericaEdition]&quot;Messageneed tovalue=\\\"complexlookingstationbelievesmaller-mobilerecordswant tokind ofFirefoxyou aresimilarstudiedmaximumheadingrapidlyclimatekingdomemergedamountsfoundedpioneerformuladynastyhow to SupportrevenueeconomyResultsbrothersoldierlargelycalling.&quot;AccountEdward segmentRobert effortsPacificlearnedup withheight:we haveAngelesnations_searchappliedacquiremassivegranted: falsetreatedbiggestbenefitdrivingStudiesminimumperhapsmorningsellingis usedreversevariant role=\\\"missingachievepromotestudentsomeoneextremerestorebottom:evolvedall thesitemapenglishway to  AugustsymbolsCompanymattersmusicalagainstserving})();\\r\\npaymenttroubleconceptcompareparentsplayersregionsmonitor ''The winningexploreadaptedGalleryproduceabilityenhancecareers). The collectSearch ancientexistedfooter handlerprintedconsoleEasternexportswindowsChannelillegalneutralsuggest_headersigning.html\\\">settledwesterncausing-webkitclaimedJusticechaptervictimsThomas mozillapromisepartieseditionoutside:false,hundredOlympic_buttonauthorsreachedchronicdemandssecondsprotectadoptedprepareneithergreatlygreateroverallimprovecommandspecialsearch.worshipfundingthoughthighestinsteadutilityquarterCulturetestingclearlyexposedBrowserliberal} catchProjectexamplehide();FloridaanswersallowedEmperordefenseseriousfreedomSeveral-buttonFurtherout of != nulltrainedDenmarkvoid(0)/all.jspreventRequestStephen\\n\\nWhen observe</h2>\\r\\nModern provide\\\" alt=\\\"borders.\\n\\nFor \\n\\nMany artistspoweredperformfictiontype ofmedicalticketsopposedCouncilwitnessjusticeGeorge Belgium...</a>twitternotablywaitingwarfare Other rankingphrasesmentionsurvivescholar</p>\\r\\n Countryignoredloss ofjust asGeorgiastrange<head><stopped1']);\\r\\nislandsnotableborder:list ofcarried100,000</h3>\\n severalbecomesselect wedding00.htmlmonarchoff theteacherhighly biologylife ofor evenrise of&raquo;plusonehunting(thoughDouglasjoiningcirclesFor theAncientVietnamvehiclesuch ascrystalvalue =Windowsenjoyeda smallassumed<a id=\\\"foreign All rihow theDisplayretiredhoweverhidden;battlesseekingcabinetwas notlook atconductget theJanuaryhappensturninga:hoverOnline French lackingtypicalextractenemieseven ifgeneratdecidedare not/searchbeliefs-image:locatedstatic.login\\\">convertviolententeredfirst\\\">circuitFinlandchemistshe was10px;\\\">as suchdivided</span>will beline ofa greatmystery/index.fallingdue to railwaycollegemonsterdescentit withnuclearJewish protestBritishflowerspredictreformsbutton who waslectureinstantsuicidegenericperiodsmarketsSocial fishingcombinegraphicwinners<br /><by the NaturalPrivacycookiesoutcomeresolveSwedishbrieflyPersianso muchCenturydepictscolumnshousingscriptsnext tobearingmappingrevisedjQuery(-width:title\\\">tooltipSectiondesignsTurkishyounger.match(})();\\n\\nburningoperatedegreessource=Richardcloselyplasticentries</tr>\\r\\ncolor:#ul id=\\\"possessrollingphysicsfailingexecutecontestlink toDefault<br />\\n: true,chartertourismclassicproceedexplain</h1>\\r\\nonline.?xml vehelpingdiamonduse theairlineend -->).attr(readershosting#ffffffrealizeVincentsignals src=\\\"/ProductdespitediversetellingPublic held inJoseph theatreaffects<style>a largedoesn'tlater, ElementfaviconcreatorHungaryAirportsee theso thatMichaelSystemsPrograms, and  width=e&quot;tradingleft\\\">\\npersonsGolden Affairsgrammarformingdestroyidea ofcase ofoldest this is.src = cartoonregistrCommonsMuslimsWhat isin manymarkingrevealsIndeed,equally/show_aoutdoorescape(Austriageneticsystem,In the sittingHe alsoIslandsAcademy\\n\\t\\t<!--Daniel bindingblock\\\">imposedutilizeAbraham(except{width:putting).html(|| [];\\nDATA[ *kitchenmountedactual dialectmainly _blank'installexpertsif(typeIt also&copy; \\\">Termsborn inOptionseasterntalkingconcerngained ongoingjustifycriticsfactoryits ownassaultinvitedlastinghis ownhref=\\\"/\\\" rel=\\\"developconcertdiagramdollarsclusterphp?id=alcohol);})();using a><span>vesselsrevivalAddressamateurandroidallegedillnesswalkingcentersqualifymatchesunifiedextinctDefensedied in\\n\\t<!-- customslinkingLittle Book ofeveningmin.js?are thekontakttoday's.html\\\" target=wearingAll Rig;\\n})();raising Also, crucialabout\\\">declare-->\\n<scfirefoxas muchappliesindex, s, but type = \\n\\r\\n<!--towardsRecordsPrivateForeignPremierchoicesVirtualreturnsCommentPoweredinline;povertychamberLiving volumesAnthonylogin\\\" RelatedEconomyreachescuttinggravitylife inChapter-shadowNotable</td>\\r\\n returnstadiumwidgetsvaryingtravelsheld bywho arework infacultyangularwho hadairporttown of\\n\\nSome 'click'chargeskeywordit willcity of(this);Andrew unique checkedor more300px; return;rsion=\\\"pluginswithin herselfStationFederalventurepublishsent totensionactresscome tofingersDuke ofpeople,exploitwhat isharmonya major\\\":\\\"httpin his menu\\\">\\nmonthlyofficercouncilgainingeven inSummarydate ofloyaltyfitnessand wasemperorsupremeSecond hearingRussianlongestAlbertalateralset of small\\\">.appenddo withfederalbank ofbeneathDespiteCapitalgrounds), and percentit fromclosingcontainInsteadfifteenas well.yahoo.respondfighterobscurereflectorganic= Math.editingonline paddinga wholeonerroryear ofend of barrierwhen itheader home ofresumedrenamedstrong>heatingretainscloudfrway of March 1knowingin partBetweenlessonsclosestvirtuallinks\\\">crossedEND -->famous awardedLicenseHealth fairly wealthyminimalAfricancompetelabel\\\">singingfarmersBrasil)discussreplaceGregoryfont copursuedappearsmake uproundedboth ofblockedsaw theofficescoloursif(docuwhen heenforcepush(fuAugust UTF-8\\\">Fantasyin mostinjuredUsuallyfarmingclosureobject defenceuse of Medical<body>\\nevidentbe usedkeyCodesixteenIslamic#000000entire widely active (typeofone cancolor =speakerextendsPhysicsterrain<tbody>funeralviewingmiddle cricketprophetshifteddoctorsRussell targetcompactalgebrasocial-bulk ofman and</td>\\n he left).val()false);logicalbankinghome tonaming Arizonacredits);\\n});\\nfounderin turnCollinsbefore But thechargedTitle\\\">CaptainspelledgoddessTag -->Adding:but wasRecent patientback in=false&Lincolnwe knowCounterJudaismscript altered']);\\n  has theunclearEvent',both innot all\\n\\n<!-- placinghard to centersort ofclientsstreetsBernardassertstend tofantasydown inharbourFreedomjewelry/about..searchlegendsis mademodern only ononly toimage\\\" linear painterand notrarely acronymdelivershorter00&amp;as manywidth=\\\"/* <![Ctitle =of the lowest picked escapeduses ofpeoples PublicMatthewtacticsdamagedway forlaws ofeasy to windowstrong  simple}catch(seventhinfoboxwent topaintedcitizenI don'tretreat. Some ww.\\\");\\nbombingmailto:made in. Many carries||{};wiwork ofsynonymdefeatsfavoredopticalpageTraunless sendingleft\\\"><comScorAll thejQuery.touristClassicfalse\\\" Wilhelmsuburbsgenuinebishops.split(global followsbody ofnominalContactsecularleft tochiefly-hidden-banner</li>\\n\\n. When in bothdismissExplorealways via thespa\\u00C3\\u00B1olwelfareruling arrangecaptainhis sonrule ofhe tookitself,=0&amp;(calledsamplesto makecom/pagMartin Kennedyacceptsfull ofhandledBesides//--></able totargetsessencehim to its by common.mineralto takeways tos.org/ladvisedpenaltysimple:if theyLettersa shortHerbertstrikes groups.lengthflightsoverlapslowly lesser social </p>\\n\\t\\tit intoranked rate oful>\\r\\n  attemptpair ofmake itKontaktAntoniohaving ratings activestreamstrapped\\\").css(hostilelead tolittle groups,Picture-->\\r\\n\\r\\n rows=\\\" objectinverse<footerCustomV><\\\\/scrsolvingChamberslaverywoundedwhereas!= 'undfor allpartly -right:Arabianbacked centuryunit ofmobile-Europe,is homerisk ofdesiredClintoncost ofage of become none ofp&quot;Middle ead')[0Criticsstudios>&copy;group\\\">assemblmaking pressedwidget.ps:\\\" ? rebuiltby someFormer editorsdelayedCanonichad thepushingclass=\\\"but arepartialBabylonbottom carrierCommandits useAs withcoursesa thirddenotesalso inHouston20px;\\\">accuseddouble goal ofFamous ).bind(priests Onlinein Julyst + \\\"gconsultdecimalhelpfulrevivedis veryr'+'iptlosing femalesis alsostringsdays ofarrivalfuture <objectforcingString(\\\" />\\n\\t\\there isencoded.  The balloondone by/commonbgcolorlaw of Indianaavoidedbut the2px 3pxjquery.after apolicy.men andfooter-= true;for usescreen.Indian image =family,http:// &nbsp;driverseternalsame asnoticedviewers})();\\n is moreseasonsformer the newis justconsent Searchwas thewhy theshippedbr><br>width: height=made ofcuisineis thata very Admiral fixed;normal MissionPress, ontariocharsettry to invaded=\\\"true\\\"spacingis mosta more totallyfall of});\\r\\n  immensetime inset outsatisfyto finddown tolot of Playersin Junequantumnot thetime todistantFinnishsrc = (single help ofGerman law andlabeledforestscookingspace\\\">header-well asStanleybridges/globalCroatia About [0];\\n  it, andgroupedbeing a){throwhe madelighterethicalFFFFFF\\\"bottom\\\"like a employslive inas seenprintermost ofub-linkrejectsand useimage\\\">succeedfeedingNuclearinformato helpWomen'sNeitherMexicanprotein<table by manyhealthylawsuitdevised.push({sellerssimply Through.cookie Image(older\\\">us.js\\\"> Since universlarger open to!-- endlies in']);\\r\\n  marketwho is (\\\"DOMComanagedone fortypeof Kingdomprofitsproposeto showcenter;made itdressedwere inmixtureprecisearisingsrc = 'make a securedBaptistvoting \\n\\t\\tvar March 2grew upClimate.removeskilledway the</head>face ofacting right\\\">to workreduceshas haderectedshow();action=book ofan area== \\\"htt<header\\n<html>conformfacing cookie.rely onhosted .customhe wentbut forspread Family a meansout theforums.footage\\\">MobilClements\\\" id=\\\"as highintense--><!--female is seenimpliedset thea stateand hisfastestbesidesbutton_bounded\\\"><img Infoboxevents,a youngand areNative cheaperTimeoutand hasengineswon the(mostlyright: find a -bottomPrince area ofmore ofsearch_nature,legallyperiod,land ofor withinducedprovingmissilelocallyAgainstthe wayk&quot;px;\\\">\\r\\npushed abandonnumeralCertainIn thismore inor somename isand, incrownedISBN 0-createsOctobermay notcenter late inDefenceenactedwish tobroadlycoolingonload=it. TherecoverMembersheight assumes<html>\\npeople.in one =windowfooter_a good reklamaothers,to this_cookiepanel\\\">London,definescrushedbaptismcoastalstatus title\\\" move tolost inbetter impliesrivalryservers SystemPerhapses and contendflowinglasted rise inGenesisview ofrising seem tobut in backinghe willgiven agiving cities.flow of Later all butHighwayonly bysign ofhe doesdiffersbattery&amp;lasinglesthreatsintegertake onrefusedcalled =US&ampSee thenativesby thissystem.head of:hover,lesbiansurnameand allcommon/header__paramsHarvard/pixel.removalso longrole ofjointlyskyscraUnicodebr />\\r\\nAtlantanucleusCounty,purely count\\\">easily build aonclicka givenpointerh&quot;events else {\\nditionsnow the, with man whoorg/Webone andcavalryHe diedseattle00,000 {windowhave toif(windand itssolely m&quot;renewedDetroitamongsteither them inSenatorUs</a><King ofFrancis-produche usedart andhim andused byscoringat hometo haverelatesibilityfactionBuffalolink\\\"><what hefree toCity ofcome insectorscountedone daynervoussquare };if(goin whatimg\\\" alis onlysearch/tuesdaylooselySolomonsexual - <a hrmedium\\\"DO NOT France,with a war andsecond take a >\\r\\n\\r\\n\\r\\nmarket.highwaydone inctivity\\\"last\\\">obligedrise to\\\"undefimade to Early praisedin its for hisathleteJupiterYahoo! termed so manyreally s. The a woman?value=direct right\\\" bicycleacing=\\\"day andstatingRather,higher Office are nowtimes, when a pay foron this-link\\\">;borderaround annual the Newput the.com\\\" takin toa brief(in thegroups.; widthenzymessimple in late{returntherapya pointbanninginks\\\">\\n();\\\" rea place\\\\u003Caabout atr>\\r\\n\\t\\tccount gives a<SCRIPTRailwaythemes/toolboxById(\\\"xhumans,watchesin some if (wicoming formats Under but hashanded made bythan infear ofdenoted/iframeleft involtagein eacha&quot;base ofIn manyundergoregimesaction </p>\\r\\n<ustomVa;&gt;</importsor thatmostly &amp;re size=\\\"</a></ha classpassiveHost = WhetherfertileVarious=[];(fucameras/></td>acts asIn some>\\r\\n\\r\\n<!organis <br />Beijingcatal\\u00C3\\u00A0deutscheuropeueuskaragaeilgesvenskaespa\\u00C3\\u00B1amensajeusuariotrabajom\\u00C3\\u00A9xicop\\u00C3\\u00A1ginasiempresistemaoctubredurantea\\u00C3\\u00B1adirempresamomentonuestroprimeratrav\\u00C3\\u00A9sgraciasnuestraprocesoestadoscalidadpersonan\\u00C3\\u00BAmeroacuerdom\\u00C3\\u00BAsicamiembroofertasalgunospa\\u00C3\\u00ADsesejemploderechoadem\\u00C3\\u00A1sprivadoagregarenlacesposiblehotelessevillaprimero\\u00C3\\u00BAltimoeventosarchivoculturamujeresentradaanuncioembargomercadograndesestudiomejoresfebrerodise\\u00C3\\u00B1oturismoc\\u00C3\\u00B3digoportadaespaciofamiliaantoniopermiteguardaralgunaspreciosalguiensentidovisitast\\u00C3\\u00ADtuloconocersegundoconsejofranciaminutossegundatenemosefectosm\\u00C3\\u00A1lagasesi\\u00C3\\u00B3nrevistagranadacompraringresogarc\\u00C3\\u00ADaacci\\u00C3\\u00B3necuadorquienesinclusodeber\\u00C3\\u00A1materiahombresmuestrapodr\\u00C3\\u00ADama\\u00C3\\u00B1ana\\u00C3\\u00BAltimaestamosoficialtambienning\\u00C3\\u00BAnsaludospodemosmejorarpositionbusinesshomepagesecuritylanguagestandardcampaignfeaturescategoryexternalchildrenreservedresearchexchangefavoritetemplatemilitaryindustryservicesmaterialproductsz-index:commentssoftwarecompletecalendarplatformarticlesrequiredmovementquestionbuildingpoliticspossiblereligionphysicalfeedbackregisterpicturesdisabledprotocolaudiencesettingsactivityelementslearninganythingabstractprogressoverviewmagazineeconomictrainingpressurevarious <strong>propertyshoppingtogetheradvancedbehaviordownloadfeaturedfootballselectedLanguagedistanceremembertrackingpasswordmodifiedstudentsdirectlyfightingnortherndatabasefestivalbreakinglocationinternetdropdownpracticeevidencefunctionmarriageresponseproblemsnegativeprogramsanalysisreleasedbanner\\\">purchasepoliciesregionalcreativeargumentbookmarkreferrerchemicaldivisioncallbackseparateprojectsconflicthardwareinterestdeliverymountainobtained= false;for(var acceptedcapacitycomputeridentityaircraftemployedproposeddomesticincludesprovidedhospitalverticalcollapseapproachpartnerslogo\\\"><adaughterauthor\\\" culturalfamilies/images/assemblypowerfulteachingfinisheddistrictcriticalcgi-bin/purposesrequireselectionbecomingprovidesacademicexerciseactuallymedicineconstantaccidentMagazinedocumentstartingbottom\\\">observed: &quot;extendedpreviousSoftwarecustomerdecisionstrengthdetailedslightlyplanningtextareacurrencyeveryonestraighttransferpositiveproducedheritageshippingabsolutereceivedrelevantbutton\\\" violenceanywherebenefitslaunchedrecentlyalliancefollowedmultiplebulletinincludedoccurredinternal$(this).republic><tr><tdcongressrecordedultimatesolution<ul id=\\\"discoverHome</a>websitesnetworksalthoughentirelymemorialmessagescontinueactive\\\">somewhatvictoriaWestern  title=\\\"LocationcontractvisitorsDownloadwithout right\\\">\\nmeasureswidth = variableinvolvedvirginianormallyhappenedaccountsstandingnationalRegisterpreparedcontrolsaccuratebirthdaystrategyofficialgraphicscriminalpossiblyconsumerPersonalspeakingvalidateachieved.jpg\\\" />machines</h2>\\n  keywordsfriendlybrotherscombinedoriginalcomposedexpectedadequatepakistanfollow\\\" valuable</label>relativebringingincreasegovernorplugins/List of Header\\\">\\\" name=\\\" (&quot;graduate</head>\\ncommercemalaysiadirectormaintain;height:schedulechangingback to catholicpatternscolor: #greatestsuppliesreliable</ul>\\n\\t\\t<select citizensclothingwatching<li id=\\\"specificcarryingsentence<center>contrastthinkingcatch(e)southernMichael merchantcarouselpadding:interior.split(\\\"lizationOctober ){returnimproved--&gt;\\n\\ncoveragechairman.png\\\" />subjectsRichard whateverprobablyrecoverybaseballjudgmentconnect..css\\\" /> websitereporteddefault\\\"/></a>\\r\\nelectricscotlandcreationquantity. ISBN 0did not instance-search-\\\" lang=\\\"speakersComputercontainsarchivesministerreactiondiscountItalianocriteriastrongly: 'http:'script'coveringofferingappearedBritish identifyFacebooknumerousvehiclesconcernsAmericanhandlingdiv id=\\\"William provider_contentaccuracysection andersonflexibleCategorylawrence<script>layout=\\\"approved maximumheader\\\"></table>Serviceshamiltoncurrent canadianchannels/themes//articleoptionalportugalvalue=\\\"\\\"intervalwirelessentitledagenciesSearch\\\" measuredthousandspending&hellip;new Date\\\" size=\\\"pageNamemiddle\\\" \\\" /></a>hidden\\\">sequencepersonaloverflowopinionsillinoislinks\\\">\\n\\t<title>versionssaturdayterminalitempropengineersectionsdesignerproposal=\\\"false\\\"Espa\\u00C3\\u00B1olreleasessubmit\\\" er&quot;additionsymptomsorientedresourceright\\\"><pleasurestationshistory.leaving  border=contentscenter\\\">.\\n\\nSome directedsuitablebulgaria.show();designedGeneral conceptsExampleswilliamsOriginal\\\"><span>search\\\">operatorrequestsa &quot;allowingDocumentrevision. \\n\\nThe yourselfContact michiganEnglish columbiapriorityprintingdrinkingfacilityreturnedContent officersRussian generate-8859-1\\\"indicatefamiliar qualitymargin:0 contentviewportcontacts-title\\\">portable.length eligibleinvolvesatlanticonload=\\\"default.suppliedpaymentsglossary\\n\\nAfter guidance</td><tdencodingmiddle\\\">came to displaysscottishjonathanmajoritywidgets.clinicalthailandteachers<head>\\n\\taffectedsupportspointer;toString</small>oklahomawill be investor0\\\" alt=\\\"holidaysResourcelicensed (which . After considervisitingexplorerprimary search\\\" android\\\"quickly meetingsestimate;return ;color:# height=approval, &quot; checked.min.js\\\"magnetic></a></hforecast. While thursdaydvertise&eacute;hasClassevaluateorderingexistingpatients Online coloradoOptions\\\"campbell<!-- end</span><<br />\\r\\n_popups|sciences,&quot; quality Windows assignedheight: <b classle&quot; value=\\\" Companyexamples<iframe believespresentsmarshallpart of properly).\\n\\nThe taxonomymuch of </span>\\n\\\" data-srtugu\\u00C3\\u00AAsscrollTo project<head>\\r\\nattorneyemphasissponsorsfancyboxworld's wildlifechecked=sessionsprogrammpx;font- Projectjournalsbelievedvacationthompsonlightingand the special border=0checking</tbody><button Completeclearfix\\n<head>\\narticle <sectionfindingsrole in popular  Octoberwebsite exposureused to  changesoperatedclickingenteringcommandsinformed numbers  </div>creatingonSubmitmarylandcollegesanalyticlistingscontact.loggedInadvisorysiblingscontent\\\"s&quot;)s. This packagescheckboxsuggestspregnanttomorrowspacing=icon.png\";\n\t\t\t}\n\t\t}\n\n\t\tprivate class DataHolder1\n\t\t{\n\t\t\tinternal static string GetData()\n\t\t\t{\n\t\t\t\treturn \"japanesecodebasebutton\\\">gamblingsuch as , while </span> missourisportingtop:1px .</span>tensionswidth=\\\"2lazyloadnovemberused in height=\\\"cript\\\">\\n&nbsp;</<tr><td height:2/productcountry include footer\\\" &lt;!-- title\\\"></jquery.</form>\\n(\\u00E7\\u00AE\\u0080\\u00E4\\u00BD\\u0093)(\\u00E7\\u00B9\\u0081\\u00E9\\u00AB\\u0094)hrvatskiitalianorom\\u00C3\\u00A2n\\u00C4\\u0083t\\u00C3\\u00BCrk\\u00C3\\u00A7e\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00AF\\u00D9\\u0088tambi\\u00C3\\u00A9nnoticiasmensajespersonasderechosnacionalserviciocontactousuariosprogramagobiernoempresasanunciosvalenciacolombiadespu\\u00C3\\u00A9sdeportesproyectoproductop\\u00C3\\u00BAbliconosotroshistoriapresentemillonesmediantepreguntaanteriorrecursosproblemasantiagonuestrosopini\\u00C3\\u00B3nimprimirmientrasam\\u00C3\\u00A9ricavendedorsociedadrespectorealizarregistropalabrasinter\\u00C3\\u00A9sentoncesespecialmiembrosrealidadc\\u00C3\\u00B3rdobazaragozap\\u00C3\\u00A1ginassocialesbloqueargesti\\u00C3\\u00B3nalquilersistemascienciascompletoversi\\u00C3\\u00B3ncompletaestudiosp\\u00C3\\u00BAblicaobjetivoalicantebuscadorcantidadentradasaccionesarchivossuperiormayor\\u00C3\\u00ADaalemaniafunci\\u00C3\\u00B3n\\u00C3\\u00BAltimoshaciendoaquellosedici\\u00C3\\u00B3nfernandoambientefacebooknuestrasclientesprocesosbastantepresentareportarcongresopublicarcomerciocontratoj\\u00C3\\u00B3venesdistritot\\u00C3\\u00A9cnicaconjuntoenerg\\u00C3\\u00ADatrabajarasturiasrecienteutilizarbolet\\u00C3\\u00ADnsalvadorcorrectatrabajosprimerosnegocioslibertaddetallespantallapr\\u00C3\\u00B3ximoalmer\\u00C3\\u00ADaanimalesqui\\u00C3\\u00A9nescoraz\\u00C3\\u00B3nsecci\\u00C3\\u00B3nbuscandoopcionesexteriorconceptotodav\\u00C3\\u00ADagaler\\u00C3\\u00ADaescribirmedicinalicenciaconsultaaspectoscr\\u00C3\\u00ADticad\\u00C3\\u00B3laresjusticiadeber\\u00C3\\u00A1nper\\u00C3\\u00ADodonecesitamantenerpeque\\u00C3\\u00B1orecibidatribunaltenerifecanci\\u00C3\\u00B3ncanariasdescargadiversosmallorcarequieret\\u00C3\\u00A9cnicodeber\\u00C3\\u00ADaviviendafinanzasadelantefuncionaconsejosdif\\u00C3\\u00ADcilciudadesantiguasavanzadat\\u00C3\\u00A9rminounidadess\\u00C3\\u00A1nchezcampa\\u00C3\\u00B1asoftonicrevistascontienesectoresmomentosfacultadcr\\u00C3\\u00A9ditodiversassupuestofactoressegundospeque\\u00C3\\u00B1a\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00B8\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00B1\\u00D1\\u008B\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u008B\\u00D1\\u0082\\u00D1\\u008C\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u0095\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u008F\\u00D0\\u00B2\\u00D1\\u0081\\u00D0\\u00B5\\u00D1\\u0085\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00B6\\u00D0\\u00B5\\u00D0\\u00B1\\u00D1\\u008B\\u00D0\\u00BB\\u00D0\\u00B8\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00B4\\u00D1\\u0083\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u008C\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B1\\u00D1\\u008B\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B1\\u00D1\\u008F\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B1\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00B4\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00B9\\u00D1\\u0082\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00B8\\u00D0\\u00B3\\u00D1\\u0080\\u00D1\\u008B\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B6\\u00D0\\u00B5\\u00D0\\u00B2\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D1\\u008E\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u0088\\u00D1\\u008C\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00B8\\u00D1\\u0085\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00B4\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u00B4\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00B8\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BB\\u00D0\\u00B8\\u00D0\\u00B1\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u0083\\u00D1\\u0085\\u00D0\\u00BE\\u00D1\\u0082\\u00D1\\u008F\\u00D0\\u00B4\\u00D0\\u00B2\\u00D1\\u0083\\u00D1\\u0085\\u00D1\\u0081\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BB\\u00D1\\u008E\\u00D0\\u00B4\\u00D0\\u00B8\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00B8\\u00D1\\u0080\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00B1\\u00D1\\u008F\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B5\\u00D0\\u00B2\\u00D0\\u00B8\\u00D0\\u00B4\\u00D0\\u00B5\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BC\\u00D1\\u0081\\u00D1\\u0087\\u00D0\\u00B5\\u00D1\\u0082\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u008B\\u00D1\\u0086\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u008B\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BB\\u00D0\\u00B2\\u00D0\\u00B5\\u00D0\\u00B4\\u00D1\\u008C\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B4\\u00D1\\u008B\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00B1\\u00D0\\u00B5\\u00D0\\u00B2\\u00D1\\u008B\\u00D1\\u0088\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BF\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u0083\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u0086\\u00D0\\u00B0\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00B4\\u00D1\\u008B\\u00D0\\u00B7\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u008E\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B3\\u00D1\\u0083\\u00D0\\u00B4\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00B3\\u00D0\\u00B2\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u00B8\\u00D0\\u00B4\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00B0\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00BA\\u00D0\\u00B8\\u00D1\\u008E\\u00D0\\u00BD\\u00D1\\u008F\\u00D0\\u00B2\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u008C\\u00D0\\u0095\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u008C\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0088\\u00D0\\u00B8\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0084\\u00D9\\u0087\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D9\\u008A\\u00D8\\u00AC\\u00D9\\u0085\\u00D9\\u008A\\u00D8\\u00B9\\u00D8\\u00AE\\u00D8\\u00A7\\u00D8\\u00B5\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B0\\u00D9\\u008A\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u0087\\u00D8\\u00AC\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A2\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00AF\\u00D8\\u00AA\\u00D8\\u00AD\\u00D9\\u0083\\u00D9\\u0085\\u00D8\\u00B5\\u00D9\\u0081\\u00D8\\u00AD\\u00D8\\u00A9\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u008A\\u00D9\\u0083\\u00D9\\u0088\\u00D9\\u0086\\u00D8\\u00B4\\u00D8\\u00A8\\u00D9\\u0083\\u00D8\\u00A9\\u00D9\\u0081\\u00D9\\u008A\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00A8\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00AD\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00A1\\u00D8\\u00A3\\u00D9\\u0083\\u00D8\\u00AB\\u00D8\\u00B1\\u00D8\\u00AE\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AD\\u00D8\\u00A8\\u00D8\\u00AF\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u0084\\u00D8\\u00AF\\u00D8\\u00B1\\u00D9\\u0088\\u00D8\\u00B3\\u00D8\\u00A7\\u00D8\\u00B6\\u00D8\\u00BA\\u00D8\\u00B7\\u00D8\\u00AA\\u00D9\\u0083\\u00D9\\u0088\\u00D9\\u0086\\u00D9\\u0087\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0083\\u00D8\\u00B3\\u00D8\\u00A7\\u00D8\\u00AD\\u00D8\\u00A9\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B7\\u00D8\\u00A8\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u0083\\u00D8\\u00B4\\u00D9\\u0083\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u008A\\u00D9\\u0085\\u00D9\\u0083\\u00D9\\u0086\\u00D9\\u0085\\u00D9\\u0086\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00B4\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A9\\u00D8\\u00B1\\u00D8\\u00A6\\u00D9\\u008A\\u00D8\\u00B3\\u00D9\\u0086\\u00D8\\u00B4\\u00D9\\u008A\\u00D8\\u00B7\\u00D9\\u0085\\u00D8\\u00A7\\u00D8\\u00B0\\u00D8\\u00A7\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0081\\u00D9\\u0086\\u00D8\\u00B4\\u00D8\\u00A8\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00AA\\u00D8\\u00B9\\u00D8\\u00A8\\u00D8\\u00B1\\u00D8\\u00B1\\u00D8\\u00AD\\u00D9\\u0085\\u00D8\\u00A9\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0081\\u00D8\\u00A9\\u00D9\\u008A\\u00D9\\u0082\\u00D9\\u0088\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00B2\\u00D9\\u0083\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00A9\\u00D8\\u00A3\\u00D8\\u00AD\\u00D9\\u0085\\u00D8\\u00AF\\u00D9\\u0082\\u00D9\\u0084\\u00D8\\u00A8\\u00D9\\u008A\\u00D9\\u008A\\u00D8\\u00B9\\u00D9\\u0086\\u00D9\\u008A\\u00D8\\u00B5\\u00D9\\u0088\\u00D8\\u00B1\\u00D8\\u00A9\\u00D8\\u00B7\\u00D8\\u00B1\\u00D9\\u008A\\u00D9\\u0082\\u00D8\\u00B4\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00AC\\u00D9\\u0088\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D8\\u00AE\\u00D8\\u00B1\\u00D9\\u0089\\u00D9\\u0085\\u00D8\\u00B9\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00AD\\u00D8\\u00AB\\u00D8\\u00B9\\u00D8\\u00B1\\u00D9\\u0088\\u00D8\\u00B6\\u00D8\\u00A8\\u00D8\\u00B4\\u00D9\\u0083\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B3\\u00D8\\u00AC\\u00D9\\u0084\\u00D8\\u00A8\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0086\\u00D8\\u00AE\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A7\\u00D8\\u00A8\\u00D9\\u0083\\u00D9\\u0084\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A8\\u00D8\\u00AF\\u00D9\\u0088\\u00D9\\u0086\\u00D8\\u00A3\\u00D9\\u008A\\u00D8\\u00B6\\u00D8\\u00A7\\u00D9\\u008A\\u00D9\\u0088\\u00D8\\u00AC\\u00D8\\u00AF\\u00D9\\u0081\\u00D8\\u00B1\\u00D9\\u008A\\u00D9\\u0082\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A8\\u00D8\\u00AA\\u00D8\\u00A3\\u00D9\\u0081\\u00D8\\u00B6\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B7\\u00D8\\u00A8\\u00D8\\u00AE\\u00D8\\u00A7\\u00D9\\u0083\\u00D8\\u00AB\\u00D8\\u00B1\\u00D8\\u00A8\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0081\\u00D8\\u00B6\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00AD\\u00D9\\u0084\\u00D9\\u0089\\u00D9\\u0086\\u00D9\\u0081\\u00D8\\u00B3\\u00D9\\u0087\\u00D8\\u00A3\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00B1\\u00D8\\u00AF\\u00D9\\u0088\\u00D8\\u00AF\\u00D8\\u00A3\\u00D9\\u0086\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00AF\\u00D9\\u008A\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0086\\u00D9\\u0085\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00B6\\u00D8\\u00AA\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00AF\\u00D8\\u00A7\\u00D8\\u00AE\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0085\\u00D9\\u0083\\u00D9\\u0086\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0001\\u0000\\u0001\\u0000\\u0001\\u0000\\u0001\\u0000\\u0002\\u0000\\u0002\\u0000\\u0002\\u0000\\u0002\\u0000\\u0004\\u0000\\u0004\\u0000\\u0004\\u0000\\u0004\\u0000\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\u0007\\u0006\\u0005\\u0004\\u0003\\u0002\\u0001\\u0000\\u0008\\t\\n\\u000B\\u000C\\r\\u000E\\u000F\\u000F\\u000E\\r\\u000C\\u000B\\n\\t\\u0008\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0017\\u0016\\u0015\\u0014\\u0013\\u0012\\u0011\\u0010\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\\u001F\\u001E\\u001D\\u001C\\u001B\\u001A\\u0019\\u0018\\u00FF\\u00FF\\u00FF\\u00FF\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u00FF\\u00FF\\u00FF\\u00FF\\u0001\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0002\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u0000\\u0003\\u0000\\u0000\\u0000\\u00FF\\u00FF\\u0000\\u0001\\u0000\\u0000\\u0000\\u0001\\u0000\\u0000\\u00FF\\u00FF\\u0000\\u0001\\u0000\\u0000\\u0000\\u0008\\u0000\\u0008\\u0000\\u0008\\u0000\\u0008\\u0000\\u0000\\u0000\\u0001\\u0000\\u0002\\u0000\\u0003\\u0000\\u0004\\u0000\\u0005\\u0000\\u0006\\u0000\\u0007resourcescountriesquestionsequipmentcommunityavailablehighlightDTD/xhtmlmarketingknowledgesomethingcontainerdirectionsubscribeadvertisecharacter\\\" value=\\\"</select>Australia\\\" class=\\\"situationauthorityfollowingprimarilyoperationchallengedevelopedanonymousfunction functionscompaniesstructureagreement\\\" title=\\\"potentialeducationargumentssecondarycopyrightlanguagesexclusivecondition</form>\\r\\nstatementattentionBiography} else {\\nsolutionswhen the Analyticstemplatesdangeroussatellitedocumentspublisherimportantprototypeinfluence&raquo;</effectivegenerallytransformbeautifultransportorganizedpublishedprominentuntil thethumbnailNational .focus();over the migrationannouncedfooter\\\">\\nexceptionless thanexpensiveformationframeworkterritoryndicationcurrentlyclassNamecriticismtraditionelsewhereAlexanderappointedmaterialsbroadcastmentionedaffiliate</option>treatmentdifferent/default.Presidentonclick=\\\"biographyotherwisepermanentFran\\u00C3\\u00A7aisHollywoodexpansionstandards</style>\\nreductionDecember preferredCambridgeopponentsBusiness confusion>\\n<title>presentedexplaineddoes not worldwideinterfacepositionsnewspaper</table>\\nmountainslike the essentialfinancialselectionaction=\\\"/abandonedEducationparseInt(stabilityunable to</title>\\nrelationsNote thatefficientperformedtwo yearsSince thethereforewrapper\\\">alternateincreasedBattle ofperceivedtrying tonecessaryportrayedelectionsElizabeth</iframe>discoveryinsurances.length;legendaryGeographycandidatecorporatesometimesservices.inherited</strong>CommunityreligiouslocationsCommitteebuildingsthe worldno longerbeginningreferencecannot befrequencytypicallyinto the relative;recordingpresidentinitiallytechniquethe otherit can beexistenceunderlinethis timetelephoneitemscopepracticesadvantage);return For otherprovidingdemocracyboth the extensivesufferingsupportedcomputers functionpracticalsaid thatit may beEnglish</from the scheduleddownloads</label>\\nsuspectedmargin: 0spiritual</head>\\n\\nmicrosoftgraduallydiscussedhe becameexecutivejquery.jshouseholdconfirmedpurchasedliterallydestroyedup to thevariationremainingit is notcenturiesJapanese among thecompletedalgorithminterestsrebellionundefinedencourageresizableinvolvingsensitiveuniversalprovision(althoughfeaturingconducted), which continued-header\\\">February numerous overflow:componentfragmentsexcellentcolspan=\\\"technicalnear the Advanced source ofexpressedHong Kong Facebookmultiple mechanismelevationoffensive</form>\\n\\tsponsoreddocument.or &quot;there arethose whomovementsprocessesdifficultsubmittedrecommendconvincedpromoting\\\" width=\\\".replace(classicalcoalitionhis firstdecisionsassistantindicatedevolution-wrapper\\\"enough toalong thedelivered-->\\r\\n<!--American protectedNovember </style><furnitureInternet  onblur=\\\"suspendedrecipientbased on Moreover,abolishedcollectedwere madeemotionalemergencynarrativeadvocatespx;bordercommitteddir=\\\"ltr\\\"employeesresearch. selectedsuccessorcustomersdisplayedSeptemberaddClass(Facebook suggestedand lateroperatingelaborateSometimesInstitutecertainlyinstalledfollowersJerusalemthey havecomputinggeneratedprovincesguaranteearbitraryrecognizewanted topx;width:theory ofbehaviourWhile theestimatedbegan to it becamemagnitudemust havemore thanDirectoryextensionsecretarynaturallyoccurringvariablesgiven theplatform.</label><failed tocompoundskinds of societiesalongside --&gt;\\n\\nsouthwestthe rightradiationmay have unescape(spoken in\\\" href=\\\"/programmeonly the come fromdirectoryburied ina similarthey were</font></Norwegianspecifiedproducingpassenger(new DatetemporaryfictionalAfter theequationsdownload.regularlydeveloperabove thelinked tophenomenaperiod oftooltip\\\">substanceautomaticaspect ofAmong theconnectedestimatesAir Forcesystem ofobjectiveimmediatemaking itpaintingsconqueredare stillproceduregrowth ofheaded byEuropean divisionsmoleculesfranchiseintentionattractedchildhoodalso useddedicatedsingaporedegree offather ofconflicts</a></p>\\ncame fromwere usednote thatreceivingExecutiveeven moreaccess tocommanderPoliticalmusiciansdeliciousprisonersadvent ofUTF-8\\\" /><![CDATA[\\\">ContactSouthern bgcolor=\\\"series of. It was in Europepermittedvalidate.appearingofficialsseriously-languageinitiatedextendinglong-terminflationsuch thatgetCookiemarked by</button>implementbut it isincreasesdown the requiringdependent-->\\n<!-- interviewWith the copies ofconsensuswas builtVenezuela(formerlythe statepersonnelstrategicfavour ofinventionWikipediacontinentvirtuallywhich wasprincipleComplete identicalshow thatprimitiveaway frommolecularpreciselydissolvedUnder theversion=\\\">&nbsp;</It is the This is will haveorganismssome timeFriedrichwas firstthe only fact thatform id=\\\"precedingTechnicalphysicistoccurs innavigatorsection\\\">span id=\\\"sought tobelow thesurviving}</style>his deathas in thecaused bypartiallyexisting using thewas givena list oflevels ofnotion ofOfficial dismissedscientistresemblesduplicateexplosiverecoveredall othergalleries{padding:people ofregion ofaddressesassociateimg alt=\\\"in modernshould bemethod ofreportingtimestampneeded tothe Greatregardingseemed toviewed asimpact onidea thatthe Worldheight ofexpandingThese arecurrent\\\">carefullymaintainscharge ofClassicaladdressedpredictedownership<div id=\\\"right\\\">\\r\\nresidenceleave thecontent\\\">are often  })();\\r\\nprobably Professor-button\\\" respondedsays thathad to beplaced inHungarianstatus ofserves asUniversalexecutionaggregatefor whichinfectionagreed tohowever, popular\\\">placed onconstructelectoralsymbol ofincludingreturn toarchitectChristianprevious living ineasier toprofessor\\n&lt;!-- effect ofanalyticswas takenwhere thetook overbelief inAfrikaansas far aspreventedwork witha special<fieldsetChristmasRetrieved\\n\\nIn the back intonortheastmagazines><strong>committeegoverninggroups ofstored inestablisha generalits firsttheir ownpopulatedan objectCaribbeanallow thedistrictswisconsinlocation.; width: inhabitedSocialistJanuary 1</footer>similarlychoice ofthe same specific business The first.length; desire todeal withsince theuserAgentconceivedindex.phpas &quot;engage inrecently,few yearswere also\\n<head>\\n<edited byare knowncities inaccesskeycondemnedalso haveservices,family ofSchool ofconvertednature of languageministers</object>there is a popularsequencesadvocatedThey wereany otherlocation=enter themuch morereflectedwas namedoriginal a typicalwhen theyengineerscould notresidentswednesdaythe third productsJanuary 2what theya certainreactionsprocessorafter histhe last contained\\\"></div>\\n</a></td>depend onsearch\\\">\\npieces ofcompetingReferencetennesseewhich has version=</span> <</header>gives thehistorianvalue=\\\"\\\">padding:0view thattogether,the most was foundsubset ofattack onchildren,points ofpersonal position:allegedlyClevelandwas laterand afterare givenwas stillscrollingdesign ofmakes themuch lessAmericans.\\n\\nAfter , but theMuseum oflouisiana(from theminnesotaparticlesa processDominicanvolume ofreturningdefensive00px|righmade frommouseover\\\" style=\\\"states of(which iscontinuesFranciscobuilding without awith somewho woulda form ofa part ofbefore itknown as  Serviceslocation and oftenmeasuringand it ispaperbackvalues of\\r\\n<title>= window.determineer&quot; played byand early</center>from thisthe threepower andof &quot;innerHTML<a href=\\\"y:inline;Church ofthe eventvery highofficial -height: content=\\\"/cgi-bin/to createafrikaansesperantofran\\u00C3\\u00A7aislatvie\\u00C5\\u00A1ulietuvi\\u00C5\\u00B3\\u00C4\\u008Ce\\u00C5\\u00A1tina\\u00C4\\u008De\\u00C5\\u00A1tina\\u00E0\\u00B9\\u0084\\u00E0\\u00B8\\u0097\\u00E0\\u00B8\\u00A2\\u00E6\\u0097\\u00A5\\u00E6\\u009C\\u00AC\\u00E8\\u00AA\\u009E\\u00E7\\u00AE\\u0080\\u00E4\\u00BD\\u0093\\u00E5\\u00AD\\u0097\\u00E7\\u00B9\\u0081\\u00E9\\u00AB\\u0094\\u00E5\\u00AD\\u0097\\u00ED\\u0095\\u009C\\u00EA\\u00B5\\u00AD\\u00EC\\u0096\\u00B4\\u00E4\\u00B8\\u00BA\\u00E4\\u00BB\\u0080\\u00E4\\u00B9\\u0088\\u00E8\\u00AE\\u00A1\\u00E7\\u00AE\\u0097\\u00E6\\u009C\\u00BA\\u00E7\\u00AC\\u0094\\u00E8\\u00AE\\u00B0\\u00E6\\u009C\\u00AC\\u00E8\\u00A8\\u008E\\u00E8\\u00AB\\u0096\\u00E5\\u008D\\u0080\\u00E6\\u009C\\u008D\\u00E5\\u008A\\u00A1\\u00E5\\u0099\\u00A8\\u00E4\\u00BA\\u0092\\u00E8\\u0081\\u0094\\u00E7\\u00BD\\u0091\\u00E6\\u0088\\u00BF\\u00E5\\u009C\\u00B0\\u00E4\\u00BA\\u00A7\\u00E4\\u00BF\\u00B1\\u00E4\\u00B9\\u0090\\u00E9\\u0083\\u00A8\\u00E5\\u0087\\u00BA\\u00E7\\u0089\\u0088\\u00E7\\u00A4\\u00BE\\u00E6\\u008E\\u0092\\u00E8\\u00A1\\u008C\\u00E6\\u00A6\\u009C\\u00E9\\u0083\\u00A8\\u00E8\\u0090\\u00BD\\u00E6\\u00A0\\u00BC\\u00E8\\u00BF\\u009B\\u00E4\\u00B8\\u0080\\u00E6\\u00AD\\u00A5\\u00E6\\u0094\\u00AF\\u00E4\\u00BB\\u0098\\u00E5\\u00AE\\u009D\\u00E9\\u00AA\\u008C\\u00E8\\u00AF\\u0081\\u00E7\\u00A0\\u0081\\u00E5\\u00A7\\u0094\\u00E5\\u0091\\u0098\\u00E4\\u00BC\\u009A\\u00E6\\u0095\\u00B0\\u00E6\\u008D\\u00AE\\u00E5\\u00BA\\u0093\\u00E6\\u00B6\\u0088\\u00E8\\u00B4\\u00B9\\u00E8\\u0080\\u0085\\u00E5\\u008A\\u009E\\u00E5\\u0085\\u00AC\\u00E5\\u00AE\\u00A4\\u00E8\\u00AE\\u00A8\\u00E8\\u00AE\\u00BA\\u00E5\\u008C\\u00BA\\u00E6\\u00B7\\u00B1\\u00E5\\u009C\\u00B3\\u00E5\\u00B8\\u0082\\u00E6\\u0092\\u00AD\\u00E6\\u0094\\u00BE\\u00E5\\u0099\\u00A8\\u00E5\\u008C\\u0097\\u00E4\\u00BA\\u00AC\\u00E5\\u00B8\\u0082\\u00E5\\u00A4\\u00A7\\u00E5\\u00AD\\u00A6\\u00E7\\u0094\\u009F\\u00E8\\u00B6\\u008A\\u00E6\\u009D\\u00A5\\u00E8\\u00B6\\u008A\\u00E7\\u00AE\\u00A1\\u00E7\\u0090\\u0086\\u00E5\\u0091\\u0098\\u00E4\\u00BF\\u00A1\\u00E6\\u0081\\u00AF\\u00E7\\u00BD\\u0091serviciosart\\u00C3\\u00ADculoargentinabarcelonacualquierpublicadoproductospol\\u00C3\\u00ADticarespuestawikipediasiguienteb\\u00C3\\u00BAsquedacomunidadseguridadprincipalpreguntascontenidorespondervenezuelaproblemasdiciembrerelaci\\u00C3\\u00B3nnoviembresimilaresproyectosprogramasinstitutoactividadencuentraeconom\\u00C3\\u00ADaim\\u00C3\\u00A1genescontactardescargarnecesarioatenci\\u00C3\\u00B3ntel\\u00C3\\u00A9fonocomisi\\u00C3\\u00B3ncancionescapacidadencontraran\\u00C3\\u00A1lisisfavoritost\\u00C3\\u00A9rminosprovinciaetiquetaselementosfuncionesresultadocar\\u00C3\\u00A1cterpropiedadprincipionecesidadmunicipalcreaci\\u00C3\\u00B3ndescargaspresenciacomercialopinionesejercicioeditorialsalamancagonz\\u00C3\\u00A1lezdocumentopel\\u00C3\\u00ADcularecientesgeneralestarragonapr\\u00C3\\u00A1cticanovedadespropuestapacientest\\u00C3\\u00A9cnicasobjetivoscontactos\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u009B\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AD\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4diplodocs\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AB\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0094\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u0096\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u008C\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u0089\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00AD\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u0081\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u0096\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00AD\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0090\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u008A\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0090\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0089\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0081\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008C\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u0096\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u0080categoriesexperience</title>\\r\\nCopyright javascriptconditionseverything<p class=\\\"technologybackground<a class=\\\"management&copy; 201javaScriptcharactersbreadcrumbthemselveshorizontalgovernmentCaliforniaactivitiesdiscoveredNavigationtransitionconnectionnavigationappearance</title><mcheckbox\\\" techniquesprotectionapparentlyas well asunt', 'UA-resolutionoperationstelevisiontranslatedWashingtonnavigator. = window.impression&lt;br&gt;literaturepopulationbgcolor=\\\"#especially content=\\\"productionnewsletterpropertiesdefinitionleadershipTechnologyParliamentcomparisonul class=\\\".indexOf(\\\"conclusiondiscussioncomponentsbiologicalRevolution_containerunderstoodnoscript><permissioneach otheratmosphere onfocus=\\\"<form id=\\\"processingthis.valuegenerationConferencesubsequentwell-knownvariationsreputationphenomenondisciplinelogo.png\\\" (document,boundariesexpressionsettlementBackgroundout of theenterprise(\\\"https:\\\" unescape(\\\"password\\\" democratic<a href=\\\"/wrapper\\\">\\nmembershiplinguisticpx;paddingphilosophyassistanceuniversityfacilitiesrecognizedpreferenceif (typeofmaintainedvocabularyhypothesis.submit();&amp;nbsp;annotationbehind theFoundationpublisher\\\"assumptionintroducedcorruptionscientistsexplicitlyinstead ofdimensions onClick=\\\"considereddepartmentoccupationsoon afterinvestmentpronouncedidentifiedexperimentManagementgeographic\\\" height=\\\"link rel=\\\".replace(/depressionconferencepunishmenteliminatedresistanceadaptationoppositionwell knownsupplementdeterminedh1 class=\\\"0px;marginmechanicalstatisticscelebratedGovernment\\n\\nDuring tdevelopersartificialequivalentoriginatedCommissionattachment<span id=\\\"there wereNederlandsbeyond theregisteredjournalistfrequentlyall of thelang=\\\"en\\\" </style>\\r\\nabsolute; supportingextremely mainstream</strong> popularityemployment</table>\\r\\n colspan=\\\"</form>\\n  conversionabout the </p></div>integrated\\\" lang=\\\"enPortuguesesubstituteindividualimpossiblemultimediaalmost allpx solid #apart fromsubject toin Englishcriticizedexcept forguidelinesoriginallyremarkablethe secondh2 class=\\\"<a title=\\\"(includingparametersprohibited= \\\"http://dictionaryperceptionrevolutionfoundationpx;height:successfulsupportersmillenniumhis fatherthe &quot;no-repeat;commercialindustrialencouragedamount of unofficialefficiencyReferencescoordinatedisclaimerexpeditiondevelopingcalculatedsimplifiedlegitimatesubstring(0\\\" class=\\\"completelyillustratefive yearsinstrumentPublishing1\\\" class=\\\"psychologyconfidencenumber of absence offocused onjoined thestructurespreviously></iframe>once againbut ratherimmigrantsof course,a group ofLiteratureUnlike the</a>&nbsp;\\nfunction it was theConventionautomobileProtestantaggressiveafter the Similarly,\\\" /></div>collection\\r\\nfunctionvisibilitythe use ofvolunteersattractionunder the threatened*<![CDATA[importancein generalthe latter</form>\\n</.indexOf('i = 0; i <differencedevoted totraditionssearch forultimatelytournamentattributesso-called }\\n</style>evaluationemphasizedaccessible</section>successionalong withMeanwhile,industries</a><br />has becomeaspects ofTelevisionsufficientbasketballboth sidescontinuingan article<img alt=\\\"adventureshis mothermanchesterprinciplesparticularcommentaryeffects ofdecided to\\\"><strong>publishersJournal ofdifficultyfacilitateacceptablestyle.css\\\"\\tfunction innovation>Copyrightsituationswould havebusinessesDictionarystatementsoften usedpersistentin Januarycomprising</title>\\n\\tdiplomaticcontainingperformingextensionsmay not beconcept of onclick=\\\"It is alsofinancial making theLuxembourgadditionalare calledengaged in\\\"script\\\");but it waselectroniconsubmit=\\\"\\n<!-- End electricalofficiallysuggestiontop of theunlike theAustralianOriginallyreferences\\n</head>\\r\\nrecognisedinitializelimited toAlexandriaretirementAdventuresfour years\\n\\n&lt;!-- increasingdecorationh3 class=\\\"origins ofobligationregulationclassified(function(advantagesbeing the historians<base hrefrepeatedlywilling tocomparabledesignatednominationfunctionalinside therevelationend of thes for the authorizedrefused totake placeautonomouscompromisepolitical restauranttwo of theFebruary 2quality ofswfobject.understandnearly allwritten byinterviews\\\" width=\\\"1withdrawalfloat:leftis usuallycandidatesnewspapersmysteriousDepartmentbest knownparliamentsuppressedconvenientremembereddifferent systematichas led topropagandacontrolledinfluencesceremonialproclaimedProtectionli class=\\\"Scientificclass=\\\"no-trademarksmore than widespreadLiberationtook placeday of theas long asimprisonedAdditional\\n<head>\\n<mLaboratoryNovember 2exceptionsIndustrialvariety offloat: lefDuring theassessmenthave been deals withStatisticsoccurrence/ul></div>clearfix\\\">the publicmany yearswhich wereover time,synonymouscontent\\\">\\npresumablyhis familyuserAgent.unexpectedincluding challengeda minorityundefined\\\"belongs totaken fromin Octoberposition: said to bereligious Federation rowspan=\\\"only a fewmeant thatled to the-->\\r\\n<div <fieldset>Archbishop class=\\\"nobeing usedapproachesprivilegesnoscript>\\nresults inmay be theEaster eggmechanismsreasonablePopulationCollectionselected\\\">noscript>\\r/index.phparrival of-jssdk'));managed toincompletecasualtiescompletionChristiansSeptember arithmeticproceduresmight haveProductionit appearsPhilosophyfriendshipleading togiving thetoward theguaranteeddocumentedcolor:#000video gamecommissionreflectingchange theassociatedsans-serifonkeypress; padding:He was theunderlyingtypically , and the srcElementsuccessivesince the should be networkingaccountinguse of thelower thanshows that</span>\\n\\t\\tcomplaintscontinuousquantitiesastronomerhe did notdue to itsapplied toan averageefforts tothe futureattempt toTherefore,capabilityRepublicanwas formedElectronickilometerschallengespublishingthe formerindigenousdirectionssubsidiaryconspiracydetails ofand in theaffordablesubstancesreason forconventionitemtype=\\\"absolutelysupposedlyremained aattractivetravellingseparatelyfocuses onelementaryapplicablefound thatstylesheetmanuscriptstands for no-repeat(sometimesCommercialin Americaundertakenquarter ofan examplepersonallyindex.php?</button>\\npercentagebest-knowncreating a\\\" dir=\\\"ltrLieutenant\\n<div id=\\\"they wouldability ofmade up ofnoted thatclear thatargue thatto anotherchildren'spurpose offormulatedbased uponthe regionsubject ofpassengerspossession.\\n\\nIn the Before theafterwardscurrently across thescientificcommunity.capitalismin Germanyright-wingthe systemSociety ofpoliticiandirection:went on toremoval of New York apartmentsindicationduring theunless thehistoricalhad been adefinitiveingredientattendanceCenter forprominencereadyStatestrategiesbut in theas part ofconstituteclaim thatlaboratorycompatiblefailure of, such as began withusing the to providefeature offrom which/\\\" class=\\\"geologicalseveral ofdeliberateimportant holds thating&quot; valign=topthe Germanoutside ofnegotiatedhis careerseparationid=\\\"searchwas calledthe fourthrecreationother thanpreventionwhile the education,connectingaccuratelywere builtwas killedagreementsmuch more Due to thewidth: 100some otherKingdom ofthe entirefamous forto connectobjectivesthe Frenchpeople andfeatured\\\">is said tostructuralreferendummost oftena separate->\\n<div id Official worldwide.aria-labelthe planetand it wasd\\\" value=\\\"looking atbeneficialare in themonitoringreportedlythe modernworking onallowed towhere the innovative</a></div>soundtracksearchFormtend to beinput id=\\\"opening ofrestrictedadopted byaddressingtheologianmethods ofvariant ofChristian very largeautomotiveby far therange frompursuit offollow thebrought toin Englandagree thataccused ofcomes frompreventingdiv style=his or hertremendousfreedom ofconcerning0 1em 1em;Basketball/style.cssan earliereven after/\\\" title=\\\".com/indextaking thepittsburghcontent\\\">\\r<script>(fturned outhaving the</span>\\r\\n occasionalbecause itstarted tophysically></div>\\n  created byCurrently, bgcolor=\\\"tabindex=\\\"disastrousAnalytics also has a><div id=\\\"</style>\\n<called forsinger and.src = \\\"//violationsthis pointconstantlyis locatedrecordingsd from thenederlandsportugu\\u00C3\\u00AAs\\u00D7\\u00A2\\u00D7\\u0091\\u00D7\\u00A8\\u00D7\\u0099\\u00D7\\u00AA\\u00D9\\u0081\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00B3\\u00DB\\u008Cdesarrollocomentarioeducaci\\u00C3\\u00B3nseptiembreregistradodirecci\\u00C3\\u00B3nubicaci\\u00C3\\u00B3npublicidadrespuestasresultadosimportantereservadosart\\u00C3\\u00ADculosdiferentessiguientesrep\\u00C3\\u00BAblicasituaci\\u00C3\\u00B3nministerioprivacidaddirectorioformaci\\u00C3\\u00B3npoblaci\\u00C3\\u00B3npresidentecontenidosaccesoriostechnoratipersonalescategor\\u00C3\\u00ADaespecialesdisponibleactualidadreferenciavalladolidbibliotecarelacionescalendariopol\\u00C3\\u00ADticasanterioresdocumentosnaturalezamaterialesdiferenciaecon\\u00C3\\u00B3micatransporterodr\\u00C3\\u00ADguezparticiparencuentrandiscusi\\u00C3\\u00B3nestructurafundaci\\u00C3\\u00B3nfrecuentespermanentetotalmente\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B6\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u0083\\u00D0\\u00B4\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B6\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B2\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u008F\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B6\\u00D0\\u00B5\\u00D1\\u0087\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u008B\\u00D0\\u00B1\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00B5\\u00D0\\u00BE\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u008C\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00B2\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00B9\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0087\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00B7\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B3\\u00D1\\u0083\\u00D1\\u0082\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00B9\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00B6\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00B6\\u00D0\\u00B4\\u00D1\\u0083\\u00D0\\u00B1\\u00D1\\u0083\\u00D0\\u00B4\\u00D1\\u0083\\u00D1\\u0082\\u00D0\\u009F\\u00D0\\u00BE\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B7\\u00D0\\u00B4\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u008C\\u00D0\\u00B2\\u00D0\\u00B8\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00B2\\u00D1\\u008F\\u00D0\\u00B7\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u0083\\u00D0\\u00B6\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u00BB\\u00D1\\u008E\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00B9\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B8\\u00D1\\u0085\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B6\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00BD\\u00D1\\u008C\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00BB\\u00D1\\u0083\\u00D1\\u0087\\u00D1\\u0088\\u00D0\\u00B5\\u00D0\\u00BF\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00B4\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u008C\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B1\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B2\\u00D1\\u008B\\u00D1\\u0085\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00B1\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00B5\\u00D1\\u0087\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B2\\u00D1\\u008B\\u00D0\\u00B5\\u00D1\\u0083\\u00D1\\u0081\\u00D0\\u00BB\\u00D1\\u0083\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00B0\\u00D0\\u00B4\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u0087\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u009F\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B2\\u00D1\\u008B\\u00D0\\u00B9\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B8\\u00D1\\u0085\\u00D1\\u0081\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D1\\u0083\\u00D0\\u00A1\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00BA\\u00D1\\u0082\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00BC\\u00D0\\u009A\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B3\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0088\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00B9\\u00D1\\u0082\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B8\\u00D0\\u00BC\\u00D1\\u0081\\u00D0\\u00B2\\u00D1\\u008F\\u00D0\\u00B7\\u00D1\\u008C\\u00D0\\u00BB\\u00D1\\u008E\\u00D0\\u00B1\\u00D0\\u00BE\\u00D0\\u00B9\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00B4\\u00D0\\u00B8\\u00D0\\u009A\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00A4\\u00D0\\u00BE\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00BC\\u00D1\\u0080\\u00D1\\u008B\\u00D0\\u00BD\\u00D0\\u00BA\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BB\\u00D0\\u00B8\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00BA\\u00D1\\u0082\\u00D1\\u008B\\u00D1\\u0081\\u00D1\\u008F\\u00D1\\u0087\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u008F\\u00D1\\u0086\\u00D1\\u0086\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u0082\\u00D1\\u0080\\u00D1\\u0082\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00B4\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00BC\\u00D1\\u008B\\u00D1\\u0085\\u00D1\\u0080\\u00D1\\u008B\\u00D0\\u00BD\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u009D\\u00D0\\u00BE\\u00D0\\u00B2\\u00D1\\u008B\\u00D0\\u00B9\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B0\\u00D1\\u0084\\u00D0\\u00B8\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00BC\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0080\\u00D1\\u0082\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BA\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0088\\u00D0\\u00B8\\u00D1\\u0085\\u00D0\\u00BC\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u0083\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u008E\\u00D1\\u0082\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B4\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u0083\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BD\\u00D1\\u0086\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u0090\\u00D1\\u0080\\u00D1\\u0085\\u00D0\\u00B8\\u00D0\\u00B2\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00AF\\u00D9\\u0089\\u00D8\\u00A5\\u00D8\\u00B1\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0085\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A8\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00AC\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u0088\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B5\\u00D9\\u0088\\u00D8\\u00B1\\u00D8\\u00AC\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00AF\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00B6\\u00D9\\u0088\\u00D8\\u00A5\\u00D8\\u00B6\\u00D8\\u00A7\\u00D9\\u0081\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0082\\u00D8\\u00B3\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00AA\\u00D8\\u00AD\\u00D9\\u0085\\u00D9\\u008A\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0084\\u00D9\\u0081\\u00D8\\u00A7\\u00D8\\u00AA\\u00D9\\u0085\\u00D9\\u0084\\u00D8\\u00AA\\u00D9\\u0082\\u00D9\\u0089\\u00D8\\u00AA\\u00D8\\u00B9\\u00D8\\u00AF\\u00D9\\u008A\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B4\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00A3\\u00D8\\u00AE\\u00D8\\u00A8\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00AA\\u00D8\\u00B7\\u00D9\\u0088\\u00D9\\u008A\\u00D8\\u00B1\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u0083\\u00D9\\u0085\\u00D8\\u00A5\\u00D8\\u00B1\\u00D9\\u0081\\u00D8\\u00A7\\u00D9\\u0082\\u00D8\\u00B7\\u00D9\\u0084\\u00D8\\u00A8\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0084\\u00D8\\u00BA\\u00D8\\u00A9\\u00D8\\u00AA\\u00D8\\u00B1\\u00D8\\u00AA\\u00D9\\u008A\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B4\\u00D9\\u008A\\u00D8\\u00AE\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0082\\u00D8\\u00B5\\u00D8\\u00B5\\u00D8\\u00A7\\u00D9\\u0081\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00AD\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00AB\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0084\\u00D9\\u0087\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D9\\u0085\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A8\\u00D8\\u00A9\\u00D9\\u008A\\u00D9\\u0085\\u00D9\\u0083\\u00D9\\u0086\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B7\\u00D9\\u0081\\u00D9\\u0084\\u00D9\\u0081\\u00D9\\u008A\\u00D8\\u00AF\\u00D9\\u008A\\u00D9\\u0088\\u00D8\\u00A5\\u00D8\\u00AF\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00A9\\u00D8\\u00AA\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u008A\\u00D8\\u00AE\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B5\\u00D8\\u00AD\\u00D8\\u00A9\\u00D8\\u00AA\\u00D8\\u00B3\\u00D8\\u00AC\\u00D9\\u008A\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0088\\u00D9\\u0082\\u00D8\\u00AA\\u00D8\\u00B9\\u00D9\\u0086\\u00D8\\u00AF\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00AF\\u00D9\\u008A\\u00D9\\u0086\\u00D8\\u00A9\\u00D8\\u00AA\\u00D8\\u00B5\\u00D9\\u0085\\u00D9\\u008A\\u00D9\\u0085\\u00D8\\u00A3\\u00D8\\u00B1\\u00D8\\u00B4\\u00D9\\u008A\\u00D9\\u0081\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B0\\u00D9\\u008A\\u00D9\\u0086\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00A8\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A8\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A9\\u00D8\\u00A3\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B3\\u00D9\\u0081\\u00D8\\u00B1\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D9\\u0083\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0089\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D9\\u0088\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B3\\u00D9\\u0086\\u00D8\\u00A9\\u00D8\\u00AC\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00B9\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B5\\u00D8\\u00AD\\u00D9\\u0081\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D9\\u008A\\u00D9\\u0086\\u00D9\\u0083\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AE\\u00D8\\u00A7\\u00D8\\u00B5\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0084\\u00D9\\u0081\\u00D8\\u00A3\\u00D8\\u00B9\\u00D8\\u00B6\\u00D8\\u00A7\\u00D8\\u00A1\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AE\\u00D9\\u008A\\u00D8\\u00B1\\u00D8\\u00B1\\u00D8\\u00B3\\u00D8\\u00A7\\u00D8\\u00A6\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0082\\u00D9\\u0084\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D8\\u00AF\\u00D8\\u00A8\\u00D9\\u0085\\u00D9\\u0082\\u00D8\\u00A7\\u00D8\\u00B7\\u00D8\\u00B9\\u00D9\\u0085\\u00D8\\u00B1\\u00D8\\u00A7\\u00D8\\u00B3\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00B7\\u00D9\\u0082\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00AC\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00B4\\u00D8\\u00AA\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0082\\u00D8\\u00AF\\u00D9\\u0085\\u00D9\\u008A\\u00D8\\u00B9\\u00D8\\u00B7\\u00D9\\u008A\\u00D9\\u0083sByTagName(.jpg\\\" alt=\\\"1px solid #.gif\\\" alt=\\\"transparentinformationapplication\\\" onclick=\\\"establishedadvertising.png\\\" alt=\\\"environmentperformanceappropriate&amp;mdash;immediately</strong></rather thantemperaturedevelopmentcompetitionplaceholdervisibility:copyright\\\">0\\\" height=\\\"even thoughreplacementdestinationCorporation<ul class=\\\"AssociationindividualsperspectivesetTimeout(url(http://mathematicsmargin-top:eventually description) no-repeatcollections.JPG|thumb|participate/head><bodyfloat:left;<li class=\\\"hundreds of\\n\\nHowever, compositionclear:both;cooperationwithin the label for=\\\"border-top:New Zealandrecommendedphotographyinteresting&lt;sup&gt;controversyNetherlandsalternativemaxlength=\\\"switzerlandDevelopmentessentially\\n\\nAlthough </textarea>thunderbirdrepresented&amp;ndash;speculationcommunitieslegislationelectronics\\n\\t<div id=\\\"illustratedengineeringterritoriesauthoritiesdistributed6\\\" height=\\\"sans-serif;capable of disappearedinteractivelooking forit would beAfghanistanwas createdMath.floor(surroundingcan also beobservationmaintenanceencountered<h2 class=\\\"more recentit has beeninvasion of).getTime()fundamentalDespite the\\\"><div id=\\\"inspirationexaminationpreparationexplanation<input id=\\\"</a></span>versions ofinstrumentsbefore the  = 'http://Descriptionrelatively .substring(each of theexperimentsinfluentialintegrationmany peopledue to the combinationdo not haveMiddle East<noscript><copyright\\\" perhaps theinstitutionin Decemberarrangementmost famouspersonalitycreation oflimitationsexclusivelysovereignty-content\\\">\\n<td class=\\\"undergroundparallel todoctrine ofoccupied byterminologyRenaissancea number ofsupport forexplorationrecognitionpredecessor<img src=\\\"/<h1 class=\\\"publicationmay also bespecialized</fieldset>progressivemillions ofstates thatenforcementaround the one another.parentNodeagricultureAlternativeresearcherstowards theMost of themany other (especially<td width=\\\";width:100%independent<h3 class=\\\" onchange=\\\").addClass(interactionOne of the daughter ofaccessoriesbranches of\\r\\n<div id=\\\"the largestdeclarationregulationsInformationtranslationdocumentaryin order to\\\">\\n<head>\\n<\\\" height=\\\"1across the orientation);</script>implementedcan be seenthere was ademonstratecontainer\\\">connectionsthe Britishwas written!important;px; margin-followed byability to complicatedduring the immigrationalso called<h4 class=\\\"distinctionreplaced bygovernmentslocation ofin Novemberwhether the</p>\\n</div>acquisitioncalled the persecutiondesignation{font-size:appeared ininvestigateexperiencedmost likelywidely useddiscussionspresence of (document.extensivelyIt has beenit does notcontrary toinhabitantsimprovementscholarshipconsumptioninstructionfor exampleone or morepx; paddingthe currenta series ofare usuallyrole in thepreviously derivativesevidence ofexperiencescolorschemestated thatcertificate</a></div>\\n selected=\\\"high schoolresponse tocomfortableadoption ofthree yearsthe countryin Februaryso that thepeople who provided by<param nameaffected byin terms ofappointmentISO-8859-1\\\"was born inhistorical regarded asmeasurementis based on and other : function(significantcelebrationtransmitted/js/jquery.is known astheoretical tabindex=\\\"it could be<noscript>\\nhaving been\\r\\n<head>\\r\\n< &quot;The compilationhe had beenproduced byphilosopherconstructedintended toamong othercompared toto say thatEngineeringa differentreferred todifferencesbelief thatphotographsidentifyingHistory of Republic ofnecessarilyprobabilitytechnicallyleaving thespectacularfraction ofelectricityhead of therestaurantspartnershipemphasis onmost recentshare with saying thatfilled withdesigned toit is often\\\"></iframe>as follows:merged withthrough thecommercial pointed outopportunityview of therequirementdivision ofprogramminghe receivedsetInterval\\\"></span></in New Yorkadditional compression\\n\\n<div id=\\\"incorporate;</script><attachEventbecame the \\\" target=\\\"_carried outSome of thescience andthe time ofContainer\\\">maintainingChristopherMuch of thewritings of\\\" height=\\\"2size of theversion of mixture of between theExamples ofeducationalcompetitive onsubmit=\\\"director ofdistinctive/DTD XHTML relating totendency toprovince ofwhich woulddespite thescientific legislature.innerHTML allegationsAgriculturewas used inapproach tointelligentyears later,sans-serifdeterminingPerformanceappearances, which is foundationsabbreviatedhigher thans from the individual composed ofsupposed toclaims thatattributionfont-size:1elements ofHistorical his brotherat the timeanniversarygoverned byrelated to ultimately innovationsit is stillcan only bedefinitionstoGMTStringA number ofimg class=\\\"Eventually,was changedoccurred inneighboringdistinguishwhen he wasintroducingterrestrialMany of theargues thatan Americanconquest ofwidespread were killedscreen and In order toexpected todescendantsare locatedlegislativegenerations backgroundmost peopleyears afterthere is nothe highestfrequently they do notargued thatshowed thatpredominanttheologicalby the timeconsideringshort-lived</span></a>can be usedvery littleone of the had alreadyinterpretedcommunicatefeatures ofgovernment,</noscript>entered the\\\" height=\\\"3Independentpopulationslarge-scale. Although used in thedestructionpossibilitystarting intwo or moreexpressionssubordinatelarger thanhistory and</option>\\r\\nContinentaleliminatingwill not bepractice ofin front ofsite of theensure thatto create amississippipotentiallyoutstandingbetter thanwhat is nowsituated inmeta name=\\\"TraditionalsuggestionsTranslationthe form ofatmosphericideologicalenterprisescalculatingeast of theremnants ofpluginspage/index.php?remained intransformedHe was alsowas alreadystatisticalin favor ofMinistry ofmovement offormulationis required<link rel=\\\"This is the <a href=\\\"/popularizedinvolved inare used toand severalmade by theseems to belikely thatPalestiniannamed afterit had beenmost commonto refer tobut this isconsecutivetemporarilyIn general,conventionstakes placesubdivisionterritorialoperationalpermanentlywas largelyoutbreak ofin the pastfollowing a xmlns:og=\\\"><a class=\\\"class=\\\"textConversion may be usedmanufactureafter beingclearfix\\\">\\nquestion ofwas electedto become abecause of some peopleinspired bysuccessful a time whenmore commonamongst thean officialwidth:100%;technology,was adoptedto keep thesettlementslive birthsindex.html\\\"Connecticutassigned to&amp;times;account foralign=rightthe companyalways beenreturned toinvolvementBecause thethis period\\\" name=\\\"q\\\" confined toa result ofvalue=\\\"\\\" />is actuallyEnvironment\\r\\n</head>\\r\\nConversely,>\\n<div id=\\\"0\\\" width=\\\"1is probablyhave becomecontrollingthe problemcitizens ofpoliticiansreached theas early as:none; over<table cellvalidity ofdirectly toonmousedownwhere it iswhen it wasmembers of relation toaccommodatealong with In the latethe Englishdelicious\\\">this is notthe presentif they areand finallya matter of\\r\\n\\t</div>\\r\\n\\r\\n</script>faster thanmajority ofafter whichcomparativeto maintainimprove theawarded theer\\\" class=\\\"frameborderrestorationin the sameanalysis oftheir firstDuring the continentalsequence offunction(){font-size: work on the</script>\\n<begins withjavascript:constituentwas foundedequilibriumassume thatis given byneeds to becoordinatesthe variousare part ofonly in thesections ofis a commontheories ofdiscoveriesassociationedge of thestrength ofposition inpresent-dayuniversallyto form thebut insteadcorporationattached tois commonlyreasons for &quot;the can be madewas able towhich meansbut did notonMouseOveras possibleoperated bycoming fromthe primaryaddition offor severaltransferreda period ofare able tohowever, itshould havemuch larger\\n\\t</script>adopted theproperty ofdirected byeffectivelywas broughtchildren ofProgramminglonger thanmanuscriptswar againstby means ofand most ofsimilar to proprietaryoriginatingprestigiousgrammaticalexperience.to make theIt was alsois found incompetitorsin the U.S.replace thebrought thecalculationfall of thethe generalpracticallyin honor ofreleased inresidentialand some ofking of thereaction to1st Earl ofculture andprincipally</title>\\n  they can beback to thesome of hisexposure toare similarform of theaddFavoritecitizenshippart in thepeople within practiceto continue&amp;minus;approved by the first allowed theand for thefunctioningplaying thesolution toheight=\\\"0\\\" in his bookmore than afollows thecreated thepresence in&nbsp;</td>nationalistthe idea ofa characterwere forced class=\\\"btndays of thefeatured inshowing theinterest inin place ofturn of thethe head ofLord of thepoliticallyhas its ownEducationalapproval ofsome of theeach other,behavior ofand becauseand anotherappeared onrecorded inblack&quot;may includethe world'scan lead torefers to aborder=\\\"0\\\" government winning theresulted in while the Washington,the subjectcity in the></div>\\r\\n\\t\\treflect theto completebecame moreradioactiverejected bywithout anyhis father,which couldcopy of theto indicatea politicalaccounts ofconstitutesworked wither</a></li>of his lifeaccompaniedclientWidthprevent theLegislativedifferentlytogether inhas severalfor anothertext of thefounded thee with the is used forchanged theusually theplace wherewhereas the> <a href=\\\"\\\"><a href=\\\"themselves,although hethat can betraditionalrole of theas a resultremoveChilddesigned bywest of theSome peopleproduction,side of thenewslettersused by thedown to theaccepted bylive in theattempts tooutside thefrequenciesHowever, inprogrammersat least inapproximatealthough itwas part ofand variousGovernor ofthe articleturned into><a href=\\\"/the economyis the mostmost widelywould laterand perhapsrise to theoccurs whenunder whichconditions.the westerntheory thatis producedthe city ofin which heseen in thethe centralbuilding ofmany of hisarea of theis the onlymost of themany of thethe WesternThere is noextended toStatisticalcolspan=2 |short storypossible totopologicalcritical ofreported toa Christiandecision tois equal toproblems ofThis can bemerchandisefor most ofno evidenceeditions ofelements in&quot;. Thecom/images/which makesthe processremains theliterature,is a memberthe popularthe ancientproblems intime of thedefeated bybody of thea few yearsmuch of thethe work ofCalifornia,served as agovernment.concepts ofmovement in\\t\\t<div id=\\\"it\\\" value=\\\"language ofas they areproduced inis that theexplain thediv></div>\\nHowever thelead to the\\t<a href=\\\"/was grantedpeople havecontinuallywas seen asand relatedthe role ofproposed byof the besteach other.Constantinepeople fromdialects ofto revisionwas renameda source ofthe initiallaunched inprovide theto the westwhere thereand similarbetween twois also theEnglish andconditions,that it wasentitled tothemselves.quantity ofransparencythe same asto join thecountry andthis is theThis led toa statementcontrast tolastIndexOfthrough hisis designedthe term isis providedprotect theng</a></li>The currentthe site ofsubstantialexperience,in the Westthey shouldsloven\\u00C4\\u008Dinacomentariosuniversidadcondicionesactividadesexperienciatecnolog\\u00C3\\u00ADaproducci\\u00C3\\u00B3npuntuaci\\u00C3\\u00B3naplicaci\\u00C3\\u00B3ncontrase\\u00C3\\u00B1acategor\\u00C3\\u00ADasregistrarseprofesionaltratamientoreg\\u00C3\\u00ADstratesecretar\\u00C3\\u00ADaprincipalesprotecci\\u00C3\\u00B3nimportantesimportanciaposibilidadinteresantecrecimientonecesidadessuscribirseasociaci\\u00C3\\u00B3ndisponiblesevaluaci\\u00C3\\u00B3nestudiantesresponsableresoluci\\u00C3\\u00B3nguadalajararegistradosoportunidadcomercialesfotograf\\u00C3\\u00ADaautoridadesingenier\\u00C3\\u00ADatelevisi\\u00C3\\u00B3ncompetenciaoperacionesestablecidosimplementeactualmentenavegaci\\u00C3\\u00B3nconformidadline-height:font-family:\\\" : \\\"http://applicationslink\\\" href=\\\"specifically//<![CDATA[\\nOrganizationdistribution0px; height:relationshipdevice-width<div class=\\\"<label for=\\\"registration</noscript>\\n/index.html\\\"window.open( !important;application/independence//www.googleorganizationautocompleterequirementsconservative<form name=\\\"intellectualmargin-left:18th centuryan importantinstitutionsabbreviation<img class=\\\"organisationcivilization19th centuryarchitectureincorporated20th century-container\\\">most notably/></a></div>notification'undefined')Furthermore,believe thatinnerHTML = prior to thedramaticallyreferring tonegotiationsheadquartersSouth AfricaunsuccessfulPennsylvaniaAs a result,<html lang=\\\"&lt;/sup&gt;dealing withphiladelphiahistorically);</script>\\npadding-top:experimentalgetAttributeinstructionstechnologiespart of the =function(){subscriptionl.dtd\\\">\\r\\n<htgeographicalConstitution', function(supported byagriculturalconstructionpublicationsfont-size: 1a variety of<div style=\\\"Encyclopediaiframe src=\\\"demonstratedaccomplisheduniversitiesDemographics);</script><dedicated toknowledge ofsatisfactionparticularly</div></div>English (US)appendChild(transmissions. However, intelligence\\\" tabindex=\\\"float:right;Commonwealthranging fromin which theat least onereproductionencyclopedia;font-size:1jurisdictionat that time\\\"><a class=\\\"In addition,description+conversationcontact withis generallyr\\\" content=\\\"representing&lt;math&gt;presentationoccasionally<img width=\\\"navigation\\\">compensationchampionshipmedia=\\\"all\\\" violation ofreference toreturn true;Strict//EN\\\" transactionsinterventionverificationInformation difficultiesChampionshipcapabilities<![endif]-->}\\n</script>\\nChristianityfor example,Professionalrestrictionssuggest thatwas released(such as theremoveClass(unemploymentthe Americanstructure of/index.html published inspan class=\\\"\\\"><a href=\\\"/introductionbelonging toclaimed thatconsequences<meta name=\\\"Guide to theoverwhelmingagainst the concentrated,\\n.nontouch observations</a>\\n</div>\\nf (document.border: 1px {font-size:1treatment of0\\\" height=\\\"1modificationIndependencedivided intogreater thanachievementsestablishingJavaScript\\\" neverthelesssignificanceBroadcasting>&nbsp;</td>container\\\">\\nsuch as the influence ofa particularsrc='http://navigation\\\" half of the substantial &nbsp;</div>advantage ofdiscovery offundamental metropolitanthe opposite\\\" xml:lang=\\\"deliberatelyalign=centerevolution ofpreservationimprovementsbeginning inJesus ChristPublicationsdisagreementtext-align:r, function()similaritiesbody></html>is currentlyalphabeticalis sometimestype=\\\"image/many of the flow:hidden;available indescribe theexistence ofall over thethe Internet\\t<ul class=\\\"installationneighborhoodarmed forcesreducing thecontinues toNonetheless,temperatures\\n\\t\\t<a href=\\\"close to theexamples of is about the(see below).\\\" id=\\\"searchprofessionalis availablethe official\\t\\t</script>\\n\\n\\t\\t<div id=\\\"accelerationthrough the Hall of Famedescriptionstranslationsinterference type='text/recent yearsin the worldvery popular{background:traditional some of the connected toexploitationemergence ofconstitutionA History ofsignificant manufacturedexpectations><noscript><can be foundbecause the has not beenneighbouringwithout the added to the\\t<li class=\\\"instrumentalSoviet Unionacknowledgedwhich can bename for theattention toattempts to developmentsIn fact, the<li class=\\\"aimplicationssuitable formuch of the colonizationpresidentialcancelBubble Informationmost of the is describedrest of the more or lessin SeptemberIntelligencesrc=\\\"http://px; height: available tomanufacturerhuman rightslink href=\\\"/availabilityproportionaloutside the astronomicalhuman beingsname of the are found inare based onsmaller thana person whoexpansion ofarguing thatnow known asIn the earlyintermediatederived fromScandinavian</a></div>\\r\\nconsider thean estimatedthe National<div id=\\\"pagresulting incommissionedanalogous toare required/ul>\\n</div>\\nwas based onand became a&nbsp;&nbsp;t\\\" value=\\\"\\\" was capturedno more thanrespectivelycontinue to >\\r\\n<head>\\r\\n<were createdmore generalinformation used for theindependent the Imperialcomponent ofto the northinclude the Constructionside of the would not befor instanceinvention ofmore complexcollectivelybackground: text-align: its originalinto accountthis processan extensivehowever, thethey are notrejected thecriticism ofduring whichprobably thethis article(function(){It should bean agreementaccidentallydiffers fromArchitecturebetter knownarrangementsinfluence onattended theidentical tosouth of thepass throughxml\\\" title=\\\"weight:bold;creating thedisplay:nonereplaced the<img src=\\\"/ihttps://www.World War IItestimonialsfound in therequired to and that thebetween the was designedconsists of considerablypublished bythe languageConservationconsisted ofrefer to theback to the css\\\" media=\\\"People from available onproved to besuggestions\\\"was known asvarieties oflikely to becomprised ofsupport the hands of thecoupled withconnect and border:none;performancesbefore beinglater becamecalculationsoften calledresidents ofmeaning that><li class=\\\"evidence forexplanationsenvironments\\\"></a></div>which allowsIntroductiondeveloped bya wide rangeon behalf ofvalign=\\\"top\\\"principle ofat the time,</noscript>\\rsaid to havein the firstwhile othershypotheticalphilosopherspower of thecontained inperformed byinability towere writtenspan style=\\\"input name=\\\"the questionintended forrejection ofimplies thatinvented thethe standardwas probablylink betweenprofessor ofinteractionschanging theIndian Ocean class=\\\"lastworking with'http://www.years beforeThis was therecreationalentering themeasurementsan extremelyvalue of thestart of the\\n</script>\\n\\nan effort toincrease theto the southspacing=\\\"0\\\">sufficientlythe Europeanconverted toclearTimeoutdid not haveconsequentlyfor the nextextension ofeconomic andalthough theare producedand with theinsufficientgiven by thestating thatexpenditures</span></a>\\nthought thaton the basiscellpadding=image of thereturning toinformation,separated byassassinateds\\\" content=\\\"authority ofnorthwestern</div>\\n<div \\\"></div>\\r\\n  consultationcommunity ofthe nationalit should beparticipants align=\\\"leftthe greatestselection ofsupernaturaldependent onis mentionedallowing thewas inventedaccompanyinghis personalavailable atstudy of theon the otherexecution ofHuman Rightsterms of theassociationsresearch andsucceeded bydefeated theand from thebut they arecommander ofstate of theyears of agethe study of<ul class=\\\"splace in thewhere he was<li class=\\\"fthere are nowhich becamehe publishedexpressed into which thecommissionerfont-weight:territory ofextensions\\\">Roman Empireequal to theIn contrast,however, andis typicallyand his wife(also called><ul class=\\\"effectively evolved intoseem to havewhich is thethere was noan excellentall of thesedescribed byIn practice,broadcastingcharged withreflected insubjected tomilitary andto the pointeconomicallysetTargetingare actuallyvictory over();</script>continuouslyrequired forevolutionaryan effectivenorth of the, which was front of theor otherwisesome form ofhad not beengenerated byinformation.permitted toincludes thedevelopment,entered intothe previous\";\n\t\t\t}\n\t\t}\n\n\t\tprivate class DataHolder2\n\t\t{\n\t\t\tinternal static string GetData()\n\t\t\t{\n\t\t\t\treturn \"consistentlyare known asthe field ofthis type ofgiven to thethe title ofcontains theinstances ofin the northdue to theirare designedcorporationswas that theone of thesemore popularsucceeded insupport fromin differentdominated bydesigned forownership ofand possiblystandardizedresponseTextwas intendedreceived theassumed thatareas of theprimarily inthe basis ofin the senseaccounts fordestroyed byat least twowas declaredcould not beSecretary ofappear to bemargin-top:1/^\\\\s+|\\\\s+$/ge){throw e};the start oftwo separatelanguage andwho had beenoperation ofdeath of thereal numbers\\t<link rel=\\\"provided thethe story ofcompetitionsenglish (UK)english (US)\\u00D0\\u009C\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00A1\\u00D1\\u0080\\u00D0\\u00BF\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\u00D1\\u0081\\u00D1\\u0080\\u00D0\\u00BF\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\u00D1\\u0081\\u00D1\\u0080\\u00D0\\u00BF\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00BE\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00A8\\u00D9\\u008A\\u00D8\\u00A9\\u00E6\\u00AD\\u00A3\\u00E9\\u00AB\\u0094\\u00E4\\u00B8\\u00AD\\u00E6\\u0096\\u0087\\u00E7\\u00AE\\u0080\\u00E4\\u00BD\\u0093\\u00E4\\u00B8\\u00AD\\u00E6\\u0096\\u0087\\u00E7\\u00B9\\u0081\\u00E4\\u00BD\\u0093\\u00E4\\u00B8\\u00AD\\u00E6\\u0096\\u0087\\u00E6\\u009C\\u0089\\u00E9\\u0099\\u0090\\u00E5\\u0085\\u00AC\\u00E5\\u008F\\u00B8\\u00E4\\u00BA\\u00BA\\u00E6\\u00B0\\u0091\\u00E6\\u0094\\u00BF\\u00E5\\u00BA\\u009C\\u00E9\\u0098\\u00BF\\u00E9\\u0087\\u008C\\u00E5\\u00B7\\u00B4\\u00E5\\u00B7\\u00B4\\u00E7\\u00A4\\u00BE\\u00E4\\u00BC\\u009A\\u00E4\\u00B8\\u00BB\\u00E4\\u00B9\\u0089\\u00E6\\u0093\\u008D\\u00E4\\u00BD\\u009C\\u00E7\\u00B3\\u00BB\\u00E7\\u00BB\\u009F\\u00E6\\u0094\\u00BF\\u00E7\\u00AD\\u0096\\u00E6\\u00B3\\u0095\\u00E8\\u00A7\\u0084informaci\\u00C3\\u00B3nherramientaselectr\\u00C3\\u00B3nicodescripci\\u00C3\\u00B3nclasificadosconocimientopublicaci\\u00C3\\u00B3nrelacionadasinform\\u00C3\\u00A1ticarelacionadosdepartamentotrabajadoresdirectamenteayuntamientomercadoLibrecont\\u00C3\\u00A1ctenoshabitacionescumplimientorestaurantesdisposici\\u00C3\\u00B3nconsecuenciaelectr\\u00C3\\u00B3nicaaplicacionesdesconectadoinstalaci\\u00C3\\u00B3nrealizaci\\u00C3\\u00B3nutilizaci\\u00C3\\u00B3nenciclopediaenfermedadesinstrumentosexperienciasinstituci\\u00C3\\u00B3nparticularessubcategoria\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00A0\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0081\\u00D0\\u00B8\\u00D0\\u00B8\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B1\\u00D0\\u00BE\\u00D1\\u0082\\u00D1\\u008B\\u00D0\\u00B1\\u00D0\\u00BE\\u00D0\\u00BB\\u00D1\\u008C\\u00D1\\u0088\\u00D0\\u00B5\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B6\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00B4\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00B3\\u00D0\\u00B8\\u00D1\\u0085\\u00D1\\u0081\\u00D0\\u00BB\\u00D1\\u0083\\u00D1\\u0087\\u00D0\\u00B0\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B9\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00B2\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00A0\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0081\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u009C\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B2\\u00D0\\u00B5\\u00D0\\u00B4\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00B3\\u00D0\\u00B8\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00BD\\u00D1\\u008B\\u00D1\\u0085\\u00D0\\u00B4\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B6\\u00D0\\u00BD\\u00D1\\u008B\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u009C\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B2\\u00D1\\u008B\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00B1\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00B9\\u00D0\\u009C\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B2\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BD\\u00D1\\u008B\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B1\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00B4\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B6\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u0083\\u00D1\\u0081\\u00D0\\u00BB\\u00D1\\u0083\\u00D0\\u00B3\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BF\\u00D0\\u00B5\\u00D1\\u0080\\u00D1\\u008C\\u00D0\\u009E\\u00D0\\u00B4\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u0083\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B1\\u00D0\\u00BE\\u00D1\\u0082\\u00D1\\u0083\\u00D0\\u00B0\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00BB\\u00D1\\u008F\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u0089\\u00D0\\u00B5\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00B8\\u00D0\\u00B4\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00B9\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0085\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D1\\u0088\\u00D0\\u00BE\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00B2\\u00D1\\u0081\\u00D1\\u0081\\u00D1\\u008B\\u00D0\\u00BB\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00B6\\u00D0\\u00B4\\u00D1\\u008B\\u00D0\\u00B9\\u00D0\\u00B2\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00B3\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00BF\\u00D0\\u00BF\\u00D1\\u008B\\u00D0\\u00B2\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B1\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00B0\\u00D0\\u00BB\\u00D0\\u00BF\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B2\\u00D1\\u008B\\u00D0\\u00B9\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u008C\\u00D0\\u00B3\\u00D0\\u00B8\\u00D0\\u00BF\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B1\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00BD\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u0082\\u00D0\\u00BA\\u00D1\\u0083\\u00D0\\u00BF\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00B4\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B6\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0085\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0087\\u00D0\\u00B0\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00A0\\u00D0\\u00B0\\u00D0\\u00B1\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00A2\\u00D0\\u00BE\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00B2\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00B2\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0087\\u00D0\\u00B0\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00BF\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00BA\\u00D1\\u0081\\u00D0\\u00BB\\u00D1\\u0083\\u00D0\\u00B6\\u00D0\\u00B1\\u00D1\\u008B\\u00D1\\u0081\\u00D0\\u00B8\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BF\\u00D0\\u00B5\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BE\\u00D1\\u0089\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00B9\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u0083\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BE\\u00D1\\u0089\\u00D1\\u008C\\u00D0\\u00B4\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B6\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0081\\u00D1\\u008B\\u00D0\\u00BB\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00B1\\u00D1\\u008B\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00BD\\u00D1\\u008B\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00B8\\u00D0\\u00B5\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B5\\u00D0\\u00BA\\u00D1\\u0082\\u00D0\\u00A1\\u00D0\\u00B5\\u00D0\\u00B9\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00B0\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00BB\\u00D0\\u00B0\\u00D0\\u00B9\\u00D0\\u00BD\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00B2\\u00D0\\u00B5\\u00D1\\u0080\\u00D1\\u0081\\u00D0\\u00B8\\u00D1\\u008F\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B5\\u00D1\\u0084\\u00D0\\u00B8\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00BC\\u00D1\\u008B\\u00D1\\u0083\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BD\\u00D1\\u008F\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00BD\\u00D1\\u008B\\u00D1\\u0085\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BB\\u00D1\\u008E\\u00D1\\u008F\\u00D0\\u00BD\\u00D0\\u00B2\\u00D0\\u00B0\\u00D1\\u0080\\u00D1\\u008F\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D1\\u008C\\u00D1\\u0088\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00B8\\u00D1\\u0085\\u00D0\\u00B4\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00B7\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0087\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00B7\\u00D1\\u008F\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0080\\u00D1\\u0083\\u00D0\\u00BC\\u00D0\\u00B0\\u00D0\\u00A2\\u00D0\\u00B5\\u00D0\\u00BF\\u00D0\\u00B5\\u00D1\\u0080\\u00D1\\u008C\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u008F\\u00D1\\u0086\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00B0\\u00D1\\u0089\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u008B\\u00D0\\u009B\\u00D1\\u0083\\u00D1\\u0087\\u00D1\\u0088\\u00D0\\u00B8\\u00D0\\u00B5\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0081\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B6\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0098\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A7\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u009D\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A3\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BC\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u00A0\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0098\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u009A\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BC\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0098\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00B6\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BC\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BC\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AB\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BC\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008C\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00D8\\u00AA\\u00D8\\u00B3\\u00D8\\u00AA\\u00D8\\u00B7\\u00D9\\u008A\\u00D8\\u00B9\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A9\\u00D8\\u00A8\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00B3\\u00D8\\u00B7\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B5\\u00D9\\u0081\\u00D8\\u00AD\\u00D8\\u00A9\\u00D9\\u0085\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00B6\\u00D9\\u008A\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AE\\u00D8\\u00A7\\u00D8\\u00B5\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B2\\u00D9\\u008A\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00AF\\u00D9\\u0088\\u00D8\\u00AF\\u00D8\\u00A8\\u00D8\\u00B1\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00AC\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D9\\u0088\\u00D9\\u0084\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0088\\u00D9\\u0082\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00A8\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B3\\u00D8\\u00B1\\u00D9\\u008A\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AC\\u00D9\\u0088\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B0\\u00D9\\u0087\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AD\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AD\\u00D9\\u0082\\u00D9\\u0088\\u00D9\\u0082\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D8\\u00B1\\u00D9\\u008A\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0082\\u00D9\\u0085\\u00D8\\u00AD\\u00D9\\u0081\\u00D9\\u0088\\u00D8\\u00B8\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AB\\u00D8\\u00A7\\u00D9\\u0086\\u00D9\\u008A\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D9\\u0087\\u00D8\\u00AF\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B1\\u00D8\\u00A3\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0082\\u00D8\\u00B1\\u00D8\\u00A2\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B4\\u00D8\\u00A8\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AD\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AC\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D8\\u00B3\\u00D8\\u00B1\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u0088\\u00D9\\u0085\\u00D9\\u0085\\u00D8\\u00AC\\u00D9\\u0085\\u00D9\\u0088\\u00D8\\u00B9\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00AD\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0086\\u00D9\\u0082\\u00D8\\u00A7\\u00D8\\u00B7\\u00D9\\u0081\\u00D9\\u0084\\u00D8\\u00B3\\u00D8\\u00B7\\u00D9\\u008A\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0088\\u00D9\\u008A\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D9\\u0086\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A7\\u00D8\\u00AA\\u00D9\\u0087\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00B6\\u00D8\\u00AA\\u00D8\\u00AD\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AA\\u00D9\\u008A\\u00D8\\u00A8\\u00D8\\u00AA\\u00D9\\u0088\\u00D9\\u0082\\u00D9\\u008A\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D9\\u0088\\u00D9\\u0084\\u00D9\\u0089\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A8\\u00D8\\u00B1\\u00D9\\u008A\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00B7\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B4\\u00D8\\u00AE\\u00D8\\u00B5\\u00D9\\u008A\\u00D8\\u00B3\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AB\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AB\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B5\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AD\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00AB\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B2\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AE\\u00D9\\u0084\\u00D9\\u008A\\u00D8\\u00AC\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AC\\u00D9\\u0085\\u00D9\\u008A\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0085\\u00D9\\u0087\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AC\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B3\\u00D8\\u00A7\\u00D8\\u00B9\\u00D8\\u00A9\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D9\\u0087\\u00D8\\u00AF\\u00D9\\u0087\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00A6\\u00D9\\u008A\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D8\\u00AE\\u00D9\\u0088\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0081\\u00D9\\u0086\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D8\\u00AA\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D9\\u0088\\u00D8\\u00B1\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D8\\u00B1\\u00D9\\u0088\\u00D8\\u00B3\\u00D8\\u00A7\\u00D8\\u00B3\\u00D8\\u00AA\\u00D8\\u00BA\\u00D8\\u00B1\\u00D9\\u0082\\u00D8\\u00AA\\u00D8\\u00B5\\u00D8\\u00A7\\u00D9\\u0085\\u00D9\\u008A\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A8\\u00D9\\u0086\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00B8\\u00D9\\u008A\\u00D9\\u0085entertainmentunderstanding = function().jpg\\\" width=\\\"configuration.png\\\" width=\\\"<body class=\\\"Math.random()contemporary United Statescircumstances.appendChild(organizations<span class=\\\"\\\"><img src=\\\"/distinguishedthousands of communicationclear\\\"></div>investigationfavicon.ico\\\" margin-right:based on the Massachusettstable border=internationalalso known aspronunciationbackground:#fpadding-left:For example, miscellaneous&lt;/math&gt;psychologicalin particularearch\\\" type=\\\"form method=\\\"as opposed toSupreme Courtoccasionally Additionally,North Americapx;backgroundopportunitiesEntertainment.toLowerCase(manufacturingprofessional combined withFor instance,consisting of\\\" maxlength=\\\"return false;consciousnessMediterraneanextraordinaryassassinationsubsequently button type=\\\"the number ofthe original comprehensiverefers to the</ul>\\n</div>\\nphilosophicallocation.hrefwas publishedSan Francisco(function(){\\n<div id=\\\"mainsophisticatedmathematical /head>\\r\\n<bodysuggests thatdocumentationconcentrationrelationshipsmay have been(for example,This article in some casesparts of the definition ofGreat Britain cellpadding=equivalent toplaceholder=\\\"; font-size: justificationbelieved thatsuffered fromattempted to leader of thecript\\\" src=\\\"/(function() {are available\\n\\t<link rel=\\\" src='http://interested inconventional \\\" alt=\\\"\\\" /></are generallyhas also beenmost popular correspondingcredited withtyle=\\\"border:</a></span></.gif\\\" width=\\\"<iframe src=\\\"table class=\\\"inline-block;according to together withapproximatelyparliamentarymore and moredisplay:none;traditionallypredominantly&nbsp;|&nbsp;&nbsp;</span> cellspacing=<input name=\\\"or\\\" content=\\\"controversialproperty=\\\"og:/x-shockwave-demonstrationsurrounded byNevertheless,was the firstconsiderable Although the collaborationshould not beproportion of<span style=\\\"known as the shortly afterfor instance,described as /head>\\n<body starting withincreasingly the fact thatdiscussion ofmiddle of thean individualdifficult to point of viewhomosexualityacceptance of</span></div>manufacturersorigin of thecommonly usedimportance ofdenominationsbackground: #length of thedeterminationa significant\\\" border=\\\"0\\\">revolutionaryprinciples ofis consideredwas developedIndo-Europeanvulnerable toproponents ofare sometimescloser to theNew York City name=\\\"searchattributed tocourse of themathematicianby the end ofat the end of\\\" border=\\\"0\\\" technological.removeClass(branch of theevidence that![endif]-->\\r\\nInstitute of into a singlerespectively.and thereforeproperties ofis located insome of whichThere is alsocontinued to appearance of &amp;ndash; describes theconsiderationauthor of theindependentlyequipped withdoes not have</a><a href=\\\"confused with<link href=\\\"/at the age ofappear in theThese includeregardless ofcould be used style=&quot;several timesrepresent thebody>\\n</html>thought to bepopulation ofpossibilitiespercentage ofaccess to thean attempt toproduction ofjquery/jquerytwo differentbelong to theestablishmentreplacing thedescription\\\" determine theavailable forAccording to wide range of\\t<div class=\\\"more commonlyorganisationsfunctionalitywas completed &amp;mdash; participationthe characteran additionalappears to befact that thean example ofsignificantlyonmouseover=\\\"because they async = true;problems withseems to havethe result of src=\\\"http://familiar withpossession offunction () {took place inand sometimessubstantially<span></span>is often usedin an attemptgreat deal ofEnvironmentalsuccessfully virtually all20th century,professionalsnecessary to determined bycompatibilitybecause it isDictionary ofmodificationsThe followingmay refer to:Consequently,Internationalalthough somethat would beworld's firstclassified asbottom of the(particularlyalign=\\\"left\\\" most commonlybasis for thefoundation ofcontributionspopularity ofcenter of theto reduce thejurisdictionsapproximation onmouseout=\\\"New Testamentcollection of</span></a></in the Unitedfilm director-strict.dtd\\\">has been usedreturn to thealthough thischange in theseveral otherbut there areunprecedentedis similar toespecially inweight: bold;is called thecomputationalindicate thatrestricted to\\t<meta name=\\\"are typicallyconflict withHowever, the An example ofcompared withquantities ofrather than aconstellationnecessary forreported thatspecificationpolitical and&nbsp;&nbsp;<references tothe same yearGovernment ofgeneration ofhave not beenseveral yearscommitment to\\t\\t<ul class=\\\"visualization19th century,practitionersthat he wouldand continuedoccupation ofis defined ascentre of thethe amount of><div style=\\\"equivalent ofdifferentiatebrought aboutmargin-left: automaticallythought of asSome of these\\n<div class=\\\"input class=\\\"replaced withis one of theeducation andinfluenced byreputation as\\n<meta name=\\\"accommodation</div>\\n</div>large part ofInstitute forthe so-called against the In this case,was appointedclaimed to beHowever, thisDepartment ofthe remainingeffect on theparticularly deal with the\\n<div style=\\\"almost alwaysare currentlyexpression ofphilosophy offor more thancivilizationson the islandselectedIndexcan result in\\\" value=\\\"\\\" />the structure /></a></div>Many of thesecaused by theof the Unitedspan class=\\\"mcan be tracedis related tobecame one ofis frequentlyliving in thetheoreticallyFollowing theRevolutionarygovernment inis determinedthe politicalintroduced insufficient todescription\\\">short storiesseparation ofas to whetherknown for itswas initiallydisplay:blockis an examplethe principalconsists of arecognized as/body></html>a substantialreconstructedhead of stateresistance toundergraduateThere are twogravitationalare describedintentionallyserved as theclass=\\\"headeropposition tofundamentallydominated theand the otheralliance withwas forced torespectively,and politicalin support ofpeople in the20th century.and publishedloadChartbeatto understandmember statesenvironmentalfirst half ofcountries andarchitecturalbe consideredcharacterizedclearIntervalauthoritativeFederation ofwas succeededand there area consequencethe Presidentalso includedfree softwaresuccession ofdeveloped thewas destroyedaway from the;\\n</script>\\n<although theyfollowed by amore powerfulresulted in aUniversity ofHowever, manythe presidentHowever, someis thought tountil the endwas announcedare importantalso includes><input type=the center of DO NOT ALTERused to referthemes/?sort=that had beenthe basis forhas developedin the summercomparativelydescribed thesuch as thosethe resultingis impossiblevarious otherSouth Africanhave the sameeffectivenessin which case; text-align:structure and; background:regarding thesupported theis also knownstyle=\\\"marginincluding thebahasa Melayunorsk bokm\\u00C3\\u00A5lnorsk nynorsksloven\\u00C5\\u00A1\\u00C4\\u008Dinainternacionalcalificaci\\u00C3\\u00B3ncomunicaci\\u00C3\\u00B3nconstrucci\\u00C3\\u00B3n\\\"><div class=\\\"disambiguationDomainName', 'administrationsimultaneouslytransportationInternational margin-bottom:responsibility<![endif]-->\\n</><meta name=\\\"implementationinfrastructurerepresentationborder-bottom:</head>\\n<body>=http%3A%2F%2F<form method=\\\"method=\\\"post\\\" /favicon.ico\\\" });\\n</script>\\n.setAttribute(Administration= new Array();<![endif]-->\\r\\ndisplay:block;Unfortunately,\\\">&nbsp;</div>/favicon.ico\\\">='stylesheet' identification, for example,<li><a href=\\\"/an alternativeas a result ofpt\\\"></script>\\ntype=\\\"submit\\\" \\n(function() {recommendationform action=\\\"/transformationreconstruction.style.display According to hidden\\\" name=\\\"along with thedocument.body.approximately Communicationspost\\\" action=\\\"meaning &quot;--<![endif]-->Prime Ministercharacteristic</a> <a class=the history of onmouseover=\\\"the governmenthref=\\\"https://was originallywas introducedclassificationrepresentativeare considered<![endif]-->\\n\\ndepends on theUniversity of in contrast to placeholder=\\\"in the case ofinternational constitutionalstyle=\\\"border-: function() {Because of the-strict.dtd\\\">\\n<table class=\\\"accompanied byaccount of the<script src=\\\"/nature of the the people in in addition tos); js.id = id\\\" width=\\\"100%\\\"regarding the Roman Catholican independentfollowing the .gif\\\" width=\\\"1the following discriminationarchaeologicalprime minister.js\\\"></script>combination of marginwidth=\\\"createElement(w.attachEvent(</a></td></tr>src=\\\"https://aIn particular, align=\\\"left\\\" Czech RepublicUnited Kingdomcorrespondenceconcluded that.html\\\" title=\\\"(function () {comes from theapplication of<span class=\\\"sbelieved to beement('script'</a>\\n</li>\\n<livery different><span class=\\\"option value=\\\"(also known as\\t<li><a href=\\\"><input name=\\\"separated fromreferred to as valign=\\\"top\\\">founder of theattempting to carbon dioxide\\n\\n<div class=\\\"class=\\\"search-/body>\\n</html>opportunity tocommunications</head>\\r\\n<body style=\\\"width:Ti\\u00E1\\u00BA\\u00BFng Vi\\u00E1\\u00BB\\u0087tchanges in theborder-color:#0\\\" border=\\\"0\\\" </span></div><was discovered\\\" type=\\\"text\\\" );\\n</script>\\n\\nDepartment of ecclesiasticalthere has beenresulting from</body></html>has never beenthe first timein response toautomatically </div>\\n\\n<div iwas consideredpercent of the\\\" /></a></div>collection of descended fromsection of theaccept-charsetto be confusedmember of the padding-right:translation ofinterpretation href='http://whether or notThere are alsothere are manya small numberother parts ofimpossible to  class=\\\"buttonlocated in the. However, theand eventuallyAt the end of because of itsrepresents the<form action=\\\" method=\\\"post\\\"it is possiblemore likely toan increase inhave also beencorresponds toannounced thatalign=\\\"right\\\">many countriesfor many yearsearliest knownbecause it waspt\\\"></script>\\r valign=\\\"top\\\" inhabitants offollowing year\\r\\n<div class=\\\"million peoplecontroversial concerning theargue that thegovernment anda reference totransferred todescribing the style=\\\"color:although therebest known forsubmit\\\" name=\\\"multiplicationmore than one recognition ofCouncil of theedition of the  <meta name=\\\"Entertainment away from the ;margin-right:at the time ofinvestigationsconnected withand many otheralthough it isbeginning with <span class=\\\"descendants of<span class=\\\"i align=\\\"right\\\"</head>\\n<body aspects of thehas since beenEuropean Unionreminiscent ofmore difficultVice Presidentcomposition ofpassed throughmore importantfont-size:11pxexplanation ofthe concept ofwritten in the\\t<span class=\\\"is one of the resemblance toon the groundswhich containsincluding the defined by thepublication ofmeans that theoutside of thesupport of the<input class=\\\"<span class=\\\"t(Math.random()most prominentdescription ofConstantinoplewere published<div class=\\\"seappears in the1\\\" height=\\\"1\\\" most importantwhich includeswhich had beendestruction ofthe population\\n\\t<div class=\\\"possibility ofsometimes usedappear to havesuccess of theintended to bepresent in thestyle=\\\"clear:b\\r\\n</script>\\r\\n<was founded ininterview with_id\\\" content=\\\"capital of the\\r\\n<link rel=\\\"srelease of thepoint out thatxMLHttpRequestand subsequentsecond largestvery importantspecificationssurface of theapplied to theforeign policy_setDomainNameestablished inis believed toIn addition tomeaning of theis named afterto protect theis representedDeclaration ofmore efficientClassificationother forms ofhe returned to<span class=\\\"cperformance of(function() {\\rif and only ifregions of theleading to therelations withUnited Nationsstyle=\\\"height:other than theype\\\" content=\\\"Association of\\n</head>\\n<bodylocated on theis referred to(including theconcentrationsthe individualamong the mostthan any other/>\\n<link rel=\\\" return false;the purpose ofthe ability to;color:#fff}\\n.\\n<span class=\\\"the subject ofdefinitions of>\\r\\n<link rel=\\\"claim that thehave developed<table width=\\\"celebration ofFollowing the to distinguish<span class=\\\"btakes place inunder the namenoted that the><![endif]-->\\nstyle=\\\"margin-instead of theintroduced thethe process ofincreasing thedifferences inestimated thatespecially the/div><div id=\\\"was eventuallythroughout histhe differencesomething thatspan></span></significantly ></script>\\r\\n\\r\\nenvironmental to prevent thehave been usedespecially forunderstand theis essentiallywere the firstis the largesthave been made\\\" src=\\\"http://interpreted assecond half ofcrolling=\\\"no\\\" is composed ofII, Holy Romanis expected tohave their owndefined as thetraditionally have differentare often usedto ensure thatagreement withcontaining theare frequentlyinformation onexample is theresulting in a</a></li></ul> class=\\\"footerand especiallytype=\\\"button\\\" </span></span>which included>\\n<meta name=\\\"considered thecarried out byHowever, it isbecame part ofin relation topopular in thethe capital ofwas officiallywhich has beenthe History ofalternative todifferent fromto support thesuggested thatin the process  <div class=\\\"the foundationbecause of hisconcerned withthe universityopposed to thethe context of<span class=\\\"ptext\\\" name=\\\"q\\\"\\t\\t<div class=\\\"the scientificrepresented bymathematicianselected by thethat have been><div class=\\\"cdiv id=\\\"headerin particular,converted into);\\n</script>\\n<philosophical srpskohrvatskiti\\u00E1\\u00BA\\u00BFng Vi\\u00E1\\u00BB\\u0087t\\u00D0\\u00A0\\u00D1\\u0083\\u00D1\\u0081\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00B9\\u00D1\\u0080\\u00D1\\u0083\\u00D1\\u0081\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00B9investigaci\\u00C3\\u00B3nparticipaci\\u00C3\\u00B3n\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D1\\u008B\\u00D0\\u00B5\\u00D0\\u00BE\\u00D0\\u00B1\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D1\\u008B\\u00D0\\u00B9\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B5\\u00D0\\u00BA\\u00D1\\u0081\\u00D0\\u00B8\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u008B\\u00D0\\u009D\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D1\\u008B\\u00D1\\u0085\\u00D0\\u00BE\\u00D0\\u00B1\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00B2\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B0\\u00D1\\u008F\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00BD\\u00D1\\u008F\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00A3\\u00D0\\u00BA\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u008B\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u008B\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B9\\u00D1\\u0081\\u00D0\\u00B4\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BE\\u00D1\\u0089\\u00D1\\u008C\\u00D1\\u008E\\u00D1\\u0081\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00B4\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00BD\\u00D1\\u008B\\u00D1\\u0083\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B5\\u00D0\\u0093\\u00D0\\u00BB\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u008F\\u00D0\\u00B8\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00B8\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0080\\u00D0\\u00B5\\u00D1\\u0088\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00A1\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0087\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u008D\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00BC\\u00D1\\u0083\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00B4\\u00D1\\u0083\\u00D0\\u00B5\\u00D1\\u0082\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u008C\\u00D1\\u0082\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B0\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BD\\u00D0\\u00B5\\u00D1\\u0087\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B5\\u00D1\\u0088\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B5\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B5\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B3\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00A0\\u00D0\\u00B5\\u00D0\\u00BA\\u00D0\\u00BB\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00B0\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00AF\\u00D9\\u0089\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0088\\u00D8\\u00B6\\u00D9\\u0088\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A8\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00AC\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0088\\u00D8\\u00A7\\u00D9\\u0082\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00B3\\u00D8\\u00A7\\u00D8\\u00A6\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D8\\u00B9\\u00D8\\u00B6\\u00D8\\u00A7\\u00D8\\u00A1\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00B6\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00B5\\u00D9\\u0085\\u00D9\\u008A\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00B9\\u00D8\\u00B6\\u00D8\\u00A7\\u00D8\\u00A1\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00A7\\u00D8\\u00A6\\u00D8\\u00AC\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00B3\\u00D8\\u00AC\\u00D9\\u008A\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D9\\u0082\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B6\\u00D8\\u00BA\\u00D8\\u00B7\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0081\\u00D9\\u008A\\u00D8\\u00AF\\u00D9\\u008A\\u00D9\\u0088\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00B1\\u00D8\\u00AD\\u00D9\\u008A\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AC\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00AF\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u008A\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D8\\u00AE\\u00D8\\u00A8\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0081\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D9\\u0081\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u008A\\u00D8\\u00AE\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D9\\u0082\\u00D9\\u0086\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AE\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00B7\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00AC\\u00D8\\u00AA\\u00D9\\u0085\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AF\\u00D9\\u008A\\u00D9\\u0083\\u00D9\\u0088\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B3\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AD\\u00D8\\u00A9\\u00D8\\u00B9\\u00D8\\u00A8\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0084\\u00D9\\u0087\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00B1\\u00D8\\u00A8\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00A8\\u00D8\\u00B7\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A3\\u00D8\\u00AF\\u00D8\\u00A8\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00AE\\u00D8\\u00A8\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00AA\\u00D8\\u00AD\\u00D8\\u00AF\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00BA\\u00D8\\u00A7\\u00D9\\u0086\\u00D9\\u008Acursor:pointer;</title>\\n<meta \\\" href=\\\"http://\\\"><span class=\\\"members of the window.locationvertical-align:/a> | <a href=\\\"<!doctype html>media=\\\"screen\\\" <option value=\\\"favicon.ico\\\" />\\n\\t\\t<div class=\\\"characteristics\\\" method=\\\"get\\\" /body>\\n</html>\\nshortcut icon\\\" document.write(padding-bottom:representativessubmit\\\" value=\\\"align=\\\"center\\\" throughout the science fiction\\n  <div class=\\\"submit\\\" class=\\\"one of the most valign=\\\"top\\\"><was established);\\r\\n</script>\\r\\nreturn false;\\\">).style.displaybecause of the document.cookie<form action=\\\"/}body{margin:0;Encyclopedia ofversion of the .createElement(name\\\" content=\\\"</div>\\n</div>\\n\\nadministrative </body>\\n</html>history of the \\\"><input type=\\\"portion of the as part of the &nbsp;<a href=\\\"other countries\\\">\\n<div class=\\\"</span></span><In other words,display: block;control of the introduction of/>\\n<meta name=\\\"as well as the in recent years\\r\\n\\t<div class=\\\"</div>\\n\\t</div>\\ninspired by thethe end of the compatible withbecame known as style=\\\"margin:.js\\\"></script>< International there have beenGerman language style=\\\"color:#Communist Partyconsistent withborder=\\\"0\\\" cell marginheight=\\\"the majority of\\\" align=\\\"centerrelated to the many different Orthodox Churchsimilar to the />\\n<link rel=\\\"swas one of the until his death})();\\n</script>other languagescompared to theportions of thethe Netherlandsthe most commonbackground:url(argued that thescrolling=\\\"no\\\" included in theNorth American the name of theinterpretationsthe traditionaldevelopment of frequently useda collection ofvery similar tosurrounding theexample of thisalign=\\\"center\\\">would have beenimage_caption =attached to thesuggesting thatin the form of involved in theis derived fromnamed after theIntroduction torestrictions on style=\\\"width: can be used to the creation ofmost important information andresulted in thecollapse of theThis means thatelements of thewas replaced byanalysis of theinspiration forregarded as themost successfulknown as &quot;a comprehensiveHistory of the were consideredreturned to theare referred toUnsourced image>\\n\\t<div class=\\\"consists of thestopPropagationinterest in theavailability ofappears to haveelectromagneticenableServices(function of theIt is important</script></div>function(){var relative to theas a result of the position ofFor example, in method=\\\"post\\\" was followed by&amp;mdash; thethe applicationjs\\\"></script>\\r\\nul></div></div>after the deathwith respect tostyle=\\\"padding:is particularlydisplay:inline; type=\\\"submit\\\" is divided into\\u00E4\\u00B8\\u00AD\\u00E6\\u0096\\u0087 (\\u00E7\\u00AE\\u0080\\u00E4\\u00BD\\u0093)responsabilidadadministraci\\u00C3\\u00B3ninternacionalescorrespondiente\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0096\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00AD\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A3\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0089\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0083\\u00E0\\u00A4\\u00B7\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A0\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A2\\u00E0\\u00A4\\u00BC\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AB\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u008C\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0081\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009B\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A3\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A2\\u00E0\\u00A4\\u00BC\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AB\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0096\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u009A\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009B\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009B\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u0098\\u00E0\\u00A4\\u00A3\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A7\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B6\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BC\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0083\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u0098\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0096\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0082\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087rss+xml\\\" title=\\\"-type\\\" content=\\\"title\\\" content=\\\"at the same time.js\\\"></script>\\n<\\\" method=\\\"post\\\" </span></a></li>vertical-align:t/jquery.min.js\\\">.click(function( style=\\\"padding-})();\\n</script>\\n</span><a href=\\\"<a href=\\\"http://); return false;text-decoration: scrolling=\\\"no\\\" border-collapse:associated with Bahasa IndonesiaEnglish language<text xml:space=.gif\\\" border=\\\"0\\\"</body>\\n</html>\\noverflow:hidden;img src=\\\"http://addEventListenerresponsible for s.js\\\"></script>\\n/favicon.ico\\\" />operating system\\\" style=\\\"width:1target=\\\"_blank\\\">State Universitytext-align:left;\\ndocument.write(, including the around the world);\\r\\n</script>\\r\\n<\\\" style=\\\"height:;overflow:hiddenmore informationan internationala member of the one of the firstcan be found in </div>\\n\\t\\t</div>\\ndisplay: none;\\\">\\\" />\\n<link rel=\\\"\\n  (function() {the 15th century.preventDefault(large number of Byzantine Empire.jpg|thumb|left|vast majority ofmajority of the  align=\\\"center\\\">University Pressdominated by theSecond World Wardistribution of style=\\\"position:the rest of the characterized by rel=\\\"nofollow\\\">derives from therather than the a combination ofstyle=\\\"width:100English-speakingcomputer scienceborder=\\\"0\\\" alt=\\\"the existence ofDemocratic Party\\\" style=\\\"margin-For this reason,.js\\\"></script>\\n\\tsByTagName(s)[0]js\\\"></script>\\r\\n<.js\\\"></script>\\r\\nlink rel=\\\"icon\\\" ' alt='' class='formation of theversions of the </a></div></div>/page>\\n  <page>\\n<div class=\\\"contbecame the firstbahasa Indonesiaenglish (simple)\\u00CE\\u0095\\u00CE\\u00BB\\u00CE\\u00BB\\u00CE\\u00B7\\u00CE\\u00BD\\u00CE\\u00B9\\u00CE\\u00BA\\u00CE\\u00AC\\u00D1\\u0085\\u00D1\\u0080\\u00D0\\u00B2\\u00D0\\u00B0\\u00D1\\u0082\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BF\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00B2\\u00D0\\u00BB\\u00D1\\u008F\\u00D0\\u00B5\\u00D1\\u0082\\u00D1\\u0081\\u00D1\\u008F\\u00D0\\u0094\\u00D0\\u00BE\\u00D0\\u00B1\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u008C\\u00D1\\u0087\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B5\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00B2\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u0098\\u00D0\\u00BD\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00BD\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u009E\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00BD\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u0086\\u00D1\\u008B\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0087\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00B5\\u00D1\\u0083\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B8\\u00D1\\u008F\\u00D1\\u0085\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B1\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00BC\\u00D1\\u008B\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00BB\\u00D1\\u0083\\u00D1\\u0087\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u008C\\u00D1\\u008F\\u00D0\\u00B2\\u00D0\\u00BB\\u00D1\\u008F\\u00D1\\u008E\\u00D1\\u0082\\u00D1\\u0081\\u00D1\\u008F\\u00D0\\u00BD\\u00D0\\u00B0\\u00D0\\u00B8\\u00D0\\u00B1\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00B5\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00BF\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00B2\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00B4\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00B0\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00B6\\u00D9\\u008A\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00A6\\u00D9\\u008A\\u00D8\\u00B3\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0086\\u00D8\\u00AA\\u00D9\\u0082\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A7\\u00D8\\u00AA\\u00D9\\u0083\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B3\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0083\\u00D8\\u00AA\\u00D9\\u0088\\u00D8\\u00A8\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B3\\u00D8\\u00B9\\u00D9\\u0088\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D8\\u00AD\\u00D8\\u00B5\\u00D8\\u00A7\\u00D8\\u00A6\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B5\\u00D9\\u0088\\u00D8\\u00AA\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00B1\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AA\\u00D8\\u00B5\\u00D8\\u00A7\\u00D9\\u0085\\u00D9\\u008A\\u00D9\\u0085\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A5\\u00D8\\u00B3\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0085\\u00D9\\u008A\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B1\\u00D8\\u00A6\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AArobots\\\" content=\\\"<div id=\\\"footer\\\">the United States<img src=\\\"http://.jpg|right|thumb|.js\\\"></script>\\r\\n<location.protocolframeborder=\\\"0\\\" s\\\" />\\n<meta name=\\\"</a></div></div><font-weight:bold;&quot; and &quot;depending on the margin:0;padding:\\\" rel=\\\"nofollow\\\" President of the twentieth centuryevision>\\n  </pageInternet Explorera.async = true;\\r\\ninformation about<div id=\\\"header\\\">\\\" action=\\\"http://<a href=\\\"https://<div id=\\\"content\\\"</div>\\r\\n</div>\\r\\n<derived from the <img src='http://according to the \\n</body>\\n</html>\\nstyle=\\\"font-size:script language=\\\"Arial, Helvetica,</a><span class=\\\"</script><script political partiestd></tr></table><href=\\\"http://www.interpretation ofrel=\\\"stylesheet\\\" document.write('<charset=\\\"utf-8\\\">\\nbeginning of the revealed that thetelevision series\\\" rel=\\\"nofollow\\\"> target=\\\"_blank\\\">claiming that thehttp%3A%2F%2Fwww.manifestations ofPrime Minister ofinfluenced by theclass=\\\"clearfix\\\">/div>\\r\\n</div>\\r\\n\\r\\nthree-dimensionalChurch of Englandof North Carolinasquare kilometres.addEventListenerdistinct from thecommonly known asPhonetic Alphabetdeclared that thecontrolled by theBenjamin Franklinrole-playing gamethe University ofin Western Europepersonal computerProject Gutenbergregardless of thehas been proposedtogether with the></li><li class=\\\"in some countriesmin.js\\\"></script>of the populationofficial language<img src=\\\"images/identified by thenatural resourcesclassification ofcan be consideredquantum mechanicsNevertheless, themillion years ago</body>\\r\\n</html>\\r\\u00CE\\u0095\\u00CE\\u00BB\\u00CE\\u00BB\\u00CE\\u00B7\\u00CE\\u00BD\\u00CE\\u00B9\\u00CE\\u00BA\\u00CE\\u00AC\\ntake advantage ofand, according toattributed to theMicrosoft Windowsthe first centuryunder the controldiv class=\\\"headershortly after thenotable exceptiontens of thousandsseveral differentaround the world.reaching militaryisolated from theopposition to thethe Old TestamentAfrican Americansinserted into theseparate from themetropolitan areamakes it possibleacknowledged thatarguably the mosttype=\\\"text/css\\\">\\nthe InternationalAccording to the pe=\\\"text/css\\\" />\\ncoincide with thetwo-thirds of theDuring this time,during the periodannounced that hethe internationaland more recentlybelieved that theconsciousness andformerly known assurrounded by thefirst appeared inoccasionally usedposition:absolute;\\\" target=\\\"_blank\\\" position:relative;text-align:center;jax/libs/jquery/1.background-color:#type=\\\"application/anguage\\\" content=\\\"<meta http-equiv=\\\"Privacy Policy</a>e(\\\"%3Cscript src='\\\" target=\\\"_blank\\\">On the other hand,.jpg|thumb|right|2</div><div class=\\\"<div style=\\\"float:nineteenth century</body>\\r\\n</html>\\r\\n<img src=\\\"http://s;text-align:centerfont-weight: bold; According to the difference between\\\" frameborder=\\\"0\\\" \\\" style=\\\"position:link href=\\\"http://html4/loose.dtd\\\">\\nduring this period</td></tr></table>closely related tofor the first time;font-weight:bold;input type=\\\"text\\\" <span style=\\\"font-onreadystatechange\\t<div class=\\\"cleardocument.location. For example, the a wide variety of <!DOCTYPE html>\\r\\n<&nbsp;&nbsp;&nbsp;\\\"><a href=\\\"http://style=\\\"float:left;concerned with the=http%3A%2F%2Fwww.in popular culturetype=\\\"text/css\\\" />it is possible to Harvard Universitytylesheet\\\" href=\\\"/the main characterOxford University  name=\\\"keywords\\\" cstyle=\\\"text-align:the United Kingdomfederal government<div style=\\\"margin depending on the description of the<div class=\\\"header.min.js\\\"></script>destruction of theslightly differentin accordance withtelecommunicationsindicates that theshortly thereafterespecially in the European countriesHowever, there aresrc=\\\"http://staticsuggested that the\\\" src=\\\"http://www.a large number of Telecommunications\\\" rel=\\\"nofollow\\\" tHoly Roman Emperoralmost exclusively\\\" border=\\\"0\\\" alt=\\\"Secretary of Stateculminating in theCIA World Factbookthe most importantanniversary of thestyle=\\\"background-<li><em><a href=\\\"/the Atlantic Oceanstrictly speaking,shortly before thedifferent types ofthe Ottoman Empire><img src=\\\"http://An Introduction toconsequence of thedeparture from theConfederate Statesindigenous peoplesProceedings of theinformation on thetheories have beeninvolvement in thedivided into threeadjacent countriesis responsible fordissolution of thecollaboration withwidely regarded ashis contemporariesfounding member ofDominican Republicgenerally acceptedthe possibility ofare also availableunder constructionrestoration of thethe general publicis almost entirelypasses through thehas been suggestedcomputer and videoGermanic languages according to the different from theshortly afterwardshref=\\\"https://www.recent developmentBoard of Directors<div class=\\\"search| <a href=\\\"http://In particular, theMultiple footnotesor other substancethousands of yearstranslation of the</div>\\r\\n</div>\\r\\n\\r\\n<a href=\\\"index.phpwas established inmin.js\\\"></script>\\nparticipate in thea strong influencestyle=\\\"margin-top:represented by thegraduated from theTraditionally, theElement(\\\"script\\\");However, since the/div>\\n</div>\\n<div left; margin-left:protection against0; vertical-align:Unfortunately, thetype=\\\"image/x-icon/div>\\n<div class=\\\" class=\\\"clearfix\\\"><div class=\\\"footer\\t\\t</div>\\n\\t\\t</div>\\nthe motion picture\\u00D0\\u0091\\u00D1\\u008A\\u00D0\\u00BB\\u00D0\\u00B3\\u00D0\\u00B0\\u00D1\\u0080\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00B1\\u00D1\\u008A\\u00D0\\u00BB\\u00D0\\u00B3\\u00D0\\u00B0\\u00D1\\u0080\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00A4\\u00D0\\u00B5\\u00D0\\u00B4\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B0\\u00D1\\u0086\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u00BD\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00BA\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u0089\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u0089\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B3\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00BC\\u00D1\\u008B\\u00D0\\u009E\\u00D1\\u0082\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00B1\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00BF\\u00D0\\u00BB\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00B0\\u00D0\\u00BB\\u00D1\\u008B\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00B7\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00BB\\u00D1\\u008F\\u00D0\\u00B5\\u00D1\\u0082\\u00D0\\u00BF\\u00D0\\u00BE\\u00D1\\u0081\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00B4\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u0087\\u00D0\\u00BD\\u00D1\\u008B\\u00D1\\u0085\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B4\\u00D1\\u0083\\u00D0\\u00BA\\u00D1\\u0086\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B3\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BC\\u00D0\\u00BC\\u00D0\\u00B0\\u00D0\\u00BF\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u008C\\u00D1\\u008E\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0085\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B8\\u00D1\\u0082\\u00D1\\u0081\\u00D1\\u008F\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00B1\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00BD\\u00D0\\u00BE\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00B5\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00BC\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u0090\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00BA\\u00D1\\u0081\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B4\\u00D1\\u0080\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A7\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B5\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0091\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AB\\u00E0\\u00A4\\u00BC\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0088\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BC\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00B6\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A3\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A3\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u009A\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009A\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A7\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A6\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A7\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00B9\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00AC\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u008F\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0096\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A7\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BC\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B5\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0096\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B6\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0086\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D8\\u00B1\\u00D9\\u0083\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D9\\u0086\\u00D8\\u00AA\\u00D8\\u00AF\\u00D9\\u008A\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0083\\u00D9\\u0085\\u00D8\\u00A8\\u00D9\\u008A\\u00D9\\u0088\\u00D8\\u00AA\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B4\\u00D8\\u00A7\\u00D9\\u0087\\u00D8\\u00AF\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00B9\\u00D8\\u00AF\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B2\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00B1\\u00D8\\u00B9\\u00D8\\u00AF\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00B1\\u00D8\\u00AF\\u00D9\\u0088\\u00D8\\u00AF\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A5\\u00D8\\u00B3\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0085\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0081\\u00D9\\u0088\\u00D8\\u00AA\\u00D9\\u0088\\u00D8\\u00B4\\u00D9\\u0088\\u00D8\\u00A8\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B3\\u00D8\\u00A7\\u00D8\\u00A8\\u00D9\\u0082\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B9\\u00D9\\u0084\\u00D9\\u0088\\u00D9\\u0085\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00B3\\u00D9\\u0084\\u00D8\\u00B3\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00AC\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0081\\u00D9\\u008A\\u00D9\\u0083\\u00D8\\u00B3\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00B3\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0085\\u00D9\\u008A\\u00D8\\u00A9\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00B5\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00AAkeywords\\\" content=\\\"w3.org/1999/xhtml\\\"><a target=\\\"_blank\\\" text/html; charset=\\\" target=\\\"_blank\\\"><table cellpadding=\\\"autocomplete=\\\"off\\\" text-align: center;to last version by background-color: #\\\" href=\\\"http://www./div></div><div id=<a href=\\\"#\\\" class=\\\"\\\"><img src=\\\"http://cript\\\" src=\\\"http://\\n<script language=\\\"//EN\\\" \\\"http://www.wencodeURIComponent(\\\" href=\\\"javascript:<div class=\\\"contentdocument.write('<scposition: absolute;script src=\\\"http:// style=\\\"margin-top:.min.js\\\"></script>\\n</div>\\n<div class=\\\"w3.org/1999/xhtml\\\" \\n\\r\\n</body>\\r\\n</html>distinction between/\\\" target=\\\"_blank\\\"><link href=\\\"http://encoding=\\\"utf-8\\\"?>\\nw.addEventListener?action=\\\"http://www.icon\\\" href=\\\"http:// style=\\\"background:type=\\\"text/css\\\" />\\nmeta property=\\\"og:t<input type=\\\"text\\\"  style=\\\"text-align:the development of tylesheet\\\" type=\\\"tehtml; charset=utf-8is considered to betable width=\\\"100%\\\" In addition to the contributed to the differences betweendevelopment of the It is important to </script>\\n\\n<script  style=\\\"font-size:1></span><span id=gbLibrary of Congress<img src=\\\"http://imEnglish translationAcademy of Sciencesdiv style=\\\"display:construction of the.getElementById(id)in conjunction withElement('script'); <meta property=\\\"og:\\u00D0\\u0091\\u00D1\\u008A\\u00D0\\u00BB\\u00D0\\u00B3\\u00D0\\u00B0\\u00D1\\u0080\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00B8\\n type=\\\"text\\\" name=\\\">Privacy Policy</a>administered by theenableSingleRequeststyle=&quot;margin:</div></div></div><><img src=\\\"http://i style=&quot;float:referred to as the total population ofin Washington, D.C. style=\\\"background-among other things,organization of theparticipated in thethe introduction ofidentified with thefictional character Oxford University misunderstanding ofThere are, however,stylesheet\\\" href=\\\"/Columbia Universityexpanded to includeusually referred toindicating that thehave suggested thataffiliated with thecorrelation betweennumber of different></td></tr></table>Republic of Ireland\\n</script>\\n<script under the influencecontribution to theOfficial website ofheadquarters of thecentered around theimplications of thehave been developedFederal Republic ofbecame increasinglycontinuation of theNote, however, thatsimilar to that of capabilities of theaccordance with theparticipants in thefurther developmentunder the directionis often consideredhis younger brother</td></tr></table><a http-equiv=\\\"X-UA-physical propertiesof British Columbiahas been criticized(with the exceptionquestions about thepassing through the0\\\" cellpadding=\\\"0\\\" thousands of peopleredirects here. Forhave children under%3E%3C/script%3E\\\"));<a href=\\\"http://www.<li><a href=\\\"http://site_name\\\" content=\\\"text-decoration:nonestyle=\\\"display: none<meta http-equiv=\\\"X-new Date().getTime() type=\\\"image/x-icon\\\"</span><span class=\\\"language=\\\"javascriptwindow.location.href<a href=\\\"javascript:-->\\r\\n<script type=\\\"t<a href='http://www.hortcut icon\\\" href=\\\"</div>\\r\\n<div class=\\\"<script src=\\\"http://\\\" rel=\\\"stylesheet\\\" t</div>\\n<script type=/a> <a href=\\\"http:// allowTransparency=\\\"X-UA-Compatible\\\" conrelationship between\\n</script>\\r\\n<script </a></li></ul></div>associated with the programming language</a><a href=\\\"http://</a></li><li class=\\\"form action=\\\"http://<div style=\\\"display:type=\\\"text\\\" name=\\\"q\\\"<table width=\\\"100%\\\" background-position:\\\" border=\\\"0\\\" width=\\\"rel=\\\"shortcut icon\\\" h6><ul><li><a href=\\\"  <meta http-equiv=\\\"css\\\" media=\\\"screen\\\" responsible for the \\\" type=\\\"application/\\\" style=\\\"background-html; charset=utf-8\\\" allowtransparency=\\\"stylesheet\\\" type=\\\"te\\r\\n<meta http-equiv=\\\"></span><span class=\\\"0\\\" cellspacing=\\\"0\\\">;\\n</script>\\n<script sometimes called thedoes not necessarilyFor more informationat the beginning of <!DOCTYPE html><htmlparticularly in the type=\\\"hidden\\\" name=\\\"javascript:void(0);\\\"effectiveness of the autocomplete=\\\"off\\\" generally considered><input type=\\\"text\\\" \\\"></script>\\r\\n<scriptthroughout the worldcommon misconceptionassociation with the</div>\\n</div>\\n<div cduring his lifetime,corresponding to thetype=\\\"image/x-icon\\\" an increasing numberdiplomatic relationsare often consideredmeta charset=\\\"utf-8\\\" <input type=\\\"text\\\" examples include the\\\"><img src=\\\"http://iparticipation in thethe establishment of\\n</div>\\n<div class=\\\"&amp;nbsp;&amp;nbsp;to determine whetherquite different frommarked the beginningdistance between thecontributions to theconflict between thewidely considered towas one of the firstwith varying degreeshave speculated that(document.getElementparticipating in theoriginally developedeta charset=\\\"utf-8\\\"> type=\\\"text/css\\\" />\\ninterchangeably withmore closely relatedsocial and politicalthat would otherwiseperpendicular to thestyle type=\\\"text/csstype=\\\"submit\\\" name=\\\"families residing indeveloping countriescomputer programmingeconomic developmentdetermination of thefor more informationon several occasionsportugu\\u00C3\\u00AAs (Europeu)\\u00D0\\u00A3\\u00D0\\u00BA\\u00D1\\u0080\\u00D0\\u00B0\\u00D1\\u0097\\u00D0\\u00BD\\u00D1\\u0081\\u00D1\\u008C\\u00D0\\u00BA\\u00D0\\u00B0\\u00D1\\u0083\\u00D0\\u00BA\\u00D1\\u0080\\u00D0\\u00B0\\u00D1\\u0097\\u00D0\\u00BD\\u00D1\\u0081\\u00D1\\u008C\\u00D0\\u00BA\\u00D0\\u00B0\\u00D0\\u00A0\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0081\\u00D0\\u00B8\\u00D0\\u00B9\\u00D1\\u0081\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00B9\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00B0\\u00D0\\u00BB\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0086\\u00D0\\u00B8\\u00D0\\u00B8\\u00D1\\u0083\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B2\\u00D0\\u00BB\\u00D0\\u00B5\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00BD\\u00D0\\u00B5\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u0085\\u00D0\\u00BE\\u00D0\\u00B4\\u00D0\\u00B8\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0086\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u0098\\u00D0\\u00BD\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0086\\u00D0\\u00B8\\u00D1\\u008F\\u00D0\\u00A0\\u00D0\\u00B5\\u00D1\\u0081\\u00D0\\u00BF\\u00D1\\u0083\\u00D0\\u00B1\\u00D0\\u00BB\\u00D0\\u00B8\\u00D0\\u00BA\\u00D0\\u00B8\\u00D0\\u00BA\\u00D0\\u00BE\\u00D0\\u00BB\\u00D0\\u00B8\\u00D1\\u0087\\u00D0\\u00B5\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B8\\u00D0\\u00BD\\u00D1\\u0084\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00BC\\u00D0\\u00B0\\u00D1\\u0086\\u00D0\\u00B8\\u00D1\\u008E\\u00D1\\u0082\\u00D0\\u00B5\\u00D1\\u0080\\u00D1\\u0080\\u00D0\\u00B8\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u00B4\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00BE\\u00D1\\u0087\\u00D0\\u00BD\\u00D0\\u00BE\\u00D8\\u00A7\\u00D9\\u0084\\u00D9\\u0085\\u00D8\\u00AA\\u00D9\\u0088\\u00D8\\u00A7\\u00D8\\u00AC\\u00D8\\u00AF\\u00D9\\u0088\\u00D9\\u0086\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D8\\u00B4\\u00D8\\u00AA\\u00D8\\u00B1\\u00D8\\u00A7\\u00D9\\u0083\\u00D8\\u00A7\\u00D8\\u00AA\\u00D8\\u00A7\\u00D9\\u0084\\u00D8\\u00A7\\u00D9\\u0082\\u00D8\\u00AA\\u00D8\\u00B1\\u00D8\\u00A7\\u00D8\\u00AD\\u00D8\\u00A7\\u00D8\\u00AAhtml; charset=UTF-8\\\" setTimeout(function()display:inline-block;<input type=\\\"submit\\\" type = 'text/javascri<img src=\\\"http://www.\\\" \\\"http://www.w3.org/shortcut icon\\\" href=\\\"\\\" autocomplete=\\\"off\\\" </a></div><div class=</a></li>\\n<li class=\\\"css\\\" type=\\\"text/css\\\" <form action=\\\"http://xt/css\\\" href=\\\"http://link rel=\\\"alternate\\\" \\r\\n<script type=\\\"text/ onclick=\\\"javascript:(new Date).getTime()}height=\\\"1\\\" width=\\\"1\\\" People's Republic of  <a href=\\\"http://www.text-decoration:underthe beginning of the </div>\\n</div>\\n</div>\\nestablishment of the </div></div></div></d#viewport{min-height:\\n<script src=\\\"http://option><option value=often referred to as /option>\\n<option valu<!DOCTYPE html>\\n<!--[International Airport>\\n<a href=\\\"http://www</a><a href=\\\"http://w\\u00E0\\u00B8\\u00A0\\u00E0\\u00B8\\u00B2\\u00E0\\u00B8\\u00A9\\u00E0\\u00B8\\u00B2\\u00E0\\u00B9\\u0084\\u00E0\\u00B8\\u0097\\u00E0\\u00B8\\u00A2\\u00E1\\u0083\\u00A5\\u00E1\\u0083\\u0090\\u00E1\\u0083\\u00A0\\u00E1\\u0083\\u0097\\u00E1\\u0083\\u00A3\\u00E1\\u0083\\u009A\\u00E1\\u0083\\u0098\\u00E6\\u00AD\\u00A3\\u00E9\\u00AB\\u0094\\u00E4\\u00B8\\u00AD\\u00E6\\u0096\\u0087 (\\u00E7\\u00B9\\u0081\\u00E9\\u00AB\\u0094)\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A6\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B6\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B2\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B7\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u009C\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A7\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B5\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A3\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A0\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009E\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0085\\u00E0\\u00A4\\u00AE\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A1\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0081\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AF\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u0081\\u00E0\\u00A4\\u009A\\u00E0\\u00A4\\u00A4\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AC\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A7\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A3\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00AB\\u00E0\\u00A4\\u00BC\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A3\\u00E0\\u00A4\\u00B2\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AE\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009F\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00A1description\\\" content=\\\"document.location.prot.getElementsByTagName(<!DOCTYPE html>\\n<html <meta charset=\\\"utf-8\\\">:url\\\" content=\\\"http://.css\\\" rel=\\\"stylesheet\\\"style type=\\\"text/css\\\">type=\\\"text/css\\\" href=\\\"w3.org/1999/xhtml\\\" xmltype=\\\"text/javascript\\\" method=\\\"get\\\" action=\\\"link rel=\\\"stylesheet\\\"  = document.getElementtype=\\\"image/x-icon\\\" />cellpadding=\\\"0\\\" cellsp.css\\\" type=\\\"text/css\\\" </a></li><li><a href=\\\"\\\" width=\\\"1\\\" height=\\\"1\\\"\\\"><a href=\\\"http://www.style=\\\"display:none;\\\">alternate\\\" type=\\\"appli-//W3C//DTD XHTML 1.0 ellspacing=\\\"0\\\" cellpad type=\\\"hidden\\\" value=\\\"/a>&nbsp;<span role=\\\"s\\n<input type=\\\"hidden\\\" language=\\\"JavaScript\\\"  document.getElementsBg=\\\"0\\\" cellspacing=\\\"0\\\" ype=\\\"text/css\\\" media=\\\"type='text/javascript'with the exception of ype=\\\"text/css\\\" rel=\\\"st height=\\\"1\\\" width=\\\"1\\\" ='+encodeURIComponent(<link rel=\\\"alternate\\\" \\nbody, tr, input, textmeta name=\\\"robots\\\" conmethod=\\\"post\\\" action=\\\">\\n<a href=\\\"http://www.css\\\" rel=\\\"stylesheet\\\" </div></div><div classlanguage=\\\"javascript\\\">aria-hidden=\\\"true\\\">\\u00C2\\u00B7<ript\\\" type=\\\"text/javasl=0;})();\\n(function(){background-image: url(/a></li><li><a href=\\\"h\\t\\t<li><a href=\\\"http://ator\\\" aria-hidden=\\\"tru> <a href=\\\"http://www.language=\\\"javascript\\\" /option>\\n<option value/div></div><div class=rator\\\" aria-hidden=\\\"tre=(new Date).getTime()portugu\\u00C3\\u00AAs (do Brasil)\\u00D0\\u00BE\\u00D1\\u0080\\u00D0\\u00B3\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00B0\\u00D1\\u0086\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B7\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B6\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u008C\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u0080\\u00D0\\u00B0\\u00D0\\u00B7\\u00D0\\u00BE\\u00D0\\u00B2\\u00D0\\u00B0\\u00D0\\u00BD\\u00D0\\u00B8\\u00D1\\u008F\\u00D1\\u0080\\u00D0\\u00B5\\u00D0\\u00B3\\u00D0\\u00B8\\u00D1\\u0081\\u00D1\\u0082\\u00D1\\u0080\\u00D0\\u00B0\\u00D1\\u0086\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B7\\u00D0\\u00BC\\u00D0\\u00BE\\u00D0\\u00B6\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D0\\u00BE\\u00D0\\u00B1\\u00D1\\u008F\\u00D0\\u00B7\\u00D0\\u00B0\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00BD\\u00D0\\u00B0<!DOCTYPE html PUBLIC \\\"nt-Type\\\" content=\\\"text/<meta http-equiv=\\\"Conteransitional//EN\\\" \\\"http:<html xmlns=\\\"http://www-//W3C//DTD XHTML 1.0 TDTD/xhtml1-transitional//www.w3.org/TR/xhtml1/pe = 'text/javascript';<meta name=\\\"descriptionparentNode.insertBefore<input type=\\\"hidden\\\" najs\\\" type=\\\"text/javascri(document).ready(functiscript type=\\\"text/javasimage\\\" content=\\\"http://UA-Compatible\\\" content=tml; charset=utf-8\\\" />\\nlink rel=\\\"shortcut icon<link rel=\\\"stylesheet\\\" </script>\\n<script type== document.createElemen<a target=\\\"_blank\\\" href= document.getElementsBinput type=\\\"text\\\" name=a.type = 'text/javascrinput type=\\\"hidden\\\" namehtml; charset=utf-8\\\" />dtd\\\">\\n<html xmlns=\\\"http-//W3C//DTD HTML 4.01 TentsByTagName('script')input type=\\\"hidden\\\" nam<script type=\\\"text/javas\\\" style=\\\"display:none;\\\">document.getElementById(=document.createElement(' type='text/javascript'input type=\\\"text\\\" name=\\\"d.getElementsByTagName(snical\\\" href=\\\"http://www.C//DTD HTML 4.01 Transit<style type=\\\"text/css\\\">\\n\\n<style type=\\\"text/css\\\">ional.dtd\\\">\\n<html xmlns=http-equiv=\\\"Content-Typeding=\\\"0\\\" cellspacing=\\\"0\\\"html; charset=utf-8\\\" />\\n style=\\\"display:none;\\\"><<li><a href=\\\"http://www. type='text/javascript'>\\u00D0\\u00B4\\u00D0\\u00B5\\u00D1\\u008F\\u00D1\\u0082\\u00D0\\u00B5\\u00D0\\u00BB\\u00D1\\u008C\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00D1\\u0081\\u00D0\\u00BE\\u00D0\\u00BE\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00B5\\u00D1\\u0082\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00B8\\u00D0\\u00B8\\u00D0\\u00BF\\u00D1\\u0080\\u00D0\\u00BE\\u00D0\\u00B8\\u00D0\\u00B7\\u00D0\\u00B2\\u00D0\\u00BE\\u00D0\\u00B4\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B2\\u00D0\\u00B0\\u00D0\\u00B1\\u00D0\\u00B5\\u00D0\\u00B7\\u00D0\\u00BE\\u00D0\\u00BF\\u00D0\\u00B0\\u00D1\\u0081\\u00D0\\u00BD\\u00D0\\u00BE\\u00D1\\u0081\\u00D1\\u0082\\u00D0\\u00B8\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0097\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0089\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B9\\u00E0\\u00A5\\u008B\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u00A8\\u00E0\\u00A5\\u0087\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A7\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00AD\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AB\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u0082\\u00E0\\u00A4\\u0097\\u00E0\\u00A4\\u00B8\\u00E0\\u00A5\\u0081\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B7\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u0089\\u00E0\\u00A4\\u00AA\\u00E0\\u00A5\\u0080\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0087\\u00E0\\u00A4\\u009F\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u009C\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u009E\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00AA\\u00E0\\u00A4\\u00A8\\u00E0\\u00A4\\u0095\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u00B0\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00B5\\u00E0\\u00A4\\u00BE\\u00E0\\u00A4\\u0088\\u00E0\\u00A4\\u00B8\\u00E0\\u00A4\\u0095\\u00E0\\u00A5\\u008D\\u00E0\\u00A4\\u00B0\\u00E0\\u00A4\\u00BF\\u00E0\\u00A4\\u00AF\\u00E0\\u00A4\\u00A4\\u00E0\\u00A4\\u00BE\";\n\t\t\t}\n\t\t}\n\n\t\tprivate class DataHolder\n\t\t{\n\t\t\tinternal static readonly byte[] Data;\n\n\t\t\tstatic DataHolder()\n\t\t\t{\n\t\t\t\tData = new byte[122784];\n\t\t\t\tstring[] chunks = new string[] { Org.Brotli.Dec.Dictionary.DataHolder0.GetData(), Org.Brotli.Dec.Dictionary.DataHolder1.GetData(), Org.Brotli.Dec.Dictionary.DataHolder2.GetData() };\n\t\t\t\tint sum = 0;\n\t\t\t\tforeach (string chunk in chunks)\n\t\t\t\t{\n\t\t\t\t\tsum += chunk.Length;\n\t\t\t\t}\n\t\t\t\tif (sum != Data.Length)\n\t\t\t\t{\n\t\t\t\t\tthrow new System.Exception(\"Corrupted brotli dictionary\");\n\t\t\t\t}\n\t\t\t\tsum = 0;\n\t\t\t\tforeach (string chunk in chunks)\n\t\t\t\t{\n\t\t\t\t\tfor (int j = 0; j < chunk.Length; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tData[sum++] = unchecked((byte)chunk[j]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tinternal static byte[] GetData()\n\t\t{\n\t\t\treturn Org.Brotli.Dec.Dictionary.DataHolder.Data;\n\t\t}\n\n\t\tinternal static readonly int[] OffsetsByLength = new int[] { 0, 0, 0, 0, 0, 4096, 9216, 21504, 35840, 44032, 53248, 63488, 74752, 87040, 93696, 100864, 104704, 106752, 108928, 113536, 115968, 118528, 119872, 121280, 122016 };\n\n\t\tinternal static readonly int[] SizeBitsByLength = new int[] { 0, 0, 0, 0, 10, 10, 11, 11, 10, 10, 10, 10, 10, 9, 9, 8, 7, 7, 8, 7, 7, 6, 6, 5, 5 };\n\n\t\tinternal const int MinWordLength = 4;\n\n\t\tinternal const int MaxWordLength = 24;\n\n\t\tinternal const int MaxTransformedWordLength = 5 + MaxWordLength + 8;\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/Huffman.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Utilities for building Huffman decoding tables.</summary>\n\tinternal sealed class Huffman\n\t{\n\t\t/// <summary>\n\t\t/// Maximum possible Huffman table size for an alphabet size of 704, max code length 15 and root\n\t\t/// table bits 8.\n\t\t/// </summary>\n\t\tinternal const int HuffmanMaxTableSize = 1080;\n\n\t\tprivate const int MaxLength = 15;\n\n\t\t/// <summary>Returns reverse(reverse(key, len) + 1, len).</summary>\n\t\t/// <remarks>\n\t\t/// Returns reverse(reverse(key, len) + 1, len).\n\t\t/// <p> reverse(key, len) is the bit-wise reversal of the len least significant bits of key.\n\t\t/// </remarks>\n\t\tprivate static int GetNextKey(int key, int len)\n\t\t{\n\t\t\tint step = 1 << (len - 1);\n\t\t\twhile ((key & step) != 0)\n\t\t\t{\n\t\t\t\tstep >>= 1;\n\t\t\t}\n\t\t\treturn (key & (step - 1)) + step;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Stores\n\t\t/// <paramref name=\"item\"/>\n\t\t/// in\n\t\t/// <c>table[0], table[step], table[2 * step] .., table[end]</c>\n\t\t/// .\n\t\t/// <p> Assumes that end is an integer multiple of step.\n\t\t/// </summary>\n\t\tprivate static void ReplicateValue(int[] table, int offset, int step, int end, int item)\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tend -= step;\n\t\t\t\ttable[offset + end] = item;\n\t\t\t}\n\t\t\twhile (end > 0);\n\t\t}\n\n\t\t/// <param name=\"count\">histogram of bit lengths for the remaining symbols,</param>\n\t\t/// <param name=\"len\">code length of the next processed symbol.</param>\n\t\t/// <returns>table width of the next 2nd level table.</returns>\n\t\tprivate static int NextTableBitSize(int[] count, int len, int rootBits)\n\t\t{\n\t\t\tint left = 1 << (len - rootBits);\n\t\t\twhile (len < MaxLength)\n\t\t\t{\n\t\t\t\tleft -= count[len];\n\t\t\t\tif (left <= 0)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlen++;\n\t\t\t\tleft <<= 1;\n\t\t\t}\n\t\t\treturn len - rootBits;\n\t\t}\n\n\t\t/// <summary>Builds Huffman lookup table assuming code lengths are in symbol order.</summary>\n\t\tinternal static void BuildHuffmanTable(int[] rootTable, int tableOffset, int rootBits, int[] codeLengths, int codeLengthsSize)\n\t\t{\n\t\t\tint key;\n\t\t\t// Reversed prefix code.\n\t\t\tint[] sorted = new int[codeLengthsSize];\n\t\t\t// Symbols sorted by code length.\n\t\t\t// TODO: fill with zeroes?\n\t\t\tint[] count = new int[MaxLength + 1];\n\t\t\t// Number of codes of each length.\n\t\t\tint[] offset = new int[MaxLength + 1];\n\t\t\t// Offsets in sorted table for each length.\n\t\t\tint symbol;\n\t\t\t// Build histogram of code lengths.\n\t\t\tfor (symbol = 0; symbol < codeLengthsSize; symbol++)\n\t\t\t{\n\t\t\t\tcount[codeLengths[symbol]]++;\n\t\t\t}\n\t\t\t// Generate offsets into sorted symbol table by code length.\n\t\t\toffset[1] = 0;\n\t\t\tfor (int len = 1; len < MaxLength; len++)\n\t\t\t{\n\t\t\t\toffset[len + 1] = offset[len] + count[len];\n\t\t\t}\n\t\t\t// Sort symbols by length, by symbol order within each length.\n\t\t\tfor (symbol = 0; symbol < codeLengthsSize; symbol++)\n\t\t\t{\n\t\t\t\tif (codeLengths[symbol] != 0)\n\t\t\t\t{\n\t\t\t\t\tsorted[offset[codeLengths[symbol]]++] = symbol;\n\t\t\t\t}\n\t\t\t}\n\t\t\tint tableBits = rootBits;\n\t\t\tint tableSize = 1 << tableBits;\n\t\t\tint totalSize = tableSize;\n\t\t\t// Special case code with only one value.\n\t\t\tif (offset[MaxLength] == 1)\n\t\t\t{\n\t\t\t\tfor (key = 0; key < totalSize; key++)\n\t\t\t\t{\n\t\t\t\t\trootTable[tableOffset + key] = sorted[0];\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Fill in root table.\n\t\t\tkey = 0;\n\t\t\tsymbol = 0;\n\t\t\tfor (int len = 1, step = 2; len <= rootBits; len++, step <<= 1)\n\t\t\t{\n\t\t\t\tfor (; count[len] > 0; count[len]--)\n\t\t\t\t{\n\t\t\t\t\tReplicateValue(rootTable, tableOffset + key, step, tableSize, len << 16 | sorted[symbol++]);\n\t\t\t\t\tkey = GetNextKey(key, len);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fill in 2nd level tables and add pointers to root table.\n\t\t\tint mask = totalSize - 1;\n\t\t\tint low = -1;\n\t\t\tint currentOffset = tableOffset;\n\t\t\tfor (int len = rootBits + 1, step = 2; len <= MaxLength; len++, step <<= 1)\n\t\t\t{\n\t\t\t\tfor (; count[len] > 0; count[len]--)\n\t\t\t\t{\n\t\t\t\t\tif ((key & mask) != low)\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentOffset += tableSize;\n\t\t\t\t\t\ttableBits = NextTableBitSize(count, len, rootBits);\n\t\t\t\t\t\ttableSize = 1 << tableBits;\n\t\t\t\t\t\ttotalSize += tableSize;\n\t\t\t\t\t\tlow = key & mask;\n\t\t\t\t\t\trootTable[tableOffset + low] = (tableBits + rootBits) << 16 | (currentOffset - tableOffset - low);\n\t\t\t\t\t}\n\t\t\t\t\tReplicateValue(rootTable, currentOffset + (key >> rootBits), step, tableSize, (len - rootBits) << 16 | sorted[symbol++]);\n\t\t\t\t\tkey = GetNextKey(key, len);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/HuffmanTreeGroup.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Contains a collection of huffman trees with the same alphabet size.</summary>\n\tinternal sealed class HuffmanTreeGroup\n\t{\n\t\t/// <summary>The maximal alphabet size in this group.</summary>\n\t\tprivate int alphabetSize;\n\n\t\t/// <summary>Storage for Huffman lookup tables.</summary>\n\t\tinternal int[] codes;\n\n\t\t/// <summary>\n\t\t/// Offsets of distinct lookup tables in\n\t\t/// <see cref=\"codes\"/>\n\t\t/// storage.\n\t\t/// </summary>\n\t\tinternal int[] trees;\n\n\t\t/// <summary>Initializes the Huffman tree group.</summary>\n\t\t/// <param name=\"group\">POJO to be initialised</param>\n\t\t/// <param name=\"alphabetSize\">the maximal alphabet size in this group</param>\n\t\t/// <param name=\"n\">number of Huffman codes</param>\n\t\tinternal static void Init(Org.Brotli.Dec.HuffmanTreeGroup group, int alphabetSize, int n)\n\t\t{\n\t\t\tgroup.alphabetSize = alphabetSize;\n\t\t\tgroup.codes = new int[n * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];\n\t\t\tgroup.trees = new int[n];\n\t\t}\n\n\t\t/// <summary>Decodes Huffman trees from input stream and constructs lookup tables.</summary>\n\t\t/// <param name=\"group\">target POJO</param>\n\t\t/// <param name=\"br\">data source</param>\n\t\tinternal static void Decode(Org.Brotli.Dec.HuffmanTreeGroup group, Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tint next = 0;\n\t\t\tint n = group.trees.Length;\n\t\t\tfor (int i = 0; i < n; i++)\n\t\t\t{\n\t\t\t\tgroup.trees[i] = next;\n\t\t\t\tOrg.Brotli.Dec.Decode.ReadHuffmanCode(group.alphabetSize, group.codes, next, br);\n\t\t\t\tnext += Org.Brotli.Dec.Huffman.HuffmanMaxTableSize;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/IntReader.cs",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Byte-to-int conversion magic.</summary>\n\tinternal sealed class IntReader\n\t{\n\t\tprivate byte[] byteBuffer;\n\n\t\tprivate int[] intBuffer;\n\n\t\tinternal static void Init(Org.Brotli.Dec.IntReader ir, byte[] byteBuffer, int[] intBuffer)\n\t\t{\n\t\t\tir.byteBuffer = byteBuffer;\n\t\t\tir.intBuffer = intBuffer;\n\t\t}\n\n\t\t/// <summary>Translates bytes to ints.</summary>\n\t\t/// <remarks>\n\t\t/// Translates bytes to ints.\n\t\t/// NB: intLen == 4 * byteSize!\n\t\t/// NB: intLen should be less or equal to intBuffer length.\n\t\t/// </remarks>\n\t\tinternal static void Convert(Org.Brotli.Dec.IntReader ir, int intLen)\n\t\t{\n\t\t\tfor (int i = 0; i < intLen; ++i)\n\t\t\t{\n\t\t\t\tir.intBuffer[i] = ((ir.byteBuffer[i * 4] & unchecked((int)(0xFF)))) | ((ir.byteBuffer[(i * 4) + 1] & unchecked((int)(0xFF))) << 8) | ((ir.byteBuffer[(i * 4) + 2] & unchecked((int)(0xFF))) << 16) | ((ir.byteBuffer[(i * 4) + 3] & unchecked((int\n\t\t\t\t\t)(0xFF))) << 24);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/Prefix.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Lookup tables to map prefix codes to value ranges.</summary>\n\t/// <remarks>\n\t/// Lookup tables to map prefix codes to value ranges.\n\t/// <p> This is used during decoding of the block lengths, literal insertion lengths and copy\n\t/// lengths.\n\t/// <p> Range represents values: [offset, offset + 2 ^ n_bits)\n\t/// </remarks>\n\tinternal sealed class Prefix\n\t{\n\t\tinternal static readonly int[] BlockLengthOffset = new int[] { 1, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 145, 177, 209, 241, 305, 369, 497, 753, 1265, 2289, 4337, 8433, 16625 };\n\n\t\tinternal static readonly int[] BlockLengthNBits = new int[] { 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 24 };\n\n\t\tinternal static readonly int[] InsertLengthOffset = new int[] { 0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, 34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594 };\n\n\t\tinternal static readonly int[] InsertLengthNBits = new int[] { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24 };\n\n\t\tinternal static readonly int[] CopyLengthOffset = new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18, 22, 30, 38, 54, 70, 102, 134, 198, 326, 582, 1094, 2118 };\n\n\t\tinternal static readonly int[] CopyLengthNBits = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24 };\n\n\t\tinternal static readonly int[] InsertRangeLut = new int[] { 0, 0, 8, 8, 0, 16, 8, 16, 16 };\n\n\t\tinternal static readonly int[] CopyRangeLut = new int[] { 0, 8, 0, 8, 16, 0, 16, 8, 16 };\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/RunningState.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Enumeration of decoding state-machine.</summary>\n\tinternal sealed class RunningState\n\t{\n\t\tinternal const int Uninitialized = 0;\n\n\t\tinternal const int BlockStart = 1;\n\n\t\tinternal const int CompressedBlockStart = 2;\n\n\t\tinternal const int MainLoop = 3;\n\n\t\tinternal const int ReadMetadata = 4;\n\n\t\tinternal const int CopyUncompressed = 5;\n\n\t\tinternal const int InsertLoop = 6;\n\n\t\tinternal const int CopyLoop = 7;\n\n\t\tinternal const int CopyWrapBuffer = 8;\n\n\t\tinternal const int Transform = 9;\n\n\t\tinternal const int Finished = 10;\n\n\t\tinternal const int Closed = 11;\n\n\t\tinternal const int Write = 12;\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/State.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\tinternal sealed class State\n\t{\n\t\tinternal int runningState = Org.Brotli.Dec.RunningState.Uninitialized;\n\n\t\tinternal int nextRunningState;\n\n\t\tinternal readonly Org.Brotli.Dec.BitReader br = new Org.Brotli.Dec.BitReader();\n\n\t\tinternal byte[] ringBuffer;\n\n\t\tinternal readonly int[] blockTypeTrees = new int[3 * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];\n\n\t\tinternal readonly int[] blockLenTrees = new int[3 * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];\n\n\t\tinternal int metaBlockLength;\n\n\t\tinternal bool inputEnd;\n\n\t\tinternal bool isUncompressed;\n\n\t\tinternal bool isMetadata;\n\n\t\tinternal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup0 = new Org.Brotli.Dec.HuffmanTreeGroup();\n\n\t\tinternal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup1 = new Org.Brotli.Dec.HuffmanTreeGroup();\n\n\t\tinternal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup2 = new Org.Brotli.Dec.HuffmanTreeGroup();\n\n\t\tinternal readonly int[] blockLength = new int[3];\n\n\t\tinternal readonly int[] numBlockTypes = new int[3];\n\n\t\tinternal readonly int[] blockTypeRb = new int[6];\n\n\t\tinternal readonly int[] distRb = new int[] { 16, 15, 11, 4 };\n\n\t\tinternal int pos = 0;\n\n\t\tinternal int maxDistance = 0;\n\n\t\tinternal int distRbIdx = 0;\n\n\t\tinternal bool trivialLiteralContext = false;\n\n\t\tinternal int literalTreeIndex = 0;\n\n\t\tinternal int literalTree;\n\n\t\tinternal int j;\n\n\t\tinternal int insertLength;\n\n\t\tinternal byte[] contextModes;\n\n\t\tinternal byte[] contextMap;\n\n\t\tinternal int contextMapSlice;\n\n\t\tinternal int distContextMapSlice;\n\n\t\tinternal int contextLookupOffset1;\n\n\t\tinternal int contextLookupOffset2;\n\n\t\tinternal int treeCommandOffset;\n\n\t\tinternal int distanceCode;\n\n\t\tinternal byte[] distContextMap;\n\n\t\tinternal int numDirectDistanceCodes;\n\n\t\tinternal int distancePostfixMask;\n\n\t\tinternal int distancePostfixBits;\n\n\t\tinternal int distance;\n\n\t\tinternal int copyLength;\n\n\t\tinternal int copyDst;\n\n\t\tinternal int maxBackwardDistance;\n\n\t\tinternal int maxRingBufferSize;\n\n\t\tinternal int ringBufferSize = 0;\n\n\t\tinternal long expectedTotalSize = 0;\n\n\t\tinternal byte[] customDictionary = new byte[0];\n\n\t\tinternal int bytesToIgnore = 0;\n\n\t\tinternal int outputOffset;\n\n\t\tinternal int outputLength;\n\n\t\tinternal int outputUsed;\n\n\t\tinternal int bytesWritten;\n\n\t\tinternal int bytesToWrite;\n\n\t\tinternal byte[] output;\n\n\t\t// Current meta-block header information.\n\t\t// TODO: Update to current spec.\n\t\tprivate static int DecodeWindowBits(Org.Brotli.Dec.BitReader br)\n\t\t{\n\t\t\tif (Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 0)\n\t\t\t{\n\t\t\t\treturn 16;\n\t\t\t}\n\t\t\tint n = Org.Brotli.Dec.BitReader.ReadBits(br, 3);\n\t\t\tif (n != 0)\n\t\t\t{\n\t\t\t\treturn 17 + n;\n\t\t\t}\n\t\t\tn = Org.Brotli.Dec.BitReader.ReadBits(br, 3);\n\t\t\tif (n != 0)\n\t\t\t{\n\t\t\t\treturn 8 + n;\n\t\t\t}\n\t\t\treturn 17;\n\t\t}\n\n\t\t/// <summary>Associate input with decoder state.</summary>\n\t\t/// <param name=\"state\">uninitialized state without associated input</param>\n\t\t/// <param name=\"input\">compressed data source</param>\n\t\tinternal static void SetInput(Org.Brotli.Dec.State state, System.IO.Stream input)\n\t\t{\n\t\t\tif (state.runningState != Org.Brotli.Dec.RunningState.Uninitialized)\n\t\t\t{\n\t\t\t\tthrow new System.InvalidOperationException(\"State MUST be uninitialized\");\n\t\t\t}\n\t\t\tOrg.Brotli.Dec.BitReader.Init(state.br, input);\n\t\t\tint windowBits = DecodeWindowBits(state.br);\n\t\t\tif (windowBits == 9)\n\t\t\t{\n\t\t\t\t/* Reserved case for future expansion. */\n\t\t\t\tthrow new Org.Brotli.Dec.BrotliRuntimeException(\"Invalid 'windowBits' code\");\n\t\t\t}\n\t\t\tstate.maxRingBufferSize = 1 << windowBits;\n\t\t\tstate.maxBackwardDistance = state.maxRingBufferSize - 16;\n\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.BlockStart;\n\t\t}\n\n\t\t/// <exception cref=\"System.IO.IOException\"/>\n\t\tinternal static void Close(Org.Brotli.Dec.State state)\n\t\t{\n\t\t\tif (state.runningState == Org.Brotli.Dec.RunningState.Uninitialized)\n\t\t\t{\n\t\t\t\tthrow new System.InvalidOperationException(\"State MUST be initialized\");\n\t\t\t}\n\t\t\tif (state.runningState == Org.Brotli.Dec.RunningState.Closed)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstate.runningState = Org.Brotli.Dec.RunningState.Closed;\n\t\t\tOrg.Brotli.Dec.BitReader.Close(state.br);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/Transform.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Transformations on dictionary words.</summary>\n\tinternal sealed class Transform\n\t{\n\t\tprivate readonly byte[] prefix;\n\n\t\tprivate readonly int type;\n\n\t\tprivate readonly byte[] suffix;\n\n\t\tinternal Transform(string prefix, int type, string suffix)\n\t\t{\n\t\t\tthis.prefix = ReadUniBytes(prefix);\n\t\t\tthis.type = type;\n\t\t\tthis.suffix = ReadUniBytes(suffix);\n\t\t}\n\n\t\tinternal static byte[] ReadUniBytes(string uniBytes)\n\t\t{\n\t\t\tbyte[] result = new byte[uniBytes.Length];\n\t\t\tfor (int i = 0; i < result.Length; ++i)\n\t\t\t{\n\t\t\t\tresult[i] = unchecked((byte)uniBytes[i]);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tinternal static readonly Org.Brotli.Dec.Transform[] Transforms = new Org.Brotli.Dec.Transform[] { new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, \n\t\t\tOrg.Brotli.Dec.WordTransformType.Identity, \" \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst1, string.Empty), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" the \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity\n\t\t\t, string.Empty), new Org.Brotli.Dec.Transform(\"s \", Org.Brotli.Dec.WordTransformType.Identity, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" of \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.UppercaseFirst, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" and \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst2, string.Empty), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast1, string.Empty), new Org.Brotli.Dec.Transform(\", \", Org.Brotli.Dec.WordTransformType.Identity, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity\n\t\t\t, \", \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseFirst, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" in \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.Identity, \" to \"), new Org.Brotli.Dec.Transform(\"e \", Org.Brotli.Dec.WordTransformType.Identity, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"\\\"\"), new Org.Brotli.Dec.Transform(string.Empty, \n\t\t\tOrg.Brotli.Dec.WordTransformType.Identity, \".\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"\\\">\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"\\n\"), new \n\t\t\tOrg.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast3, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"]\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.Identity, \" for \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst3, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast2, string.Empty), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" a \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" that \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseFirst\n\t\t\t, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \". \"), new Org.Brotli.Dec.Transform(\".\", Org.Brotli.Dec.WordTransformType.Identity, string.Empty), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType\n\t\t\t.Identity, \", \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst4, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" with \"), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"'\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" from \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity\n\t\t\t, \" by \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst5, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst6, string.Empty), new Org.Brotli.Dec.Transform\n\t\t\t(\" the \", Org.Brotli.Dec.WordTransformType.Identity, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast4, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.Identity, \". The \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" on \"), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" as \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" is \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast7\n\t\t\t, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast1, \"ing \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"\\n\\t\"), new Org.Brotli.Dec.Transform(string.Empty\n\t\t\t, Org.Brotli.Dec.WordTransformType.Identity, \":\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity, \". \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"ed \"), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst9, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitFirst7, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.OmitLast6, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"(\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \", \"), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast8, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" at \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.Identity, \"ly \"), new Org.Brotli.Dec.Transform(\" the \", Org.Brotli.Dec.WordTransformType.Identity, \" of \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.OmitLast5, string.Empty), new Org.Brotli.Dec.Transform(\n\t\t\tstring.Empty, Org.Brotli.Dec.WordTransformType.OmitLast9, string.Empty), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseFirst, \", \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst\n\t\t\t, \"\\\"\"), new Org.Brotli.Dec.Transform(\".\", Org.Brotli.Dec.WordTransformType.Identity, \"(\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.UppercaseFirst, \"\\\">\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"=\\\"\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity, \".\"), new Org.Brotli.Dec.Transform(\".com/\", \n\t\t\tOrg.Brotli.Dec.WordTransformType.Identity, string.Empty), new Org.Brotli.Dec.Transform(\" the \", Org.Brotli.Dec.WordTransformType.Identity, \" of the \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst\n\t\t\t, \"'\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \". This \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \",\"), new Org.Brotli.Dec.Transform(\".\", Org.Brotli.Dec.WordTransformType\n\t\t\t.Identity, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \"(\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \".\"), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \" not \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity, \"=\\\"\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"er \"\n\t\t\t), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseAll, \" \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"al \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType\n\t\t\t.UppercaseAll, string.Empty), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"='\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \"\\\"\"), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \". \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity, \"(\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \n\t\t\t\"ful \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseFirst, \". \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"ive \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.Identity, \"less \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \"'\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"est \"), new Org.Brotli.Dec.Transform\n\t\t\t(\" \", Org.Brotli.Dec.WordTransformType.UppercaseFirst, \".\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \"\\\">\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity, \"='\"\n\t\t\t), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \",\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity, \"ize \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType\n\t\t\t.UppercaseAll, \".\"), new Org.Brotli.Dec.Transform(\"\\u00c2\\u00a0\", Org.Brotli.Dec.WordTransformType.Identity, string.Empty), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.Identity, \",\"), new Org.Brotli.Dec.Transform(string.Empty\n\t\t\t, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \"=\\\"\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \"=\\\"\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.Identity\n\t\t\t, \"ous \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \", \"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseFirst, \"='\"), new Org.Brotli.Dec.Transform(\" \", \n\t\t\tOrg.Brotli.Dec.WordTransformType.UppercaseFirst, \",\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseAll, \"=\\\"\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseAll, \", \"), new Org.Brotli.Dec.Transform\n\t\t\t(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \",\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \"(\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.\n\t\t\tUppercaseAll, \". \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseAll, \".\"), new Org.Brotli.Dec.Transform(string.Empty, Org.Brotli.Dec.WordTransformType.UppercaseAll, \"='\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType\n\t\t\t.UppercaseAll, \". \"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseFirst, \"=\\\"\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType.UppercaseAll, \"='\"), new Org.Brotli.Dec.Transform(\" \", Org.Brotli.Dec.WordTransformType\n\t\t\t.UppercaseFirst, \"='\") };\n\n\t\tinternal static int TransformDictionaryWord(byte[] dst, int dstOffset, byte[] word, int wordOffset, int len, Org.Brotli.Dec.Transform transform)\n\t\t{\n\t\t\tint offset = dstOffset;\n\t\t\t// Copy prefix.\n\t\t\tbyte[] @string = transform.prefix;\n\t\t\tint tmp = @string.Length;\n\t\t\tint i = 0;\n\t\t\t// In most cases tmp < 10 -> no benefits from System.arrayCopy\n\t\t\twhile (i < tmp)\n\t\t\t{\n\t\t\t\tdst[offset++] = @string[i++];\n\t\t\t}\n\t\t\t// Copy trimmed word.\n\t\t\tint op = transform.type;\n\t\t\ttmp = Org.Brotli.Dec.WordTransformType.GetOmitFirst(op);\n\t\t\tif (tmp > len)\n\t\t\t{\n\t\t\t\ttmp = len;\n\t\t\t}\n\t\t\twordOffset += tmp;\n\t\t\tlen -= tmp;\n\t\t\tlen -= Org.Brotli.Dec.WordTransformType.GetOmitLast(op);\n\t\t\ti = len;\n\t\t\twhile (i > 0)\n\t\t\t{\n\t\t\t\tdst[offset++] = word[wordOffset++];\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif (op == Org.Brotli.Dec.WordTransformType.UppercaseAll || op == Org.Brotli.Dec.WordTransformType.UppercaseFirst)\n\t\t\t{\n\t\t\t\tint uppercaseOffset = offset - len;\n\t\t\t\tif (op == Org.Brotli.Dec.WordTransformType.UppercaseFirst)\n\t\t\t\t{\n\t\t\t\t\tlen = 1;\n\t\t\t\t}\n\t\t\t\twhile (len > 0)\n\t\t\t\t{\n\t\t\t\t\ttmp = dst[uppercaseOffset] & unchecked((int)(0xFF));\n\t\t\t\t\tif (tmp < unchecked((int)(0xc0)))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tmp >= 'a' && tmp <= 'z')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdst[uppercaseOffset] ^= unchecked((byte)32);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tuppercaseOffset += 1;\n\t\t\t\t\t\tlen -= 1;\n\t\t\t\t\t}\n\t\t\t\t\telse if (tmp < unchecked((int)(0xe0)))\n\t\t\t\t\t{\n\t\t\t\t\t\tdst[uppercaseOffset + 1] ^= unchecked((byte)32);\n\t\t\t\t\t\tuppercaseOffset += 2;\n\t\t\t\t\t\tlen -= 2;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tdst[uppercaseOffset + 2] ^= unchecked((byte)5);\n\t\t\t\t\t\tuppercaseOffset += 3;\n\t\t\t\t\t\tlen -= 3;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Copy suffix.\n\t\t\t@string = transform.suffix;\n\t\t\ttmp = @string.Length;\n\t\t\ti = 0;\n\t\t\twhile (i < tmp)\n\t\t\t{\n\t\t\t\tdst[offset++] = @string[i++];\n\t\t\t}\n\t\t\treturn offset - dstOffset;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/Utils.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>A set of utility methods.</summary>\n\tinternal sealed class Utils\n\t{\n\t\tprivate static readonly byte[] ByteZeroes = new byte[1024];\n\n\t\tprivate static readonly int[] IntZeroes = new int[1024];\n\n\t\t/// <summary>Fills byte array with zeroes.</summary>\n\t\t/// <remarks>\n\t\t/// Fills byte array with zeroes.\n\t\t/// <p> Current implementation uses\n\t\t/// <see cref=\"System.Array.Copy(object, int, object, int, int)\"/>\n\t\t/// , so it should be used for length not\n\t\t/// less than 16.\n\t\t/// </remarks>\n\t\t/// <param name=\"dest\">array to fill with zeroes</param>\n\t\t/// <param name=\"offset\">the first byte to fill</param>\n\t\t/// <param name=\"length\">number of bytes to change</param>\n\t\tinternal static void FillWithZeroes(byte[] dest, int offset, int length)\n\t\t{\n\t\t\tint cursor = 0;\n\t\t\twhile (cursor < length)\n\t\t\t{\n\t\t\t\tint step = System.Math.Min(cursor + 1024, length) - cursor;\n\t\t\t\tSystem.Array.Copy(ByteZeroes, 0, dest, offset + cursor, step);\n\t\t\t\tcursor += step;\n\t\t\t}\n\t\t}\n\n\t\t/// <summary>Fills int array with zeroes.</summary>\n\t\t/// <remarks>\n\t\t/// Fills int array with zeroes.\n\t\t/// <p> Current implementation uses\n\t\t/// <see cref=\"System.Array.Copy(object, int, object, int, int)\"/>\n\t\t/// , so it should be used for length not\n\t\t/// less than 16.\n\t\t/// </remarks>\n\t\t/// <param name=\"dest\">array to fill with zeroes</param>\n\t\t/// <param name=\"offset\">the first item to fill</param>\n\t\t/// <param name=\"length\">number of item to change</param>\n\t\tinternal static void FillWithZeroes(int[] dest, int offset, int length)\n\t\t{\n\t\t\tint cursor = 0;\n\t\t\twhile (cursor < length)\n\t\t\t{\n\t\t\t\tint step = System.Math.Min(cursor + 1024, length) - cursor;\n\t\t\t\tSystem.Array.Copy(IntZeroes, 0, dest, offset + cursor, step);\n\t\t\t\tcursor += step;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/Brotli/WordTransformType.cs",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\nDistributed under MIT license.\nSee file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\nnamespace Org.Brotli.Dec\n{\n\t/// <summary>Enumeration of all possible word transformations.</summary>\n\t/// <remarks>\n\t/// Enumeration of all possible word transformations.\n\t/// <p>There are two simple types of transforms: omit X first/last symbols, two character-case\n\t/// transforms and the identity transform.\n\t/// </remarks>\n\tinternal sealed class WordTransformType\n\t{\n\t\tinternal const int Identity = 0;\n\n\t\tinternal const int OmitLast1 = 1;\n\n\t\tinternal const int OmitLast2 = 2;\n\n\t\tinternal const int OmitLast3 = 3;\n\n\t\tinternal const int OmitLast4 = 4;\n\n\t\tinternal const int OmitLast5 = 5;\n\n\t\tinternal const int OmitLast6 = 6;\n\n\t\tinternal const int OmitLast7 = 7;\n\n\t\tinternal const int OmitLast8 = 8;\n\n\t\tinternal const int OmitLast9 = 9;\n\n\t\tinternal const int UppercaseFirst = 10;\n\n\t\tinternal const int UppercaseAll = 11;\n\n\t\tinternal const int OmitFirst1 = 12;\n\n\t\tinternal const int OmitFirst2 = 13;\n\n\t\tinternal const int OmitFirst3 = 14;\n\n\t\tinternal const int OmitFirst4 = 15;\n\n\t\tinternal const int OmitFirst5 = 16;\n\n\t\tinternal const int OmitFirst6 = 17;\n\n\t\tinternal const int OmitFirst7 = 18;\n\n\t\tinternal const int OmitFirst8 = 19;\n\n\t\tinternal const int OmitFirst9 = 20;\n\n\t\tinternal static int GetOmitFirst(int type)\n\t\t{\n\t\t\treturn type >= OmitFirst1 ? (type - OmitFirst1 + 1) : 0;\n\t\t}\n\n\t\tinternal static int GetOmitLast(int type)\n\t\t{\n\t\t\treturn type <= OmitLast9 ? (type - OmitLast1 + 1) : 0;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudio/BuildTarget.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public enum BuildTarget\n    {\n        NoTarget = -2,\n        AnyPlayer = -1,\n        ValidPlayer = 1,\n        StandaloneOSX = 2,\n        StandaloneOSXPPC = 3,\n        StandaloneOSXIntel = 4,\n        StandaloneWindows,\n        WebPlayer,\n        WebPlayerStreamed,\n        Wii = 8,\n        iOS = 9,\n        PS3,\n        XBOX360,\n        Broadcom = 12,\n        Android = 13,\n        StandaloneGLESEmu = 14,\n        StandaloneGLES20Emu = 15,\n        NaCl = 16,\n        StandaloneLinux = 17,\n        FlashPlayer = 18,\n        StandaloneWindows64 = 19,\n        WebGL,\n        WSAPlayer,\n        StandaloneLinux64 = 24,\n        StandaloneLinuxUniversal,\n        WP8Player,\n        StandaloneOSXIntel64,\n        BlackBerry,\n        Tizen,\n        PSP2,\n        PS4,\n        PSM,\n        XboxOne,\n        SamsungTV,\n        N3DS,\n        WiiU,\n        tvOS,\n        Switch,\n        Lumin,\n        Stadia,\n        CloudRendering,\n        GameCoreXboxSeries,\n        GameCoreXboxOne,\n        PS5,\n        EmbeddedLinux,\n        QNX,\n        UnknownPlatform = 9999\n    }\n}\n"
  },
  {
    "path": "AssetStudio/BuildType.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class BuildType\n    {\n        private string buildType;\n\n        public BuildType(string type)\n        {\n            buildType = type;\n        }\n\n        public bool IsAlpha => buildType == \"a\";\n        public bool IsPatch => buildType == \"p\";\n    }\n}\n"
  },
  {
    "path": "AssetStudio/BundleFile.cs",
    "content": "﻿using K4os.Compression.LZ4;\nusing System;\nusing System.IO;\nusing System.Linq;\n\nnamespace AssetStudio\n{\n    [Flags]\n    public enum ArchiveFlags\n    {\n        CompressionTypeMask = 0x3f,\n        BlocksAndDirectoryInfoCombined = 0x40,\n        BlocksInfoAtTheEnd = 0x80,\n        OldWebPluginCompatibility = 0x100,\n        BlockInfoNeedPaddingAtStart = 0x200\n    }\n\n    [Flags]\n    public enum StorageBlockFlags\n    {\n        CompressionTypeMask = 0x3f,\n        Streamed = 0x40\n    }\n\n    public enum CompressionType\n    {\n        None,\n        Lzma,\n        Lz4,\n        Lz4HC,\n        Lzham\n    }\n\n    public class BundleFile\n    {\n        public class Header\n        {\n            public string signature;\n            public uint version;\n            public string unityVersion;\n            public string unityRevision;\n            public long size;\n            public uint compressedBlocksInfoSize;\n            public uint uncompressedBlocksInfoSize;\n            public ArchiveFlags flags;\n        }\n\n        public class StorageBlock\n        {\n            public uint compressedSize;\n            public uint uncompressedSize;\n            public StorageBlockFlags flags;\n        }\n\n        public class Node\n        {\n            public long offset;\n            public long size;\n            public uint flags;\n            public string path;\n        }\n\n        public Header m_Header;\n        private StorageBlock[] m_BlocksInfo;\n        private Node[] m_DirectoryInfo;\n\n        public StreamFile[] fileList;\n\n        public BundleFile(FileReader reader)\n        {\n            m_Header = new Header();\n            m_Header.signature = reader.ReadStringToNull();\n            m_Header.version = reader.ReadUInt32();\n            m_Header.unityVersion = reader.ReadStringToNull();\n            m_Header.unityRevision = reader.ReadStringToNull();\n            switch (m_Header.signature)\n            {\n                case \"UnityArchive\":\n                    break; //TODO\n                case \"UnityWeb\":\n                case \"UnityRaw\":\n                    if (m_Header.version == 6)\n                    {\n                        goto case \"UnityFS\";\n                    }\n                    ReadHeaderAndBlocksInfo(reader);\n                    using (var blocksStream = CreateBlocksStream(reader.FullPath))\n                    {\n                        ReadBlocksAndDirectory(reader, blocksStream);\n                        ReadFiles(blocksStream, reader.FullPath);\n                    }\n                    break;\n                case \"UnityFS\":\n                    ReadHeader(reader);\n                    ReadBlocksInfoAndDirectory(reader);\n                    using (var blocksStream = CreateBlocksStream(reader.FullPath))\n                    {\n                        ReadBlocks(reader, blocksStream);\n                        ReadFiles(blocksStream, reader.FullPath);\n                    }\n                    break;\n            }\n        }\n\n        private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)\n        {\n            if (m_Header.version >= 4)\n            {\n                var hash = reader.ReadBytes(16);\n                var crc = reader.ReadUInt32();\n            }\n            var minimumStreamedBytes = reader.ReadUInt32();\n            m_Header.size = reader.ReadUInt32();\n            var numberOfLevelsToDownloadBeforeStreaming = reader.ReadUInt32();\n            var levelCount = reader.ReadInt32();\n            m_BlocksInfo = new StorageBlock[1];\n            for (int i = 0; i < levelCount; i++)\n            {\n                var storageBlock = new StorageBlock()\n                {\n                    compressedSize = reader.ReadUInt32(),\n                    uncompressedSize = reader.ReadUInt32(),\n                };\n                if (i == levelCount - 1)\n                {\n                    m_BlocksInfo[0] = storageBlock;\n                }\n            }\n            if (m_Header.version >= 2)\n            {\n                var completeFileSize = reader.ReadUInt32();\n            }\n            if (m_Header.version >= 3)\n            {\n                var fileInfoHeaderSize = reader.ReadUInt32();\n            }\n            reader.Position = m_Header.size;\n        }\n\n        private Stream CreateBlocksStream(string path)\n        {\n            Stream blocksStream;\n            var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);\n            if (uncompressedSizeSum >= int.MaxValue)\n            {\n                /*var memoryMappedFile = MemoryMappedFile.CreateNew(null, uncompressedSizeSum);\n                assetsDataStream = memoryMappedFile.CreateViewStream();*/\n                blocksStream = new FileStream(path + \".temp\", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);\n            }\n            else\n            {\n                blocksStream = new MemoryStream((int)uncompressedSizeSum);\n            }\n            return blocksStream;\n        }\n\n        private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)\n        {\n            var isCompressed = m_Header.signature == \"UnityWeb\";\n            foreach (var blockInfo in m_BlocksInfo)\n            {\n                var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);\n                if (isCompressed)\n                {\n                    using (var memoryStream = new MemoryStream(uncompressedBytes))\n                    {\n                        using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream))\n                        {\n                            uncompressedBytes = decompressStream.ToArray();\n                        }\n                    }\n                }\n                blocksStream.Write(uncompressedBytes, 0, uncompressedBytes.Length);\n            }\n            blocksStream.Position = 0;\n            var blocksReader = new EndianBinaryReader(blocksStream);\n            var nodesCount = blocksReader.ReadInt32();\n            m_DirectoryInfo = new Node[nodesCount];\n            for (int i = 0; i < nodesCount; i++)\n            {\n                m_DirectoryInfo[i] = new Node\n                {\n                    path = blocksReader.ReadStringToNull(),\n                    offset = blocksReader.ReadUInt32(),\n                    size = blocksReader.ReadUInt32()\n                };\n            }\n        }\n\n        public void ReadFiles(Stream blocksStream, string path)\n        {\n            fileList = new StreamFile[m_DirectoryInfo.Length];\n            for (int i = 0; i < m_DirectoryInfo.Length; i++)\n            {\n                var node = m_DirectoryInfo[i];\n                var file = new StreamFile();\n                fileList[i] = file;\n                file.path = node.path;\n                file.fileName = Path.GetFileName(node.path);\n                if (node.size >= int.MaxValue)\n                {\n                    /*var memoryMappedFile = MemoryMappedFile.CreateNew(null, entryinfo_size);\n                    file.stream = memoryMappedFile.CreateViewStream();*/\n                    var extractPath = path + \"_unpacked\" + Path.DirectorySeparatorChar;\n                    Directory.CreateDirectory(extractPath);\n                    file.stream = new FileStream(extractPath + file.fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);\n                }\n                else\n                {\n                    file.stream = new MemoryStream((int)node.size);\n                }\n                blocksStream.Position = node.offset;\n                blocksStream.CopyTo(file.stream, node.size);\n                file.stream.Position = 0;\n            }\n        }\n\n        private void ReadHeader(EndianBinaryReader reader)\n        {\n            m_Header.size = reader.ReadInt64();\n            m_Header.compressedBlocksInfoSize = reader.ReadUInt32();\n            m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();\n            m_Header.flags = (ArchiveFlags)reader.ReadUInt32();\n            if (m_Header.signature != \"UnityFS\")\n            {\n                reader.ReadByte();\n            }\n        }\n\n        private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader)\n        {\n            byte[] blocksInfoBytes;\n            if (m_Header.version >= 7)\n            {\n                reader.AlignStream(16);\n            }\n            if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)\n            {\n                var position = reader.Position;\n                reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;\n                blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);\n                reader.Position = position;\n            }\n            else //0x40 BlocksAndDirectoryInfoCombined\n            {\n                blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);\n            }\n            MemoryStream blocksInfoUncompresseddStream;\n            var uncompressedSize = m_Header.uncompressedBlocksInfoSize;\n            var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);\n            switch (compressionType)\n            {\n                case CompressionType.None:\n                    {\n                        blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);\n                        break;\n                    }\n                case CompressionType.Lzma:\n                    {\n                        blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));\n                        using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))\n                        {\n                            SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);\n                        }\n                        blocksInfoUncompresseddStream.Position = 0;\n                        break;\n                    }\n                case CompressionType.Lz4:\n                case CompressionType.Lz4HC:\n                    {\n                        var uncompressedBytes = new byte[uncompressedSize];\n                        var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);\n                        if (numWrite != uncompressedSize)\n                        {\n                            throw new IOException($\"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes\");\n                        }\n                        blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);\n                        break;\n                    }\n                default:\n                    throw new IOException($\"Unsupported compression type {compressionType}\");\n            }\n            using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))\n            {\n                var uncompressedDataHash = blocksInfoReader.ReadBytes(16);\n                var blocksInfoCount = blocksInfoReader.ReadInt32();\n                m_BlocksInfo = new StorageBlock[blocksInfoCount];\n                for (int i = 0; i < blocksInfoCount; i++)\n                {\n                    m_BlocksInfo[i] = new StorageBlock\n                    {\n                        uncompressedSize = blocksInfoReader.ReadUInt32(),\n                        compressedSize = blocksInfoReader.ReadUInt32(),\n                        flags = (StorageBlockFlags)blocksInfoReader.ReadUInt16()\n                    };\n                }\n\n                var nodesCount = blocksInfoReader.ReadInt32();\n                m_DirectoryInfo = new Node[nodesCount];\n                for (int i = 0; i < nodesCount; i++)\n                {\n                    m_DirectoryInfo[i] = new Node\n                    {\n                        offset = blocksInfoReader.ReadInt64(),\n                        size = blocksInfoReader.ReadInt64(),\n                        flags = blocksInfoReader.ReadUInt32(),\n                        path = blocksInfoReader.ReadStringToNull(),\n                    };\n                }\n            }\n            if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)\n            {\n                reader.AlignStream(16);\n            }\n        }\n\n        private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)\n        {\n            foreach (var blockInfo in m_BlocksInfo)\n            {\n                var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);\n                switch (compressionType)\n                {\n                    case CompressionType.None:\n                        {\n                            reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);\n                            break;\n                        }\n                    case CompressionType.Lzma:\n                        {\n                            SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);\n                            break;\n                        }\n                    case CompressionType.Lz4:\n                    case CompressionType.Lz4HC:\n                        {\n                            var compressedSize = (int)blockInfo.compressedSize;\n                            var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);\n                            reader.Read(compressedBytes, 0, compressedSize);\n                            var uncompressedSize = (int)blockInfo.uncompressedSize;\n                            var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);\n                            var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);\n                            if (numWrite != uncompressedSize)\n                            {\n                                throw new IOException($\"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes\");\n                            }\n                            blocksStream.Write(uncompressedBytes, 0, uncompressedSize);\n                            BigArrayPool<byte>.Shared.Return(compressedBytes);\n                            BigArrayPool<byte>.Shared.Return(uncompressedBytes);\n                            break;\n                        }\n                    default:\n                        throw new IOException($\"Unsupported compression type {compressionType}\");\n                }\n            }\n            blocksStream.Position = 0;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/ClassIDType.cs",
    "content": "// official Class ID Reference: https://docs.unity3d.com/Manual/ClassIDReference.html\nnamespace AssetStudio\n{\n    public enum ClassIDType\n    {\n        UnknownType = -1,\n        Object = 0,\n        GameObject = 1,\n        Component = 2,\n        LevelGameManager = 3,\n        Transform = 4,\n        TimeManager = 5,\n        GlobalGameManager = 6,\n        Behaviour = 8,\n        GameManager = 9,\n        AudioManager = 11,\n        ParticleAnimator = 12,\n        InputManager = 13,\n        EllipsoidParticleEmitter = 15,\n        Pipeline = 17,\n        EditorExtension = 18,\n        Physics2DSettings = 19,\n        Camera = 20,\n        Material = 21,\n        MeshRenderer = 23,\n        Renderer = 25,\n        ParticleRenderer = 26,\n        Texture = 27,\n        Texture2D = 28,\n        OcclusionCullingSettings = 29,\n        GraphicsSettings = 30,\n        MeshFilter = 33,\n        OcclusionPortal = 41,\n        Mesh = 43,\n        Skybox = 45,\n        QualitySettings = 47,\n        Shader = 48,\n        TextAsset = 49,\n        Rigidbody2D = 50,\n        Physics2DManager = 51,\n        Collider2D = 53,\n        Rigidbody = 54,\n        PhysicsManager = 55,\n        Collider = 56,\n        Joint = 57,\n        CircleCollider2D = 58,\n        HingeJoint = 59,\n        PolygonCollider2D = 60,\n        BoxCollider2D = 61,\n        PhysicsMaterial2D = 62,\n        MeshCollider = 64,\n        BoxCollider = 65,\n        CompositeCollider2D = 66,\n        EdgeCollider2D = 68,\n        CapsuleCollider2D = 70,\n        ComputeShader = 72,\n        AnimationClip = 74,\n        ConstantForce = 75,\n        WorldParticleCollider = 76,\n        TagManager = 78,\n        AudioListener = 81,\n        AudioSource = 82,\n        AudioClip = 83,\n        RenderTexture = 84,\n        CustomRenderTexture = 86,\n        MeshParticleEmitter = 87,\n        ParticleEmitter = 88,\n        Cubemap = 89,\n        Avatar = 90,\n        AnimatorController = 91,\n        GUILayer = 92,\n        RuntimeAnimatorController = 93,\n        ScriptMapper = 94,\n        Animator = 95,\n        TrailRenderer = 96,\n        DelayedCallManager = 98,\n        TextMesh = 102,\n        RenderSettings = 104,\n        Light = 108,\n        CGProgram = 109,\n        BaseAnimationTrack = 110,\n        Animation = 111,\n        MonoBehaviour = 114,\n        MonoScript = 115,\n        MonoManager = 116,\n        Texture3D = 117,\n        NewAnimationTrack = 118,\n        Projector = 119,\n        LineRenderer = 120,\n        Flare = 121,\n        Halo = 122,\n        LensFlare = 123,\n        FlareLayer = 124,\n        HaloLayer = 125,\n        NavMeshAreas = 126,\n        NavMeshProjectSettings = 126,\n        HaloManager = 127,\n        Font = 128,\n        PlayerSettings = 129,\n        NamedObject = 130,\n        GUITexture = 131,\n        GUIText = 132,\n        GUIElement = 133,\n        PhysicMaterial = 134,\n        SphereCollider = 135,\n        CapsuleCollider = 136,\n        SkinnedMeshRenderer = 137,\n        FixedJoint = 138,\n        RaycastCollider = 140,\n        BuildSettings = 141,\n        AssetBundle = 142,\n        CharacterController = 143,\n        CharacterJoint = 144,\n        SpringJoint = 145,\n        WheelCollider = 146,\n        ResourceManager = 147,\n        NetworkView = 148,\n        NetworkManager = 149,\n        PreloadData = 150,\n        MovieTexture = 152,\n        ConfigurableJoint = 153,\n        TerrainCollider = 154,\n        MasterServerInterface = 155,\n        TerrainData = 156,\n        LightmapSettings = 157,\n        WebCamTexture = 158,\n        EditorSettings = 159,\n        InteractiveCloth = 160,\n        ClothRenderer = 161,\n        EditorUserSettings = 162,\n        SkinnedCloth = 163,\n        AudioReverbFilter = 164,\n        AudioHighPassFilter = 165,\n        AudioChorusFilter = 166,\n        AudioReverbZone = 167,\n        AudioEchoFilter = 168,\n        AudioLowPassFilter = 169,\n        AudioDistortionFilter = 170,\n        SparseTexture = 171,\n        AudioBehaviour = 180,\n        AudioFilter = 181,\n        WindZone = 182,\n        Cloth = 183,\n        SubstanceArchive = 184,\n        ProceduralMaterial = 185,\n        ProceduralTexture = 186,\n        Texture2DArray = 187,\n        CubemapArray = 188,\n        OffMeshLink = 191,\n        OcclusionArea = 192,\n        Tree = 193,\n        NavMeshObsolete = 194,\n        NavMeshAgent = 195,\n        NavMeshSettings = 196,\n        LightProbesLegacy = 197,\n        ParticleSystem = 198,\n        ParticleSystemRenderer = 199,\n        ShaderVariantCollection = 200,\n        LODGroup = 205,\n        BlendTree = 206,\n        Motion = 207,\n        NavMeshObstacle = 208,\n        SortingGroup = 210,\n        SpriteRenderer = 212,\n        Sprite = 213,\n        CachedSpriteAtlas = 214,\n        ReflectionProbe = 215,\n        ReflectionProbes = 216,\n        Terrain = 218,\n        LightProbeGroup = 220,\n        AnimatorOverrideController = 221,\n        CanvasRenderer = 222,\n        Canvas = 223,\n        RectTransform = 224,\n        CanvasGroup = 225,\n        BillboardAsset = 226,\n        BillboardRenderer = 227,\n        SpeedTreeWindAsset = 228,\n        AnchoredJoint2D = 229,\n        Joint2D = 230,\n        SpringJoint2D = 231,\n        DistanceJoint2D = 232,\n        HingeJoint2D = 233,\n        SliderJoint2D = 234,\n        WheelJoint2D = 235,\n        ClusterInputManager = 236,\n        BaseVideoTexture = 237,\n        NavMeshData = 238,\n        AudioMixer = 240,\n        AudioMixerController = 241,\n        AudioMixerGroupController = 243,\n        AudioMixerEffectController = 244,\n        AudioMixerSnapshotController = 245,\n        PhysicsUpdateBehaviour2D = 246,\n        ConstantForce2D = 247,\n        Effector2D = 248,\n        AreaEffector2D = 249,\n        PointEffector2D = 250,\n        PlatformEffector2D = 251,\n        SurfaceEffector2D = 252,\n        BuoyancyEffector2D = 253,\n        RelativeJoint2D = 254,\n        FixedJoint2D = 255,\n        FrictionJoint2D = 256,\n        TargetJoint2D = 257,\n        LightProbes = 258,\n        LightProbeProxyVolume = 259,\n        SampleClip = 271,\n        AudioMixerSnapshot = 272,\n        AudioMixerGroup = 273,\n        NScreenBridge = 280,\n        AssetBundleManifest = 290,\n        UnityAdsManager = 292,\n        RuntimeInitializeOnLoadManager = 300,\n        CloudWebServicesManager = 301,\n        UnityAnalyticsManager = 303,\n        CrashReportManager = 304,\n        PerformanceReportingManager = 305,\n        UnityConnectSettings = 310,\n        AvatarMask = 319,\n        PlayableDirector = 320,\n        VideoPlayer = 328,\n        VideoClip = 329,\n        ParticleSystemForceField = 330,\n        SpriteMask = 331,\n        WorldAnchor = 362,\n        OcclusionCullingData = 363,\n        //kLargestRuntimeClassID = 364\n        SmallestEditorClassID = 1000,\n        PrefabInstance = 1001,\n        EditorExtensionImpl = 1002,\n        AssetImporter = 1003,\n        AssetDatabaseV1 = 1004,\n        Mesh3DSImporter = 1005,\n        TextureImporter = 1006,\n        ShaderImporter = 1007,\n        ComputeShaderImporter = 1008,\n        AudioImporter = 1020,\n        HierarchyState = 1026,\n        GUIDSerializer = 1027,\n        AssetMetaData = 1028,\n        DefaultAsset = 1029,\n        DefaultImporter = 1030,\n        TextScriptImporter = 1031,\n        SceneAsset = 1032,\n        NativeFormatImporter = 1034,\n        MonoImporter = 1035,\n        AssetServerCache = 1037,\n        LibraryAssetImporter = 1038,\n        ModelImporter = 1040,\n        FBXImporter = 1041,\n        TrueTypeFontImporter = 1042,\n        MovieImporter = 1044,\n        EditorBuildSettings = 1045,\n        DDSImporter = 1046,\n        InspectorExpandedState = 1048,\n        AnnotationManager = 1049,\n        PluginImporter = 1050,\n        EditorUserBuildSettings = 1051,\n        PVRImporter = 1052,\n        ASTCImporter = 1053,\n        KTXImporter = 1054,\n        IHVImageFormatImporter = 1055,\n        AnimatorStateTransition = 1101,\n        AnimatorState = 1102,\n        HumanTemplate = 1105,\n        AnimatorStateMachine = 1107,\n        PreviewAnimationClip = 1108,\n        AnimatorTransition = 1109,\n        SpeedTreeImporter = 1110,\n        AnimatorTransitionBase = 1111,\n        SubstanceImporter = 1112,\n        LightmapParameters = 1113,\n        LightingDataAsset = 1120,\n        GISRaster = 1121,\n        GISRasterImporter = 1122,\n        CadImporter = 1123,\n        SketchUpImporter = 1124,\n        BuildReport = 1125,\n        PackedAssets = 1126,\n        VideoClipImporter = 1127,\n        ActivationLogComponent = 2000,\n        //kLargestEditorClassID = 2001\n        //kClassIdOutOfHierarchy = 100000\n        //int = 100000,\n        //bool = 100001,\n        //float = 100002,\n        MonoObject = 100003,\n        Collision = 100004,\n        Vector3f = 100005,\n        RootMotionData = 100006,\n        Collision2D = 100007,\n        AudioMixerLiveUpdateFloat = 100008,\n        AudioMixerLiveUpdateBool = 100009,\n        Polygon2D = 100010,\n        //void = 100011,\n        TilemapCollider2D = 19719996,\n        AssetImporterLog = 41386430,\n        VFXRenderer = 73398921,\n        SerializableManagedRefTestClass = 76251197,\n        Grid = 156049354,\n        ScenesUsingAssets = 156483287,\n        ArticulationBody = 171741748,\n        Preset = 181963792,\n        EmptyObject = 277625683,\n        IConstraint = 285090594,\n        TestObjectWithSpecialLayoutOne = 293259124,\n        AssemblyDefinitionReferenceImporter = 294290339,\n        SiblingDerived = 334799969,\n        TestObjectWithSerializedMapStringNonAlignedStruct = 342846651,\n        SubDerived = 367388927,\n        AssetImportInProgressProxy = 369655926,\n        PluginBuildInfo = 382020655,\n        EditorProjectAccess = 426301858,\n        PrefabImporter = 468431735,\n        TestObjectWithSerializedArray = 478637458,\n        TestObjectWithSerializedAnimationCurve = 478637459,\n        TilemapRenderer = 483693784,\n        ScriptableCamera = 488575907,\n        SpriteAtlasAsset = 612988286,\n        SpriteAtlasDatabase = 638013454,\n        AudioBuildInfo = 641289076,\n        CachedSpriteAtlasRuntimeData = 644342135,\n        RendererFake = 646504946,\n        AssemblyDefinitionReferenceAsset = 662584278,\n        BuiltAssetBundleInfoSet = 668709126,\n        SpriteAtlas = 687078895,\n        RayTracingShaderImporter = 747330370,\n        RayTracingShader = 825902497,\n        LightingSettings = 850595691,\n        PlatformModuleSetup = 877146078,\n        VersionControlSettings = 890905787,\n        AimConstraint = 895512359,\n        VFXManager = 937362698,\n        VisualEffectSubgraph = 994735392,\n        VisualEffectSubgraphOperator = 994735403,\n        VisualEffectSubgraphBlock = 994735404,\n        LocalizationImporter = 1027052791,\n        Derived = 1091556383,\n        PropertyModificationsTargetTestObject = 1111377672,\n        ReferencesArtifactGenerator = 1114811875,\n        AssemblyDefinitionAsset = 1152215463,\n        SceneVisibilityState = 1154873562,\n        LookAtConstraint = 1183024399,\n        SpriteAtlasImporter = 1210832254,\n        MultiArtifactTestImporter = 1223240404,\n        GameObjectRecorder = 1268269756,\n        LightingDataAssetParent = 1325145578,\n        PresetManager = 1386491679,\n        TestObjectWithSpecialLayoutTwo = 1392443030,\n        StreamingManager = 1403656975,\n        LowerResBlitTexture = 1480428607,\n        StreamingController = 1542919678,\n        RenderPassAttachment = 1571458007,\n        TestObjectVectorPairStringBool = 1628831178,\n        GridLayout = 1742807556,\n        AssemblyDefinitionImporter = 1766753193,\n        ParentConstraint = 1773428102,\n        FakeComponent = 1803986026,\n        PositionConstraint = 1818360608,\n        RotationConstraint = 1818360609,\n        ScaleConstraint = 1818360610,\n        Tilemap = 1839735485,\n        PackageManifest = 1896753125,\n        PackageManifestImporter = 1896753126,\n        TerrainLayer = 1953259897,\n        SpriteShapeRenderer = 1971053207,\n        NativeObjectType = 1977754360,\n        TestObjectWithSerializedMapStringBool = 1981279845,\n        SerializableManagedHost = 1995898324,\n        VisualEffectAsset = 2058629509,\n        VisualEffectImporter = 2058629510,\n        VisualEffectResource = 2058629511,\n        VisualEffectObject = 2059678085,\n        VisualEffect = 2083052967,\n        LocalizationAsset = 2083778819,\n        ScriptedImporter = 2089858483\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Animation.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class Animation : Behaviour\n    {\n        public PPtr<AnimationClip>[] m_Animations;\n\n        public Animation(ObjectReader reader) : base(reader)\n        {\n            var m_Animation = new PPtr<AnimationClip>(reader);\n            int numAnimations = reader.ReadInt32();\n            m_Animations = new PPtr<AnimationClip>[numAnimations];\n            for (int i = 0; i < numAnimations; i++)\n            {\n                m_Animations[i] = new PPtr<AnimationClip>(reader);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/AnimationClip.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace AssetStudio\n{\n    public class Keyframe<T>\n    {\n        public float time;\n        public T value;\n        public T inSlope;\n        public T outSlope;\n        public int weightedMode;\n        public T inWeight;\n        public T outWeight;\n\n\n        public Keyframe(ObjectReader reader, Func<T> readerFunc)\n        {\n            time = reader.ReadSingle();\n            value = readerFunc();\n            inSlope = readerFunc();\n            outSlope = readerFunc();\n            if (reader.version[0] >= 2018) //2018 and up\n            {\n                weightedMode = reader.ReadInt32();\n                inWeight = readerFunc();\n                outWeight = readerFunc();\n            }\n        }\n    }\n\n    public class AnimationCurve<T>\n    {\n        public Keyframe<T>[] m_Curve;\n        public int m_PreInfinity;\n        public int m_PostInfinity;\n        public int m_RotationOrder;\n\n        public AnimationCurve(ObjectReader reader, Func<T> readerFunc)\n        {\n            var version = reader.version;\n            int numCurves = reader.ReadInt32();\n            m_Curve = new Keyframe<T>[numCurves];\n            for (int i = 0; i < numCurves; i++)\n            {\n                m_Curve[i] = new Keyframe<T>(reader, readerFunc);\n            }\n\n            m_PreInfinity = reader.ReadInt32();\n            m_PostInfinity = reader.ReadInt32();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up\n            {\n                m_RotationOrder = reader.ReadInt32();\n            }\n        }\n    }\n\n    public class QuaternionCurve\n    {\n        public AnimationCurve<Quaternion> curve;\n        public string path;\n\n        public QuaternionCurve(ObjectReader reader)\n        {\n            curve = new AnimationCurve<Quaternion>(reader, reader.ReadQuaternion);\n            path = reader.ReadAlignedString();\n        }\n    }\n\n    public class PackedFloatVector\n    {\n        public uint m_NumItems;\n        public float m_Range;\n        public float m_Start;\n        public byte[] m_Data;\n        public byte m_BitSize;\n\n        public PackedFloatVector(ObjectReader reader)\n        {\n            m_NumItems = reader.ReadUInt32();\n            m_Range = reader.ReadSingle();\n            m_Start = reader.ReadSingle();\n\n            int numData = reader.ReadInt32();\n            m_Data = reader.ReadBytes(numData);\n            reader.AlignStream();\n\n            m_BitSize = reader.ReadByte();\n            reader.AlignStream();\n        }\n\n        public float[] UnpackFloats(int itemCountInChunk, int chunkStride, int start = 0, int numChunks = -1)\n        {\n            int bitPos = m_BitSize * start;\n            int indexPos = bitPos / 8;\n            bitPos %= 8;\n\n            float scale = 1.0f / m_Range;\n            if (numChunks == -1)\n                numChunks = (int)m_NumItems / itemCountInChunk;\n            var end = chunkStride * numChunks / 4;\n            var data = new List<float>();\n            for (var index = 0; index != end; index += chunkStride / 4)\n            {\n                for (int i = 0; i < itemCountInChunk; ++i)\n                {\n                    uint x = 0;\n\n                    int bits = 0;\n                    while (bits < m_BitSize)\n                    {\n                        x |= (uint)((m_Data[indexPos] >> bitPos) << bits);\n                        int num = Math.Min(m_BitSize - bits, 8 - bitPos);\n                        bitPos += num;\n                        bits += num;\n                        if (bitPos == 8)\n                        {\n                            indexPos++;\n                            bitPos = 0;\n                        }\n                    }\n                    x &= (uint)(1 << m_BitSize) - 1u;\n                    data.Add(x / (scale * ((1 << m_BitSize) - 1)) + m_Start);\n                }\n            }\n\n            return data.ToArray();\n        }\n    }\n\n    public class PackedIntVector\n    {\n        public uint m_NumItems;\n        public byte[] m_Data;\n        public byte m_BitSize;\n\n        public PackedIntVector(ObjectReader reader)\n        {\n            m_NumItems = reader.ReadUInt32();\n\n            int numData = reader.ReadInt32();\n            m_Data = reader.ReadBytes(numData);\n            reader.AlignStream();\n\n            m_BitSize = reader.ReadByte();\n            reader.AlignStream();\n        }\n\n        public int[] UnpackInts()\n        {\n            var data = new int[m_NumItems];\n            int indexPos = 0;\n            int bitPos = 0;\n            for (int i = 0; i < m_NumItems; i++)\n            {\n                int bits = 0;\n                data[i] = 0;\n                while (bits < m_BitSize)\n                {\n                    data[i] |= (m_Data[indexPos] >> bitPos) << bits;\n                    int num = Math.Min(m_BitSize - bits, 8 - bitPos);\n                    bitPos += num;\n                    bits += num;\n                    if (bitPos == 8)\n                    {\n                        indexPos++;\n                        bitPos = 0;\n                    }\n                }\n                data[i] &= (1 << m_BitSize) - 1;\n            }\n            return data;\n        }\n    }\n\n    public class PackedQuatVector\n    {\n        public uint m_NumItems;\n        public byte[] m_Data;\n\n        public PackedQuatVector(ObjectReader reader)\n        {\n            m_NumItems = reader.ReadUInt32();\n\n            int numData = reader.ReadInt32();\n            m_Data = reader.ReadBytes(numData);\n\n            reader.AlignStream();\n        }\n\n        public Quaternion[] UnpackQuats()\n        {\n            var data = new Quaternion[m_NumItems];\n            int indexPos = 0;\n            int bitPos = 0;\n\n            for (int i = 0; i < m_NumItems; i++)\n            {\n                uint flags = 0;\n\n                int bits = 0;\n                while (bits < 3)\n                {\n                    flags |= (uint)((m_Data[indexPos] >> bitPos) << bits);\n                    int num = Math.Min(3 - bits, 8 - bitPos);\n                    bitPos += num;\n                    bits += num;\n                    if (bitPos == 8)\n                    {\n                        indexPos++;\n                        bitPos = 0;\n                    }\n                }\n                flags &= 7;\n\n\n                var q = new Quaternion();\n                float sum = 0;\n                for (int j = 0; j < 4; j++)\n                {\n                    if ((flags & 3) != j)\n                    {\n                        int bitSize = ((flags & 3) + 1) % 4 == j ? 9 : 10;\n                        uint x = 0;\n\n                        bits = 0;\n                        while (bits < bitSize)\n                        {\n                            x |= (uint)((m_Data[indexPos] >> bitPos) << bits);\n                            int num = Math.Min(bitSize - bits, 8 - bitPos);\n                            bitPos += num;\n                            bits += num;\n                            if (bitPos == 8)\n                            {\n                                indexPos++;\n                                bitPos = 0;\n                            }\n                        }\n                        x &= (uint)((1 << bitSize) - 1);\n                        q[j] = x / (0.5f * ((1 << bitSize) - 1)) - 1;\n                        sum += q[j] * q[j];\n                    }\n                }\n\n                int lastComponent = (int)(flags & 3);\n                q[lastComponent] = (float)Math.Sqrt(1 - sum);\n                if ((flags & 4) != 0u)\n                    q[lastComponent] = -q[lastComponent];\n                data[i] = q;\n            }\n\n            return data;\n        }\n    }\n\n    public class CompressedAnimationCurve\n    {\n        public string m_Path;\n        public PackedIntVector m_Times;\n        public PackedQuatVector m_Values;\n        public PackedFloatVector m_Slopes;\n        public int m_PreInfinity;\n        public int m_PostInfinity;\n\n        public CompressedAnimationCurve(ObjectReader reader)\n        {\n            m_Path = reader.ReadAlignedString();\n            m_Times = new PackedIntVector(reader);\n            m_Values = new PackedQuatVector(reader);\n            m_Slopes = new PackedFloatVector(reader);\n            m_PreInfinity = reader.ReadInt32();\n            m_PostInfinity = reader.ReadInt32();\n        }\n    }\n\n    public class Vector3Curve\n    {\n        public AnimationCurve<Vector3> curve;\n        public string path;\n\n        public Vector3Curve(ObjectReader reader)\n        {\n            curve = new AnimationCurve<Vector3>(reader, reader.ReadVector3);\n            path = reader.ReadAlignedString();\n        }\n    }\n\n    public class FloatCurve\n    {\n        public AnimationCurve<float> curve;\n        public string attribute;\n        public string path;\n        public ClassIDType classID;\n        public PPtr<MonoScript> script;\n\n\n        public FloatCurve(ObjectReader reader)\n        {\n            curve = new AnimationCurve<float>(reader, reader.ReadSingle);\n            attribute = reader.ReadAlignedString();\n            path = reader.ReadAlignedString();\n            classID = (ClassIDType)reader.ReadInt32();\n            script = new PPtr<MonoScript>(reader);\n        }\n    }\n\n    public class PPtrKeyframe\n    {\n        public float time;\n        public PPtr<Object> value;\n\n\n        public PPtrKeyframe(ObjectReader reader)\n        {\n            time = reader.ReadSingle();\n            value = new PPtr<Object>(reader);\n        }\n    }\n\n    public class PPtrCurve\n    {\n        public PPtrKeyframe[] curve;\n        public string attribute;\n        public string path;\n        public int classID;\n        public PPtr<MonoScript> script;\n\n\n        public PPtrCurve(ObjectReader reader)\n        {\n            int numCurves = reader.ReadInt32();\n            curve = new PPtrKeyframe[numCurves];\n            for (int i = 0; i < numCurves; i++)\n            {\n                curve[i] = new PPtrKeyframe(reader);\n            }\n\n            attribute = reader.ReadAlignedString();\n            path = reader.ReadAlignedString();\n            classID = reader.ReadInt32();\n            script = new PPtr<MonoScript>(reader);\n        }\n    }\n\n    public class AABB\n    {\n        public Vector3 m_Center;\n        public Vector3 m_Extent;\n\n        public AABB(ObjectReader reader)\n        {\n            m_Center = reader.ReadVector3();\n            m_Extent = reader.ReadVector3();\n        }\n    }\n\n    public class xform\n    {\n        public Vector3 t;\n        public Quaternion q;\n        public Vector3 s;\n\n        public xform(ObjectReader reader)\n        {\n            var version = reader.version;\n            t = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up\n            q = reader.ReadQuaternion();\n            s = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up\n        }\n    }\n\n    public class HandPose\n    {\n        public xform m_GrabX;\n        public float[] m_DoFArray;\n        public float m_Override;\n        public float m_CloseOpen;\n        public float m_InOut;\n        public float m_Grab;\n\n        public HandPose(ObjectReader reader)\n        {\n            m_GrabX = new xform(reader);\n            m_DoFArray = reader.ReadSingleArray();\n            m_Override = reader.ReadSingle();\n            m_CloseOpen = reader.ReadSingle();\n            m_InOut = reader.ReadSingle();\n            m_Grab = reader.ReadSingle();\n        }\n    }\n\n    public class HumanGoal\n    {\n        public xform m_X;\n        public float m_WeightT;\n        public float m_WeightR;\n        public Vector3 m_HintT;\n        public float m_HintWeightT;\n\n        public HumanGoal(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_X = new xform(reader);\n            m_WeightT = reader.ReadSingle();\n            m_WeightR = reader.ReadSingle();\n            if (version[0] >= 5)//5.0 and up\n            {\n                m_HintT = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up\n                m_HintWeightT = reader.ReadSingle();\n            }\n        }\n    }\n\n    public class HumanPose\n    {\n        public xform m_RootX;\n        public Vector3 m_LookAtPosition;\n        public Vector4 m_LookAtWeight;\n        public HumanGoal[] m_GoalArray;\n        public HandPose m_LeftHandPose;\n        public HandPose m_RightHandPose;\n        public float[] m_DoFArray;\n        public Vector3[] m_TDoFArray;\n\n        public HumanPose(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_RootX = new xform(reader);\n            m_LookAtPosition = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up\n            m_LookAtWeight = reader.ReadVector4();\n\n            int numGoals = reader.ReadInt32();\n            m_GoalArray = new HumanGoal[numGoals];\n            for (int i = 0; i < numGoals; i++)\n            {\n                m_GoalArray[i] = new HumanGoal(reader);\n            }\n\n            m_LeftHandPose = new HandPose(reader);\n            m_RightHandPose = new HandPose(reader);\n\n            m_DoFArray = reader.ReadSingleArray();\n\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 2))//5.2 and up\n            {\n                int numTDof = reader.ReadInt32();\n                m_TDoFArray = new Vector3[numTDof];\n                for (int i = 0; i < numTDof; i++)\n                {\n                    m_TDoFArray[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up\n                }\n            }\n        }\n    }\n\n    public class StreamedClip\n    {\n        public uint[] data;\n        public uint curveCount;\n\n        public StreamedClip(ObjectReader reader)\n        {\n            data = reader.ReadUInt32Array();\n            curveCount = reader.ReadUInt32();\n        }\n\n        public class StreamedCurveKey\n        {\n            public int index;\n            public float[] coeff;\n\n            public float value;\n            public float outSlope;\n            public float inSlope;\n\n            public StreamedCurveKey(BinaryReader reader)\n            {\n                index = reader.ReadInt32();\n                coeff = reader.ReadSingleArray(4);\n\n                outSlope = coeff[2];\n                value = coeff[3];\n            }\n\n            public float CalculateNextInSlope(float dx, StreamedCurveKey rhs)\n            {\n                //Stepped\n                if (coeff[0] == 0f && coeff[1] == 0f && coeff[2] == 0f)\n                {\n                    return float.PositiveInfinity;\n                }\n\n                dx = Math.Max(dx, 0.0001f);\n                var dy = rhs.value - value;\n                var length = 1.0f / (dx * dx);\n                var d1 = outSlope * dx;\n                var d2 = dy + dy + dy - d1 - d1 - coeff[1] / length;\n                return d2 / dx;\n            }\n        }\n\n        public class StreamedFrame\n        {\n            public float time;\n            public StreamedCurveKey[] keyList;\n\n            public StreamedFrame(BinaryReader reader)\n            {\n                time = reader.ReadSingle();\n\n                int numKeys = reader.ReadInt32();\n                keyList = new StreamedCurveKey[numKeys];\n                for (int i = 0; i < numKeys; i++)\n                {\n                    keyList[i] = new StreamedCurveKey(reader);\n                }\n            }\n        }\n\n        public List<StreamedFrame> ReadData()\n        {\n            var frameList = new List<StreamedFrame>();\n            var buffer = new byte[data.Length * 4];\n            Buffer.BlockCopy(data, 0, buffer, 0, buffer.Length);\n            using (var reader = new BinaryReader(new MemoryStream(buffer)))\n            {\n                while (reader.BaseStream.Position < reader.BaseStream.Length)\n                {\n                    frameList.Add(new StreamedFrame(reader));\n                }\n            }\n\n            for (int frameIndex = 2; frameIndex < frameList.Count - 1; frameIndex++)\n            {\n                var frame = frameList[frameIndex];\n                foreach (var curveKey in frame.keyList)\n                {\n                    for (int i = frameIndex - 1; i >= 0; i--)\n                    {\n                        var preFrame = frameList[i];\n                        var preCurveKey = preFrame.keyList.FirstOrDefault(x => x.index == curveKey.index);\n                        if (preCurveKey != null)\n                        {\n                            curveKey.inSlope = preCurveKey.CalculateNextInSlope(frame.time - preFrame.time, curveKey);\n                            break;\n                        }\n                    }\n                }\n            }\n            return frameList;\n        }\n    }\n\n    public class DenseClip\n    {\n        public int m_FrameCount;\n        public uint m_CurveCount;\n        public float m_SampleRate;\n        public float m_BeginTime;\n        public float[] m_SampleArray;\n\n        public DenseClip(ObjectReader reader)\n        {\n            m_FrameCount = reader.ReadInt32();\n            m_CurveCount = reader.ReadUInt32();\n            m_SampleRate = reader.ReadSingle();\n            m_BeginTime = reader.ReadSingle();\n            m_SampleArray = reader.ReadSingleArray();\n        }\n    }\n\n    public class ConstantClip\n    {\n        public float[] data;\n\n        public ConstantClip(ObjectReader reader)\n        {\n            data = reader.ReadSingleArray();\n        }\n    }\n\n    public class ValueConstant\n    {\n        public uint m_ID;\n        public uint m_TypeID;\n        public uint m_Type;\n        public uint m_Index;\n\n        public ValueConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_ID = reader.ReadUInt32();\n            if (version[0] < 5 || (version[0] == 5 && version[1] < 5))//5.5 down\n            {\n                m_TypeID = reader.ReadUInt32();\n            }\n            m_Type = reader.ReadUInt32();\n            m_Index = reader.ReadUInt32();\n        }\n    }\n\n    public class ValueArrayConstant\n    {\n        public ValueConstant[] m_ValueArray;\n\n        public ValueArrayConstant(ObjectReader reader)\n        {\n            int numVals = reader.ReadInt32();\n            m_ValueArray = new ValueConstant[numVals];\n            for (int i = 0; i < numVals; i++)\n            {\n                m_ValueArray[i] = new ValueConstant(reader);\n            }\n        }\n    }\n\n    public class Clip\n    {\n        public StreamedClip m_StreamedClip;\n        public DenseClip m_DenseClip;\n        public ConstantClip m_ConstantClip;\n        public ValueArrayConstant m_Binding;\n\n        public Clip(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_StreamedClip = new StreamedClip(reader);\n            m_DenseClip = new DenseClip(reader);\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_ConstantClip = new ConstantClip(reader);\n            }\n            if (version[0] < 2018 || (version[0] == 2018 && version[1] < 3)) //2018.3 down\n            {\n                m_Binding = new ValueArrayConstant(reader);\n            }\n        }\n\n        public AnimationClipBindingConstant ConvertValueArrayToGenericBinding()\n        {\n            var bindings = new AnimationClipBindingConstant();\n            var genericBindings = new List<GenericBinding>();\n            var values = m_Binding;\n            for (int i = 0; i < values.m_ValueArray.Length;)\n            {\n                var curveID = values.m_ValueArray[i].m_ID;\n                var curveTypeID = values.m_ValueArray[i].m_TypeID;\n                var binding = new GenericBinding();\n                genericBindings.Add(binding);\n                if (curveTypeID == 4174552735) //CRC(PositionX))\n                {\n                    binding.path = curveID;\n                    binding.attribute = 1; //kBindTransformPosition\n                    binding.typeID = ClassIDType.Transform;\n                    i += 3;\n                }\n                else if (curveTypeID == 2211994246) //CRC(QuaternionX))\n                {\n                    binding.path = curveID;\n                    binding.attribute = 2; //kBindTransformRotation\n                    binding.typeID = ClassIDType.Transform;\n                    i += 4;\n                }\n                else if (curveTypeID == 1512518241) //CRC(ScaleX))\n                {\n                    binding.path = curveID;\n                    binding.attribute = 3; //kBindTransformScale\n                    binding.typeID = ClassIDType.Transform;\n                    i += 3;\n                }\n                else\n                {\n                    binding.typeID = ClassIDType.Animator;\n                    binding.path = 0;\n                    binding.attribute = curveID;\n                    i++;\n                }\n            }\n            bindings.genericBindings = genericBindings.ToArray();\n            return bindings;\n        }\n    }\n\n    public class ValueDelta\n    {\n        public float m_Start;\n        public float m_Stop;\n\n        public ValueDelta(ObjectReader reader)\n        {\n            m_Start = reader.ReadSingle();\n            m_Stop = reader.ReadSingle();\n        }\n    }\n\n    public class ClipMuscleConstant\n    {\n        public HumanPose m_DeltaPose;\n        public xform m_StartX;\n        public xform m_StopX;\n        public xform m_LeftFootStartX;\n        public xform m_RightFootStartX;\n        public xform m_MotionStartX;\n        public xform m_MotionStopX;\n        public Vector3 m_AverageSpeed;\n        public Clip m_Clip;\n        public float m_StartTime;\n        public float m_StopTime;\n        public float m_OrientationOffsetY;\n        public float m_Level;\n        public float m_CycleOffset;\n        public float m_AverageAngularSpeed;\n        public int[] m_IndexArray;\n        public ValueDelta[] m_ValueArrayDelta;\n        public float[] m_ValueArrayReferencePose;\n        public bool m_Mirror;\n        public bool m_LoopTime;\n        public bool m_LoopBlend;\n        public bool m_LoopBlendOrientation;\n        public bool m_LoopBlendPositionY;\n        public bool m_LoopBlendPositionXZ;\n        public bool m_StartAtOrigin;\n        public bool m_KeepOriginalOrientation;\n        public bool m_KeepOriginalPositionY;\n        public bool m_KeepOriginalPositionXZ;\n        public bool m_HeightFromFeet;\n\n        public ClipMuscleConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_DeltaPose = new HumanPose(reader);\n            m_StartX = new xform(reader);\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up\n            {\n                m_StopX = new xform(reader);\n            }\n            m_LeftFootStartX = new xform(reader);\n            m_RightFootStartX = new xform(reader);\n            if (version[0] < 5)//5.0 down\n            {\n                m_MotionStartX = new xform(reader);\n                m_MotionStopX = new xform(reader);\n            }\n            m_AverageSpeed = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up\n            m_Clip = new Clip(reader);\n            m_StartTime = reader.ReadSingle();\n            m_StopTime = reader.ReadSingle();\n            m_OrientationOffsetY = reader.ReadSingle();\n            m_Level = reader.ReadSingle();\n            m_CycleOffset = reader.ReadSingle();\n            m_AverageAngularSpeed = reader.ReadSingle();\n\n            m_IndexArray = reader.ReadInt32Array();\n            if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down\n            {\n                var m_AdditionalCurveIndexArray = reader.ReadInt32Array();\n            }\n            int numDeltas = reader.ReadInt32();\n            m_ValueArrayDelta = new ValueDelta[numDeltas];\n            for (int i = 0; i < numDeltas; i++)\n            {\n                m_ValueArrayDelta[i] = new ValueDelta(reader);\n            }\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up\n            {\n                m_ValueArrayReferencePose = reader.ReadSingleArray();\n            }\n\n            m_Mirror = reader.ReadBoolean();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_LoopTime = reader.ReadBoolean();\n            }\n            m_LoopBlend = reader.ReadBoolean();\n            m_LoopBlendOrientation = reader.ReadBoolean();\n            m_LoopBlendPositionY = reader.ReadBoolean();\n            m_LoopBlendPositionXZ = reader.ReadBoolean();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up\n            {\n                m_StartAtOrigin = reader.ReadBoolean();\n            }\n            m_KeepOriginalOrientation = reader.ReadBoolean();\n            m_KeepOriginalPositionY = reader.ReadBoolean();\n            m_KeepOriginalPositionXZ = reader.ReadBoolean();\n            m_HeightFromFeet = reader.ReadBoolean();\n            reader.AlignStream();\n        }\n    }\n\n    public class GenericBinding\n    {\n        public uint path;\n        public uint attribute;\n        public PPtr<Object> script;\n        public ClassIDType typeID;\n        public byte customType;\n        public byte isPPtrCurve;\n        public byte isIntCurve;\n\n        public GenericBinding() { }\n\n        public GenericBinding(ObjectReader reader)\n        {\n            var version = reader.version;\n            path = reader.ReadUInt32();\n            attribute = reader.ReadUInt32();\n            script = new PPtr<Object>(reader);\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up\n            {\n                typeID = (ClassIDType)reader.ReadInt32();\n            }\n            else\n            {\n                typeID = (ClassIDType)reader.ReadUInt16();\n            }\n            customType = reader.ReadByte();\n            isPPtrCurve = reader.ReadByte();\n            if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up\n            {\n                isIntCurve = reader.ReadByte();\n            }\n            reader.AlignStream();\n        }\n    }\n\n    public class AnimationClipBindingConstant\n    {\n        public GenericBinding[] genericBindings;\n        public PPtr<Object>[] pptrCurveMapping;\n\n        public AnimationClipBindingConstant() { }\n\n        public AnimationClipBindingConstant(ObjectReader reader)\n        {\n            int numBindings = reader.ReadInt32();\n            genericBindings = new GenericBinding[numBindings];\n            for (int i = 0; i < numBindings; i++)\n            {\n                genericBindings[i] = new GenericBinding(reader);\n            }\n\n            int numMappings = reader.ReadInt32();\n            pptrCurveMapping = new PPtr<Object>[numMappings];\n            for (int i = 0; i < numMappings; i++)\n            {\n                pptrCurveMapping[i] = new PPtr<Object>(reader);\n            }\n        }\n\n        public GenericBinding FindBinding(int index)\n        {\n            int curves = 0;\n            foreach (var b in genericBindings)\n            {\n                if (b.typeID == ClassIDType.Transform)\n                {\n                    switch (b.attribute)\n                    {\n                        case 1: //kBindTransformPosition\n                        case 3: //kBindTransformScale\n                        case 4: //kBindTransformEuler\n                            curves += 3;\n                            break;\n                        case 2: //kBindTransformRotation\n                            curves += 4;\n                            break;\n                        default:\n                            curves += 1;\n                            break;\n                    }\n                }\n                else\n                {\n                    curves += 1;\n                }\n                if (curves > index)\n                {\n                    return b;\n                }\n            }\n\n            return null;\n        }\n    }\n\n    public class AnimationEvent\n    {\n        public float time;\n        public string functionName;\n        public string data;\n        public PPtr<Object> objectReferenceParameter;\n        public float floatParameter;\n        public int intParameter;\n        public int messageOptions;\n\n        public AnimationEvent(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            time = reader.ReadSingle();\n            functionName = reader.ReadAlignedString();\n            data = reader.ReadAlignedString();\n            objectReferenceParameter = new PPtr<Object>(reader);\n            floatParameter = reader.ReadSingle();\n            if (version[0] >= 3) //3 and up\n            {\n                intParameter = reader.ReadInt32();\n            }\n            messageOptions = reader.ReadInt32();\n        }\n    }\n\n    public enum AnimationType\n    {\n        Legacy = 1,\n        Generic = 2,\n        Humanoid = 3\n    };\n\n    public sealed class AnimationClip : NamedObject\n    {\n        public AnimationType m_AnimationType;\n        public bool m_Legacy;\n        public bool m_Compressed;\n        public bool m_UseHighQualityCurve;\n        public QuaternionCurve[] m_RotationCurves;\n        public CompressedAnimationCurve[] m_CompressedRotationCurves;\n        public Vector3Curve[] m_EulerCurves;\n        public Vector3Curve[] m_PositionCurves;\n        public Vector3Curve[] m_ScaleCurves;\n        public FloatCurve[] m_FloatCurves;\n        public PPtrCurve[] m_PPtrCurves;\n        public float m_SampleRate;\n        public int m_WrapMode;\n        public AABB m_Bounds;\n        public uint m_MuscleClipSize;\n        public ClipMuscleConstant m_MuscleClip;\n        public AnimationClipBindingConstant m_ClipBindingConstant;\n        public AnimationEvent[] m_Events;\n\n\n        public AnimationClip(ObjectReader reader) : base(reader)\n        {\n            if (version[0] >= 5)//5.0 and up\n            {\n                m_Legacy = reader.ReadBoolean();\n            }\n            else if (version[0] >= 4)//4.0 and up\n            {\n                m_AnimationType = (AnimationType)reader.ReadInt32();\n                if (m_AnimationType == AnimationType.Legacy)\n                    m_Legacy = true;\n            }\n            else\n            {\n                m_Legacy = true;\n            }\n            m_Compressed = reader.ReadBoolean();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3))//4.3 and up\n            {\n                m_UseHighQualityCurve = reader.ReadBoolean();\n            }\n            reader.AlignStream();\n            int numRCurves = reader.ReadInt32();\n            m_RotationCurves = new QuaternionCurve[numRCurves];\n            for (int i = 0; i < numRCurves; i++)\n            {\n                m_RotationCurves[i] = new QuaternionCurve(reader);\n            }\n\n            int numCRCurves = reader.ReadInt32();\n            m_CompressedRotationCurves = new CompressedAnimationCurve[numCRCurves];\n            for (int i = 0; i < numCRCurves; i++)\n            {\n                m_CompressedRotationCurves[i] = new CompressedAnimationCurve(reader);\n            }\n\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up\n            {\n                int numEulerCurves = reader.ReadInt32();\n                m_EulerCurves = new Vector3Curve[numEulerCurves];\n                for (int i = 0; i < numEulerCurves; i++)\n                {\n                    m_EulerCurves[i] = new Vector3Curve(reader);\n                }\n            }\n\n            int numPCurves = reader.ReadInt32();\n            m_PositionCurves = new Vector3Curve[numPCurves];\n            for (int i = 0; i < numPCurves; i++)\n            {\n                m_PositionCurves[i] = new Vector3Curve(reader);\n            }\n\n            int numSCurves = reader.ReadInt32();\n            m_ScaleCurves = new Vector3Curve[numSCurves];\n            for (int i = 0; i < numSCurves; i++)\n            {\n                m_ScaleCurves[i] = new Vector3Curve(reader);\n            }\n\n            int numFCurves = reader.ReadInt32();\n            m_FloatCurves = new FloatCurve[numFCurves];\n            for (int i = 0; i < numFCurves; i++)\n            {\n                m_FloatCurves[i] = new FloatCurve(reader);\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                int numPtrCurves = reader.ReadInt32();\n                m_PPtrCurves = new PPtrCurve[numPtrCurves];\n                for (int i = 0; i < numPtrCurves; i++)\n                {\n                    m_PPtrCurves[i] = new PPtrCurve(reader);\n                }\n            }\n\n            m_SampleRate = reader.ReadSingle();\n            m_WrapMode = reader.ReadInt32();\n            if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up\n            {\n                m_Bounds = new AABB(reader);\n            }\n            if (version[0] >= 4)//4.0 and up\n            {\n                m_MuscleClipSize = reader.ReadUInt32();\n                m_MuscleClip = new ClipMuscleConstant(reader);\n            }\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_ClipBindingConstant = new AnimationClipBindingConstant(reader);\n            }\n            if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up\n            {\n                var m_HasGenericRootTransform = reader.ReadBoolean();\n                var m_HasMotionFloatCurves = reader.ReadBoolean();\n                reader.AlignStream();\n            }\n            int numEvents = reader.ReadInt32();\n            m_Events = new AnimationEvent[numEvents];\n            for (int i = 0; i < numEvents; i++)\n            {\n                m_Events[i] = new AnimationEvent(reader);\n            }\n            if (version[0] >= 2017) //2017 and up\n            {\n                reader.AlignStream();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Animator.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class Animator : Behaviour\n    {\n        public PPtr<Avatar> m_Avatar;\n        public PPtr<RuntimeAnimatorController> m_Controller;\n        public bool m_HasTransformHierarchy = true;\n\n        public Animator(ObjectReader reader) : base(reader)\n        {\n            m_Avatar = new PPtr<Avatar>(reader);\n            m_Controller = new PPtr<RuntimeAnimatorController>(reader);\n            var m_CullingMode = reader.ReadInt32();\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up\n            {\n                var m_UpdateMode = reader.ReadInt32();\n            }\n\n            var m_ApplyRootMotion = reader.ReadBoolean();\n            if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down\n            {\n                reader.AlignStream();\n            }\n\n            if (version[0] >= 5) //5.0 and up\n            {\n                var m_LinearVelocityBlending = reader.ReadBoolean();\n                if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up\n                {\n                    var m_StabilizeFeet = reader.ReadBoolean();\n                }\n                reader.AlignStream();\n            }\n\n            if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down\n            {\n                var m_AnimatePhysics = reader.ReadBoolean();\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_HasTransformHierarchy = reader.ReadBoolean();\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up\n            {\n                var m_AllowConstantClipSamplingOptimization = reader.ReadBoolean();\n            }\n            if (version[0] >= 5 && version[0] < 2018) //5.0 and up - 2018 down\n            {\n                reader.AlignStream();\n            }\n\n            if (version[0] >= 2018) //2018 and up\n            {\n                var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();\n                reader.AlignStream();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/AnimatorController.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class HumanPoseMask\n    {\n        public uint word0;\n        public uint word1;\n        public uint word2;\n\n        public HumanPoseMask(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            word0 = reader.ReadUInt32();\n            word1 = reader.ReadUInt32();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up\n            {\n                word2 = reader.ReadUInt32();\n            }\n        }\n    }\n\n    public class SkeletonMaskElement\n    {\n        public uint m_PathHash;\n        public float m_Weight;\n\n        public SkeletonMaskElement(ObjectReader reader)\n        {\n            m_PathHash = reader.ReadUInt32();\n            m_Weight = reader.ReadSingle();\n        }\n    }\n\n    public class SkeletonMask\n    {\n        public SkeletonMaskElement[] m_Data;\n\n        public SkeletonMask(ObjectReader reader)\n        {\n            int numElements = reader.ReadInt32();\n            m_Data = new SkeletonMaskElement[numElements];\n            for (int i = 0; i < numElements; i++)\n            {\n                m_Data[i] = new SkeletonMaskElement(reader);\n            }\n        }\n    }\n\n    public class LayerConstant\n    {\n        public uint m_StateMachineIndex;\n        public uint m_StateMachineMotionSetIndex;\n        public HumanPoseMask m_BodyMask;\n        public SkeletonMask m_SkeletonMask;\n        public uint m_Binding;\n        public int m_LayerBlendingMode;\n        public float m_DefaultWeight;\n        public bool m_IKPass;\n        public bool m_SyncedLayerAffectsTiming;\n\n        public LayerConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_StateMachineIndex = reader.ReadUInt32();\n            m_StateMachineMotionSetIndex = reader.ReadUInt32();\n            m_BodyMask = new HumanPoseMask(reader);\n            m_SkeletonMask = new SkeletonMask(reader);\n            m_Binding = reader.ReadUInt32();\n            m_LayerBlendingMode = reader.ReadInt32();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up\n            {\n                m_DefaultWeight = reader.ReadSingle();\n            }\n            m_IKPass = reader.ReadBoolean();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up\n            {\n                m_SyncedLayerAffectsTiming = reader.ReadBoolean();\n            }\n            reader.AlignStream();\n        }\n    }\n\n    public class ConditionConstant\n    {\n        public uint m_ConditionMode;\n        public uint m_EventID;\n        public float m_EventThreshold;\n        public float m_ExitTime;\n\n        public ConditionConstant(ObjectReader reader)\n        {\n            m_ConditionMode = reader.ReadUInt32();\n            m_EventID = reader.ReadUInt32();\n            m_EventThreshold = reader.ReadSingle();\n            m_ExitTime = reader.ReadSingle();\n        }\n    }\n\n    public class TransitionConstant\n    {\n        public ConditionConstant[] m_ConditionConstantArray;\n        public uint m_DestinationState;\n        public uint m_FullPathID;\n        public uint m_ID;\n        public uint m_UserID;\n        public float m_TransitionDuration;\n        public float m_TransitionOffset;\n        public float m_ExitTime;\n        public bool m_HasExitTime;\n        public bool m_HasFixedDuration;\n        public int m_InterruptionSource;\n        public bool m_OrderedInterruption;\n        public bool m_Atomic;\n        public bool m_CanTransitionToSelf;\n\n        public TransitionConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            int numConditions = reader.ReadInt32();\n            m_ConditionConstantArray = new ConditionConstant[numConditions];\n            for (int i = 0; i < numConditions; i++)\n            {\n                m_ConditionConstantArray[i] = new ConditionConstant(reader);\n            }\n\n            m_DestinationState = reader.ReadUInt32();\n            if (version[0] >= 5) //5.0 and up\n            {\n                m_FullPathID = reader.ReadUInt32();\n            }\n\n            m_ID = reader.ReadUInt32();\n            m_UserID = reader.ReadUInt32();\n            m_TransitionDuration = reader.ReadSingle();\n            m_TransitionOffset = reader.ReadSingle();\n            if (version[0] >= 5) //5.0 and up\n            {\n                m_ExitTime = reader.ReadSingle();\n                m_HasExitTime = reader.ReadBoolean();\n                m_HasFixedDuration = reader.ReadBoolean();\n                reader.AlignStream();\n                m_InterruptionSource = reader.ReadInt32();\n                m_OrderedInterruption = reader.ReadBoolean();\n            }\n            else\n            {\n                m_Atomic = reader.ReadBoolean();\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up\n            {\n                m_CanTransitionToSelf = reader.ReadBoolean();\n            }\n\n            reader.AlignStream();\n        }\n    }\n\n    public class LeafInfoConstant\n    {\n        public uint[] m_IDArray;\n        public uint m_IndexOffset;\n\n        public LeafInfoConstant(ObjectReader reader)\n        {\n            m_IDArray = reader.ReadUInt32Array();\n            m_IndexOffset = reader.ReadUInt32();\n        }\n    }\n\n    public class MotionNeighborList\n    {\n        public uint[] m_NeighborArray;\n\n        public MotionNeighborList(ObjectReader reader)\n        {\n            m_NeighborArray = reader.ReadUInt32Array();\n        }\n    }\n\n    public class Blend2dDataConstant\n    {\n        public Vector2[] m_ChildPositionArray;\n        public float[] m_ChildMagnitudeArray;\n        public Vector2[] m_ChildPairVectorArray;\n        public float[] m_ChildPairAvgMagInvArray;\n        public MotionNeighborList[] m_ChildNeighborListArray;\n\n        public Blend2dDataConstant(ObjectReader reader)\n        {\n            m_ChildPositionArray = reader.ReadVector2Array();\n            m_ChildMagnitudeArray = reader.ReadSingleArray();\n            m_ChildPairVectorArray = reader.ReadVector2Array();\n            m_ChildPairAvgMagInvArray = reader.ReadSingleArray();\n\n            int numNeighbours = reader.ReadInt32();\n            m_ChildNeighborListArray = new MotionNeighborList[numNeighbours];\n            for (int i = 0; i < numNeighbours; i++)\n            {\n                m_ChildNeighborListArray[i] = new MotionNeighborList(reader);\n            }\n        }\n    }\n\n    public class Blend1dDataConstant // wrong labeled\n    {\n        public float[] m_ChildThresholdArray;\n\n        public Blend1dDataConstant(ObjectReader reader)\n        {\n            m_ChildThresholdArray = reader.ReadSingleArray();\n        }\n    }\n\n    public class BlendDirectDataConstant\n    {\n        public uint[] m_ChildBlendEventIDArray;\n        public bool m_NormalizedBlendValues;\n\n        public BlendDirectDataConstant(ObjectReader reader)\n        {\n            m_ChildBlendEventIDArray = reader.ReadUInt32Array();\n            m_NormalizedBlendValues = reader.ReadBoolean();\n            reader.AlignStream();\n        }\n    }\n\n    public class BlendTreeNodeConstant\n    {\n        public uint m_BlendType;\n        public uint m_BlendEventID;\n        public uint m_BlendEventYID;\n        public uint[] m_ChildIndices;\n        public float[] m_ChildThresholdArray;\n        public Blend1dDataConstant m_Blend1dData;\n        public Blend2dDataConstant m_Blend2dData;\n        public BlendDirectDataConstant m_BlendDirectData;\n        public uint m_ClipID;\n        public uint m_ClipIndex;\n        public float m_Duration;\n        public float m_CycleOffset;\n        public bool m_Mirror;\n\n        public BlendTreeNodeConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up\n            {\n                m_BlendType = reader.ReadUInt32();\n            }\n            m_BlendEventID = reader.ReadUInt32();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up\n            {\n                m_BlendEventYID = reader.ReadUInt32();\n            }\n            m_ChildIndices = reader.ReadUInt32Array();\n            if (version[0] < 4 || (version[0] == 4 && version[1] < 1)) //4.1 down\n            {\n                m_ChildThresholdArray = reader.ReadSingleArray();\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up\n            {\n                m_Blend1dData = new Blend1dDataConstant(reader);\n                m_Blend2dData = new Blend2dDataConstant(reader);\n            }\n\n            if (version[0] >= 5) //5.0 and up\n            {\n                m_BlendDirectData = new BlendDirectDataConstant(reader);\n            }\n\n            m_ClipID = reader.ReadUInt32();\n            if (version[0] == 4 && version[1] >= 5) //4.5 - 5.0\n            {\n                m_ClipIndex = reader.ReadUInt32();\n            }\n\n            m_Duration = reader.ReadSingle();\n\n            if (version[0] > 4\n                || (version[0] == 4 && version[1] > 1)\n                || (version[0] == 4 && version[1] == 1 && version[2] >= 3)) //4.1.3 and up\n            {\n                m_CycleOffset = reader.ReadSingle();\n                m_Mirror = reader.ReadBoolean();\n                reader.AlignStream();\n            }\n        }\n    }\n\n    public class BlendTreeConstant\n    {\n        public BlendTreeNodeConstant[] m_NodeArray;\n        public ValueArrayConstant m_BlendEventArrayConstant;\n\n        public BlendTreeConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            int numNodes = reader.ReadInt32();\n            m_NodeArray = new BlendTreeNodeConstant[numNodes];\n            for (int i = 0; i < numNodes; i++)\n            {\n                m_NodeArray[i] = new BlendTreeNodeConstant(reader);\n            }\n\n            if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down\n            {\n                m_BlendEventArrayConstant = new ValueArrayConstant(reader);\n            }\n        }\n    }\n\n\n    public class StateConstant\n    {\n        public TransitionConstant[] m_TransitionConstantArray;\n        public int[] m_BlendTreeConstantIndexArray;\n        public LeafInfoConstant[] m_LeafInfoArray;\n        public BlendTreeConstant[] m_BlendTreeConstantArray;\n        public uint m_NameID;\n        public uint m_PathID;\n        public uint m_FullPathID;\n        public uint m_TagID;\n        public uint m_SpeedParamID;\n        public uint m_MirrorParamID;\n        public uint m_CycleOffsetParamID;\n        public float m_Speed;\n        public float m_CycleOffset;\n        public bool m_IKOnFeet;\n        public bool m_WriteDefaultValues;\n        public bool m_Loop;\n        public bool m_Mirror;\n\n        public StateConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            int numTransistions = reader.ReadInt32();\n            m_TransitionConstantArray = new TransitionConstant[numTransistions];\n            for (int i = 0; i < numTransistions; i++)\n            {\n                m_TransitionConstantArray[i] = new TransitionConstant(reader);\n            }\n\n            m_BlendTreeConstantIndexArray = reader.ReadInt32Array();\n\n            if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down\n            {\n                int numInfos = reader.ReadInt32();\n                m_LeafInfoArray = new LeafInfoConstant[numInfos];\n                for (int i = 0; i < numInfos; i++)\n                {\n                    m_LeafInfoArray[i] = new LeafInfoConstant(reader);\n                }\n            }\n\n            int numBlends = reader.ReadInt32();\n            m_BlendTreeConstantArray = new BlendTreeConstant[numBlends];\n            for (int i = 0; i < numBlends; i++)\n            {\n                m_BlendTreeConstantArray[i] = new BlendTreeConstant(reader);\n            }\n\n            m_NameID = reader.ReadUInt32();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_PathID = reader.ReadUInt32();\n            }\n            if (version[0] >= 5) //5.0 and up\n            {\n                m_FullPathID = reader.ReadUInt32();\n            }\n\n            m_TagID = reader.ReadUInt32();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up\n            {\n                m_SpeedParamID = reader.ReadUInt32();\n                m_MirrorParamID = reader.ReadUInt32();\n                m_CycleOffsetParamID = reader.ReadUInt32();\n            }\n\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up\n            {\n                var m_TimeParamID = reader.ReadUInt32();\n            }\n\n            m_Speed = reader.ReadSingle();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up\n            {\n                m_CycleOffset = reader.ReadSingle();\n            }\n            m_IKOnFeet = reader.ReadBoolean();\n            if (version[0] >= 5) //5.0 and up\n            {\n                m_WriteDefaultValues = reader.ReadBoolean();\n            }\n\n            m_Loop = reader.ReadBoolean();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up\n            {\n                m_Mirror = reader.ReadBoolean();\n            }\n\n            reader.AlignStream();\n        }\n    }\n\n    public class SelectorTransitionConstant\n    {\n        public uint m_Destination;\n        public ConditionConstant[] m_ConditionConstantArray;\n\n        public SelectorTransitionConstant(ObjectReader reader)\n        {\n            m_Destination = reader.ReadUInt32();\n\n            int numConditions = reader.ReadInt32();\n            m_ConditionConstantArray = new ConditionConstant[numConditions];\n            for (int i = 0; i < numConditions; i++)\n            {\n                m_ConditionConstantArray[i] = new ConditionConstant(reader);\n            }\n        }\n    }\n\n    public class SelectorStateConstant\n    {\n        public SelectorTransitionConstant[] m_TransitionConstantArray;\n        public uint m_FullPathID;\n        public bool m_isEntry;\n\n        public SelectorStateConstant(ObjectReader reader)\n        {\n            int numTransitions = reader.ReadInt32();\n            m_TransitionConstantArray = new SelectorTransitionConstant[numTransitions];\n            for (int i = 0; i < numTransitions; i++)\n            {\n                m_TransitionConstantArray[i] = new SelectorTransitionConstant(reader);\n            }\n\n            m_FullPathID = reader.ReadUInt32();\n            m_isEntry = reader.ReadBoolean();\n            reader.AlignStream();\n        }\n    }\n\n    public class StateMachineConstant\n    {\n        public StateConstant[] m_StateConstantArray;\n        public TransitionConstant[] m_AnyStateTransitionConstantArray;\n        public SelectorStateConstant[] m_SelectorStateConstantArray;\n        public uint m_DefaultState;\n        public uint m_MotionSetCount;\n\n        public StateMachineConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            int numStates = reader.ReadInt32();\n            m_StateConstantArray = new StateConstant[numStates];\n            for (int i = 0; i < numStates; i++)\n            {\n                m_StateConstantArray[i] = new StateConstant(reader);\n            }\n\n            int numAnyStates = reader.ReadInt32();\n            m_AnyStateTransitionConstantArray = new TransitionConstant[numAnyStates];\n            for (int i = 0; i < numAnyStates; i++)\n            {\n                m_AnyStateTransitionConstantArray[i] = new TransitionConstant(reader);\n            }\n\n            if (version[0] >= 5) //5.0 and up\n            {\n                int numSelectors = reader.ReadInt32();\n                m_SelectorStateConstantArray = new SelectorStateConstant[numSelectors];\n                for (int i = 0; i < numSelectors; i++)\n                {\n                    m_SelectorStateConstantArray[i] = new SelectorStateConstant(reader);\n                }\n            }\n\n            m_DefaultState = reader.ReadUInt32();\n            m_MotionSetCount = reader.ReadUInt32();\n        }\n    }\n\n    public class ValueArray\n    {\n        public bool[] m_BoolValues;\n        public int[] m_IntValues;\n        public float[] m_FloatValues;\n        public Vector4[] m_VectorValues;\n        public Vector3[] m_PositionValues;\n        public Vector4[] m_QuaternionValues;\n        public Vector3[] m_ScaleValues;\n\n        public ValueArray(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down\n            {\n                m_BoolValues = reader.ReadBooleanArray();\n                reader.AlignStream();\n                m_IntValues = reader.ReadInt32Array();\n                m_FloatValues = reader.ReadSingleArray();\n            }\n\n            if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down\n            {\n                m_VectorValues = reader.ReadVector4Array();\n            }\n            else\n            {\n                int numPosValues = reader.ReadInt32();\n                m_PositionValues = new Vector3[numPosValues];\n                for (int i = 0; i < numPosValues; i++)\n                {\n                    m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up\n                }\n\n                m_QuaternionValues = reader.ReadVector4Array();\n\n                int numScaleValues = reader.ReadInt32();\n                m_ScaleValues = new Vector3[numScaleValues];\n                for (int i = 0; i < numScaleValues; i++)\n                {\n                    m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up\n                }\n\n                if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up\n                {\n                    m_FloatValues = reader.ReadSingleArray();\n                    m_IntValues = reader.ReadInt32Array();\n                    m_BoolValues = reader.ReadBooleanArray();\n                    reader.AlignStream();\n                }\n            }\n        }\n    }\n\n    public class ControllerConstant\n    {\n        public LayerConstant[] m_LayerArray;\n        public StateMachineConstant[] m_StateMachineArray;\n        public ValueArrayConstant m_Values;\n        public ValueArray m_DefaultValues;\n\n        public ControllerConstant(ObjectReader reader)\n        {\n            int numLayers = reader.ReadInt32();\n            m_LayerArray = new LayerConstant[numLayers];\n            for (int i = 0; i < numLayers; i++)\n            {\n                m_LayerArray[i] = new LayerConstant(reader);\n            }\n\n            int numStates = reader.ReadInt32();\n            m_StateMachineArray = new StateMachineConstant[numStates];\n            for (int i = 0; i < numStates; i++)\n            {\n                m_StateMachineArray[i] = new StateMachineConstant(reader);\n            }\n\n            m_Values = new ValueArrayConstant(reader);\n            m_DefaultValues = new ValueArray(reader);\n        }\n    }\n\n    public sealed class AnimatorController : RuntimeAnimatorController\n    {\n        public PPtr<AnimationClip>[] m_AnimationClips;\n\n        public AnimatorController(ObjectReader reader) : base(reader)\n        {\n            var m_ControllerSize = reader.ReadUInt32();\n            var m_Controller = new ControllerConstant(reader);\n\n            int tosSize = reader.ReadInt32();\n            var m_TOS = new KeyValuePair<uint, string>[tosSize];\n            for (int i = 0; i < tosSize; i++)\n            {\n                m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());\n            }\n\n            int numClips = reader.ReadInt32();\n            m_AnimationClips = new PPtr<AnimationClip>[numClips];\n            for (int i = 0; i < numClips; i++)\n            {\n                m_AnimationClips[i] = new PPtr<AnimationClip>(reader);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/AnimatorOverrideController.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class AnimationClipOverride\n    {\n        public PPtr<AnimationClip> m_OriginalClip;\n        public PPtr<AnimationClip> m_OverrideClip;\n\n        public AnimationClipOverride(ObjectReader reader)\n        {\n            m_OriginalClip = new PPtr<AnimationClip>(reader);\n            m_OverrideClip = new PPtr<AnimationClip>(reader);\n        }\n    }\n\n    public sealed class AnimatorOverrideController : RuntimeAnimatorController\n    {\n        public PPtr<RuntimeAnimatorController> m_Controller;\n        public AnimationClipOverride[] m_Clips;\n\n        public AnimatorOverrideController(ObjectReader reader) : base(reader)\n        {\n            m_Controller = new PPtr<RuntimeAnimatorController>(reader);\n\n            int numOverrides = reader.ReadInt32();\n            m_Clips = new AnimationClipOverride[numOverrides];\n            for (int i = 0; i < numOverrides; i++)\n            {\n                m_Clips[i] = new AnimationClipOverride(reader);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/AssetBundle.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class AssetInfo\n    {\n        public int preloadIndex;\n        public int preloadSize;\n        public PPtr<Object> asset;\n\n        public AssetInfo(ObjectReader reader)\n        {\n            preloadIndex = reader.ReadInt32();\n            preloadSize = reader.ReadInt32();\n            asset = new PPtr<Object>(reader);\n        }\n    }\n\n    public sealed class AssetBundle : NamedObject\n    {\n        public PPtr<Object>[] m_PreloadTable;\n        public KeyValuePair<string, AssetInfo>[] m_Container;\n\n        public AssetBundle(ObjectReader reader) : base(reader)\n        {\n            var m_PreloadTableSize = reader.ReadInt32();\n            m_PreloadTable = new PPtr<Object>[m_PreloadTableSize];\n            for (int i = 0; i < m_PreloadTableSize; i++)\n            {\n                m_PreloadTable[i] = new PPtr<Object>(reader);\n            }\n\n            var m_ContainerSize = reader.ReadInt32();\n            m_Container = new KeyValuePair<string, AssetInfo>[m_ContainerSize];\n            for (int i = 0; i < m_ContainerSize; i++)\n            {\n                m_Container[i] = new KeyValuePair<string, AssetInfo>(reader.ReadAlignedString(), new AssetInfo(reader));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/AudioClip.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class AudioClip : NamedObject\n    {\n        public int m_Format;\n        public FMODSoundType m_Type;\n        public bool m_3D;\n        public bool m_UseHardware;\n\n        //version 5\n        public int m_LoadType;\n        public int m_Channels;\n        public int m_Frequency;\n        public int m_BitsPerSample;\n        public float m_Length;\n        public bool m_IsTrackerFormat;\n        public int m_SubsoundIndex;\n        public bool m_PreloadAudioData;\n        public bool m_LoadInBackground;\n        public bool m_Legacy3D;\n        public AudioCompressionFormat m_CompressionFormat;\n\n        public string m_Source;\n        public long m_Offset; //ulong\n        public long m_Size; //ulong\n        public ResourceReader m_AudioData;\n\n        public AudioClip(ObjectReader reader) : base(reader)\n        {\n            if (version[0] < 5)\n            {\n                m_Format = reader.ReadInt32();\n                m_Type = (FMODSoundType)reader.ReadInt32();\n                m_3D = reader.ReadBoolean();\n                m_UseHardware = reader.ReadBoolean();\n                reader.AlignStream();\n\n                if (version[0] >= 4 || (version[0] == 3 && version[1] >= 2)) //3.2.0 to 5\n                {\n                    int m_Stream = reader.ReadInt32();\n                    m_Size = reader.ReadInt32();\n                    var tsize = m_Size % 4 != 0 ? m_Size + 4 - m_Size % 4 : m_Size;\n                    if (reader.byteSize + reader.byteStart - reader.Position != tsize)\n                    {\n                        m_Offset = reader.ReadUInt32();\n                        m_Source = assetsFile.fullName + \".resS\";\n                    }\n                }\n                else\n                {\n                    m_Size = reader.ReadInt32();\n                }\n            }\n            else\n            {\n                m_LoadType = reader.ReadInt32();\n                m_Channels = reader.ReadInt32();\n                m_Frequency = reader.ReadInt32();\n                m_BitsPerSample = reader.ReadInt32();\n                m_Length = reader.ReadSingle();\n                m_IsTrackerFormat = reader.ReadBoolean();\n                reader.AlignStream();\n                m_SubsoundIndex = reader.ReadInt32();\n                m_PreloadAudioData = reader.ReadBoolean();\n                m_LoadInBackground = reader.ReadBoolean();\n                m_Legacy3D = reader.ReadBoolean();\n                reader.AlignStream();\n\n                //StreamedResource m_Resource\n                m_Source = reader.ReadAlignedString();\n                m_Offset = reader.ReadInt64();\n                m_Size = reader.ReadInt64();\n                m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();\n            }\n\n            ResourceReader resourceReader;\n            if (!string.IsNullOrEmpty(m_Source))\n            {\n                resourceReader = new ResourceReader(m_Source, assetsFile, m_Offset, m_Size);\n            }\n            else\n            {\n                resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_Size);\n            }\n            m_AudioData = resourceReader;\n        }\n    }\n\n    public enum FMODSoundType\n    {\n        UNKNOWN = 0,\n        ACC = 1,\n        AIFF = 2,\n        ASF = 3,\n        AT3 = 4,\n        CDDA = 5,\n        DLS = 6,\n        FLAC = 7,\n        FSB = 8,\n        GCADPCM = 9,\n        IT = 10,\n        MIDI = 11,\n        MOD = 12,\n        MPEG = 13,\n        OGGVORBIS = 14,\n        PLAYLIST = 15,\n        RAW = 16,\n        S3M = 17,\n        SF2 = 18,\n        USER = 19,\n        WAV = 20,\n        XM = 21,\n        XMA = 22,\n        VAG = 23,\n        AUDIOQUEUE = 24,\n        XWMA = 25,\n        BCWAV = 26,\n        AT9 = 27,\n        VORBIS = 28,\n        MEDIA_FOUNDATION = 29\n    }\n\n    public enum AudioCompressionFormat\n    {\n        PCM = 0,\n        Vorbis = 1,\n        ADPCM = 2,\n        MP3 = 3,\n        PSMVAG = 4,\n        HEVAG = 5,\n        XMA = 6,\n        AAC = 7,\n        GCADPCM = 8,\n        ATRAC9 = 9\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Avatar.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\n\nnamespace AssetStudio\n{\n    public class Node\n    {\n        public int m_ParentId;\n        public int m_AxesId;\n\n        public Node(ObjectReader reader)\n        {\n            m_ParentId = reader.ReadInt32();\n            m_AxesId = reader.ReadInt32();\n        }\n    }\n\n    public class Limit\n    {\n        public object m_Min;\n        public object m_Max;\n\n        public Limit(ObjectReader reader)\n        {\n            var version = reader.version;\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up\n            {\n                m_Min = reader.ReadVector3();\n                m_Max = reader.ReadVector3();\n            }\n            else\n            {\n                m_Min = reader.ReadVector4();\n                m_Max = reader.ReadVector4();\n            }\n        }\n    }\n\n    public class Axes\n    {\n        public Vector4 m_PreQ;\n        public Vector4 m_PostQ;\n        public object m_Sgn;\n        public Limit m_Limit;\n        public float m_Length;\n        public uint m_Type;\n\n        public Axes(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_PreQ = reader.ReadVector4();\n            m_PostQ = reader.ReadVector4();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up\n            {\n                m_Sgn = reader.ReadVector3();\n            }\n            else\n            {\n                m_Sgn = reader.ReadVector4();\n            }\n            m_Limit = new Limit(reader);\n            m_Length = reader.ReadSingle();\n            m_Type = reader.ReadUInt32();\n        }\n    }\n\n    public class Skeleton\n    {\n        public Node[] m_Node;\n        public uint[] m_ID;\n        public Axes[] m_AxesArray;\n\n\n        public Skeleton(ObjectReader reader)\n        {\n            int numNodes = reader.ReadInt32();\n            m_Node = new Node[numNodes];\n            for (int i = 0; i < numNodes; i++)\n            {\n                m_Node[i] = new Node(reader);\n            }\n\n            m_ID = reader.ReadUInt32Array();\n\n            int numAxes = reader.ReadInt32();\n            m_AxesArray = new Axes[numAxes];\n            for (int i = 0; i < numAxes; i++)\n            {\n                m_AxesArray[i] = new Axes(reader);\n            }\n        }\n    }\n\n    public class SkeletonPose\n    {\n        public xform[] m_X;\n\n        public SkeletonPose(ObjectReader reader)\n        {\n            int numXforms = reader.ReadInt32();\n            m_X = new xform[numXforms];\n            for (int i = 0; i < numXforms; i++)\n            {\n                m_X[i] = new xform(reader);\n            }\n        }\n    }\n\n    public class Hand\n    {\n        public int[] m_HandBoneIndex;\n\n        public Hand(ObjectReader reader)\n        {\n            m_HandBoneIndex = reader.ReadInt32Array();\n        }\n    }\n\n    public class Handle\n    {\n        public xform m_X;\n        public uint m_ParentHumanIndex;\n        public uint m_ID;\n\n        public Handle(ObjectReader reader)\n        {\n            m_X = new xform(reader);\n            m_ParentHumanIndex = reader.ReadUInt32();\n            m_ID = reader.ReadUInt32();\n        }\n    }\n\n    public class Collider\n    {\n        public xform m_X;\n        public uint m_Type;\n        public uint m_XMotionType;\n        public uint m_YMotionType;\n        public uint m_ZMotionType;\n        public float m_MinLimitX;\n        public float m_MaxLimitX;\n        public float m_MaxLimitY;\n        public float m_MaxLimitZ;\n\n        public Collider(ObjectReader reader)\n        {\n            m_X = new xform(reader);\n            m_Type = reader.ReadUInt32();\n            m_XMotionType = reader.ReadUInt32();\n            m_YMotionType = reader.ReadUInt32();\n            m_ZMotionType = reader.ReadUInt32();\n            m_MinLimitX = reader.ReadSingle();\n            m_MaxLimitX = reader.ReadSingle();\n            m_MaxLimitY = reader.ReadSingle();\n            m_MaxLimitZ = reader.ReadSingle();\n        }\n    }\n\n    public class Human\n    {\n        public xform m_RootX;\n        public Skeleton m_Skeleton;\n        public SkeletonPose m_SkeletonPose;\n        public Hand m_LeftHand;\n        public Hand m_RightHand;\n        public Handle[] m_Handles;\n        public Collider[] m_ColliderArray;\n        public int[] m_HumanBoneIndex;\n        public float[] m_HumanBoneMass;\n        public int[] m_ColliderIndex;\n        public float m_Scale;\n        public float m_ArmTwist;\n        public float m_ForeArmTwist;\n        public float m_UpperLegTwist;\n        public float m_LegTwist;\n        public float m_ArmStretch;\n        public float m_LegStretch;\n        public float m_FeetSpacing;\n        public bool m_HasLeftHand;\n        public bool m_HasRightHand;\n        public bool m_HasTDoF;\n\n        public Human(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_RootX = new xform(reader);\n            m_Skeleton = new Skeleton(reader);\n            m_SkeletonPose = new SkeletonPose(reader);\n            m_LeftHand = new Hand(reader);\n            m_RightHand = new Hand(reader);\n\n            if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down\n            {\n                int numHandles = reader.ReadInt32();\n                m_Handles = new Handle[numHandles];\n                for (int i = 0; i < numHandles; i++)\n                {\n                    m_Handles[i] = new Handle(reader);\n                }\n\n                int numColliders = reader.ReadInt32();\n                m_ColliderArray = new Collider[numColliders];\n                for (int i = 0; i < numColliders; i++)\n                {\n                    m_ColliderArray[i] = new Collider(reader);\n                }\n            }\n\n            m_HumanBoneIndex = reader.ReadInt32Array();\n\n            m_HumanBoneMass = reader.ReadSingleArray();\n\n            if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down\n            {\n                m_ColliderIndex = reader.ReadInt32Array();\n            }\n\n            m_Scale = reader.ReadSingle();\n            m_ArmTwist = reader.ReadSingle();\n            m_ForeArmTwist = reader.ReadSingle();\n            m_UpperLegTwist = reader.ReadSingle();\n            m_LegTwist = reader.ReadSingle();\n            m_ArmStretch = reader.ReadSingle();\n            m_LegStretch = reader.ReadSingle();\n            m_FeetSpacing = reader.ReadSingle();\n            m_HasLeftHand = reader.ReadBoolean();\n            m_HasRightHand = reader.ReadBoolean();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up\n            {\n                m_HasTDoF = reader.ReadBoolean();\n            }\n            reader.AlignStream();\n        }\n    }\n\n    public class AvatarConstant\n    {\n        public Skeleton m_AvatarSkeleton;\n        public SkeletonPose m_AvatarSkeletonPose;\n        public SkeletonPose m_DefaultPose;\n        public uint[] m_SkeletonNameIDArray;\n        public Human m_Human;\n        public int[] m_HumanSkeletonIndexArray;\n        public int[] m_HumanSkeletonReverseIndexArray;\n        public int m_RootMotionBoneIndex;\n        public xform m_RootMotionBoneX;\n        public Skeleton m_RootMotionSkeleton;\n        public SkeletonPose m_RootMotionSkeletonPose;\n        public int[] m_RootMotionSkeletonIndexArray;\n\n        public AvatarConstant(ObjectReader reader)\n        {\n            var version = reader.version;\n            m_AvatarSkeleton = new Skeleton(reader);\n            m_AvatarSkeletonPose = new SkeletonPose(reader);\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_DefaultPose = new SkeletonPose(reader);\n\n                m_SkeletonNameIDArray = reader.ReadUInt32Array();\n            }\n\n            m_Human = new Human(reader);\n\n            m_HumanSkeletonIndexArray = reader.ReadInt32Array();\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array();\n            }\n\n            m_RootMotionBoneIndex = reader.ReadInt32();\n            m_RootMotionBoneX = new xform(reader);\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_RootMotionSkeleton = new Skeleton(reader);\n                m_RootMotionSkeletonPose = new SkeletonPose(reader);\n\n                m_RootMotionSkeletonIndexArray = reader.ReadInt32Array();\n            }\n        }\n    }\n\n    public sealed class Avatar : NamedObject\n    {\n        public uint m_AvatarSize;\n        public AvatarConstant m_Avatar;\n        public KeyValuePair<uint, string>[] m_TOS;\n\n        public Avatar(ObjectReader reader) : base(reader)\n        {\n            m_AvatarSize = reader.ReadUInt32();\n            m_Avatar = new AvatarConstant(reader);\n\n            int numTOS = reader.ReadInt32();\n            m_TOS = new KeyValuePair<uint, string>[numTOS];\n            for (int i = 0; i < numTOS; i++)\n            {\n                m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());\n            }\n\n            //HumanDescription m_HumanDescription 2019 and up\n        }\n\n        public string FindBonePath(uint hash)\n        {\n            return m_TOS.FirstOrDefault(pair => pair.Key == hash).Value;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Behaviour.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public abstract class Behaviour : Component\n    {\n        public byte m_Enabled;\n\n        protected Behaviour(ObjectReader reader) : base(reader)\n        {\n            m_Enabled = reader.ReadByte();\n            reader.AlignStream();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/BuildSettings.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class BuildSettings : Object\n    {\n        public string m_Version;\n\n        public BuildSettings(ObjectReader reader) : base(reader)\n        {\n            var levels = reader.ReadStringArray();\n\n            var hasRenderTexture = reader.ReadBoolean();\n            var hasPROVersion = reader.ReadBoolean();\n            var hasPublishingRights = reader.ReadBoolean();\n            var hasShadows = reader.ReadBoolean();\n\n            m_Version = reader.ReadAlignedString();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Component.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public abstract class Component : EditorExtension\n    {\n        public PPtr<GameObject> m_GameObject;\n\n        protected Component(ObjectReader reader) : base(reader)\n        {\n            m_GameObject = new PPtr<GameObject>(reader);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/EditorExtension.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public abstract class EditorExtension : Object\n    {\n        protected EditorExtension(ObjectReader reader) : base(reader)\n        {\n            if (platform == BuildTarget.NoTarget)\n            {\n                var m_PrefabParentObject = new PPtr<EditorExtension>(reader);\n                var m_PrefabInternal = new PPtr<Object>(reader); //PPtr<Prefab>\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Font.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class Font : NamedObject\n    {\n        public byte[] m_FontData;\n\n        public Font(ObjectReader reader) : base(reader)\n        {\n            if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up\n            {\n                var m_LineSpacing = reader.ReadSingle();\n                var m_DefaultMaterial = new PPtr<Material>(reader);\n                var m_FontSize = reader.ReadSingle();\n                var m_Texture = new PPtr<Texture>(reader);\n                int m_AsciiStartOffset = reader.ReadInt32();\n                var m_Tracking = reader.ReadSingle();\n                var m_CharacterSpacing = reader.ReadInt32();\n                var m_CharacterPadding = reader.ReadInt32();\n                var m_ConvertCase = reader.ReadInt32();\n                int m_CharacterRects_size = reader.ReadInt32();\n                for (int i = 0; i < m_CharacterRects_size; i++)\n                {\n                    reader.Position += 44;//CharacterInfo data 41\n                }\n                int m_KerningValues_size = reader.ReadInt32();\n                for (int i = 0; i < m_KerningValues_size; i++)\n                {\n                    reader.Position += 8;\n                }\n                var m_PixelScale = reader.ReadSingle();\n                int m_FontData_size = reader.ReadInt32();\n                if (m_FontData_size > 0)\n                {\n                    m_FontData = reader.ReadBytes(m_FontData_size);\n                }\n            }\n            else\n            {\n                int m_AsciiStartOffset = reader.ReadInt32();\n\n                if (version[0] <= 3)\n                {\n                    int m_FontCountX = reader.ReadInt32();\n                    int m_FontCountY = reader.ReadInt32();\n                }\n\n                float m_Kerning = reader.ReadSingle();\n                float m_LineSpacing = reader.ReadSingle();\n\n                if (version[0] <= 3)\n                {\n                    int m_PerCharacterKerning_size = reader.ReadInt32();\n                    for (int i = 0; i < m_PerCharacterKerning_size; i++)\n                    {\n                        int first = reader.ReadInt32();\n                        float second = reader.ReadSingle();\n                    }\n                }\n                else\n                {\n                    int m_CharacterSpacing = reader.ReadInt32();\n                    int m_CharacterPadding = reader.ReadInt32();\n                }\n\n                int m_ConvertCase = reader.ReadInt32();\n                var m_DefaultMaterial = new PPtr<Material>(reader);\n\n                int m_CharacterRects_size = reader.ReadInt32();\n                for (int i = 0; i < m_CharacterRects_size; i++)\n                {\n                    int index = reader.ReadInt32();\n                    //Rectf uv\n                    float uvx = reader.ReadSingle();\n                    float uvy = reader.ReadSingle();\n                    float uvwidth = reader.ReadSingle();\n                    float uvheight = reader.ReadSingle();\n                    //Rectf vert\n                    float vertx = reader.ReadSingle();\n                    float verty = reader.ReadSingle();\n                    float vertwidth = reader.ReadSingle();\n                    float vertheight = reader.ReadSingle();\n                    float width = reader.ReadSingle();\n\n                    if (version[0] >= 4)\n                    {\n                        var flipped = reader.ReadBoolean();\n                        reader.AlignStream();\n                    }\n                }\n\n                var m_Texture = new PPtr<Texture>(reader);\n\n                int m_KerningValues_size = reader.ReadInt32();\n                for (int i = 0; i < m_KerningValues_size; i++)\n                {\n                    int pairfirst = reader.ReadInt16();\n                    int pairsecond = reader.ReadInt16();\n                    float second = reader.ReadSingle();\n                }\n\n                if (version[0] <= 3)\n                {\n                    var m_GridFont = reader.ReadBoolean();\n                    reader.AlignStream();\n                }\n                else { float m_PixelScale = reader.ReadSingle(); }\n\n                int m_FontData_size = reader.ReadInt32();\n                if (m_FontData_size > 0)\n                {\n                    m_FontData = reader.ReadBytes(m_FontData_size);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/GameObject.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class GameObject : EditorExtension\n    {\n        public PPtr<Component>[] m_Components;\n        public string m_Name;\n\n        public Transform m_Transform;\n        public MeshRenderer m_MeshRenderer;\n        public MeshFilter m_MeshFilter;\n        public SkinnedMeshRenderer m_SkinnedMeshRenderer;\n        public Animator m_Animator;\n        public Animation m_Animation;\n\n        public GameObject(ObjectReader reader) : base(reader)\n        {\n            int m_Component_size = reader.ReadInt32();\n            m_Components = new PPtr<Component>[m_Component_size];\n            for (int i = 0; i < m_Component_size; i++)\n            {\n                if ((version[0] == 5 && version[1] < 5) || version[0] < 5) //5.5 down\n                {\n                    int first = reader.ReadInt32();\n                }\n                m_Components[i] = new PPtr<Component>(reader);\n            }\n\n            var m_Layer = reader.ReadInt32();\n            m_Name = reader.ReadAlignedString();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Material.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace AssetStudio\n{\n    public class UnityTexEnv\n    {\n        public PPtr<Texture> m_Texture;\n        public Vector2 m_Scale;\n        public Vector2 m_Offset;\n\n        public UnityTexEnv(ObjectReader reader)\n        {\n            m_Texture = new PPtr<Texture>(reader);\n            m_Scale = reader.ReadVector2();\n            m_Offset = reader.ReadVector2();\n        }\n    }\n\n    public class UnityPropertySheet\n    {\n        public KeyValuePair<string, UnityTexEnv>[] m_TexEnvs;\n        public KeyValuePair<string, int>[] m_Ints;\n        public KeyValuePair<string, float>[] m_Floats;\n        public KeyValuePair<string, Color>[] m_Colors;\n\n        public UnityPropertySheet(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            int m_TexEnvsSize = reader.ReadInt32();\n            m_TexEnvs = new KeyValuePair<string, UnityTexEnv>[m_TexEnvsSize];\n            for (int i = 0; i < m_TexEnvsSize; i++)\n            {\n                m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));\n            }\n\n            if (version[0] >= 2021) //2021.1 and up\n            {\n                int m_IntsSize = reader.ReadInt32();\n                m_Ints = new KeyValuePair<string, int>[m_IntsSize];\n                for (int i = 0; i < m_IntsSize; i++)\n                {\n                    m_Ints[i] = new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32());\n                }\n            }\n\n            int m_FloatsSize = reader.ReadInt32();\n            m_Floats = new KeyValuePair<string, float>[m_FloatsSize];\n            for (int i = 0; i < m_FloatsSize; i++)\n            {\n                m_Floats[i] = new KeyValuePair<string, float>(reader.ReadAlignedString(), reader.ReadSingle());\n            }\n\n            int m_ColorsSize = reader.ReadInt32();\n            m_Colors = new KeyValuePair<string, Color>[m_ColorsSize];\n            for (int i = 0; i < m_ColorsSize; i++)\n            {\n                m_Colors[i] = new KeyValuePair<string, Color>(reader.ReadAlignedString(), reader.ReadColor4());\n            }\n        }\n    }\n\n    public sealed class Material : NamedObject\n    {\n        public PPtr<Shader> m_Shader;\n        public UnityPropertySheet m_SavedProperties;\n\n        public Material(ObjectReader reader) : base(reader)\n        {\n            m_Shader = new PPtr<Shader>(reader);\n\n            if (version[0] == 4 && version[1] >= 1) //4.x\n            {\n                var m_ShaderKeywords = reader.ReadStringArray();\n            }\n\n            if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 and up\n            {\n                var m_ValidKeywords = reader.ReadStringArray();\n                var m_InvalidKeywords = reader.ReadStringArray();\n            }\n            else if (version[0] >= 5) //5.0 ~ 2021.2\n            {\n                var m_ShaderKeywords = reader.ReadAlignedString();\n            }\n\n            if (version[0] >= 5) //5.0 and up\n            {\n                var m_LightmapFlags = reader.ReadUInt32();\n            }\n\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up\n            {\n                var m_EnableInstancingVariants = reader.ReadBoolean();\n                //var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up\n                reader.AlignStream();\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                var m_CustomRenderQueue = reader.ReadInt32();\n            }\n\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up\n            {\n                var stringTagMapSize = reader.ReadInt32();\n                for (int i = 0; i < stringTagMapSize; i++)\n                {\n                    var first = reader.ReadAlignedString();\n                    var second = reader.ReadAlignedString();\n                }\n            }\n\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up\n            {\n                var disabledShaderPasses = reader.ReadStringArray();\n            }\n\n            m_SavedProperties = new UnityPropertySheet(reader);\n\n            //vector m_BuildTextureStacks 2020 and up\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Mesh.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace AssetStudio\n{\n    public class MinMaxAABB\n    {\n        public Vector3 m_Min;\n        public Vector3 m_Max;\n\n        public MinMaxAABB(BinaryReader reader)\n        {\n            m_Min = reader.ReadVector3();\n            m_Max = reader.ReadVector3();\n        }\n    }\n\n    public class CompressedMesh\n    {\n        public PackedFloatVector m_Vertices;\n        public PackedFloatVector m_UV;\n        public PackedFloatVector m_BindPoses;\n        public PackedFloatVector m_Normals;\n        public PackedFloatVector m_Tangents;\n        public PackedIntVector m_Weights;\n        public PackedIntVector m_NormalSigns;\n        public PackedIntVector m_TangentSigns;\n        public PackedFloatVector m_FloatColors;\n        public PackedIntVector m_BoneIndices;\n        public PackedIntVector m_Triangles;\n        public PackedIntVector m_Colors;\n        public uint m_UVInfo;\n\n        public CompressedMesh(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_Vertices = new PackedFloatVector(reader);\n            m_UV = new PackedFloatVector(reader);\n            if (version[0] < 5)\n            {\n                m_BindPoses = new PackedFloatVector(reader);\n            }\n            m_Normals = new PackedFloatVector(reader);\n            m_Tangents = new PackedFloatVector(reader);\n            m_Weights = new PackedIntVector(reader);\n            m_NormalSigns = new PackedIntVector(reader);\n            m_TangentSigns = new PackedIntVector(reader);\n            if (version[0] >= 5)\n            {\n                m_FloatColors = new PackedFloatVector(reader);\n            }\n            m_BoneIndices = new PackedIntVector(reader);\n            m_Triangles = new PackedIntVector(reader);\n            if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up\n            {\n                if (version[0] < 5)\n                {\n                    m_Colors = new PackedIntVector(reader);\n                }\n                else\n                {\n                    m_UVInfo = reader.ReadUInt32();\n                }\n            }\n        }\n    }\n\n    public class StreamInfo\n    {\n        public uint channelMask;\n        public uint offset;\n        public uint stride;\n        public uint align;\n        public byte dividerOp;\n        public ushort frequency;\n\n        public StreamInfo() { }\n\n        public StreamInfo(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            channelMask = reader.ReadUInt32();\n            offset = reader.ReadUInt32();\n\n            if (version[0] < 4) //4.0 down\n            {\n                stride = reader.ReadUInt32();\n                align = reader.ReadUInt32();\n            }\n            else\n            {\n                stride = reader.ReadByte();\n                dividerOp = reader.ReadByte();\n                frequency = reader.ReadUInt16();\n            }\n        }\n    }\n\n    public class ChannelInfo\n    {\n        public byte stream;\n        public byte offset;\n        public byte format;\n        public byte dimension;\n\n        public ChannelInfo() { }\n\n        public ChannelInfo(ObjectReader reader)\n        {\n            stream = reader.ReadByte();\n            offset = reader.ReadByte();\n            format = reader.ReadByte();\n            dimension = (byte)(reader.ReadByte() & 0xF);\n        }\n    }\n\n    public class VertexData\n    {\n        public uint m_CurrentChannels;\n        public uint m_VertexCount;\n        public ChannelInfo[] m_Channels;\n        public StreamInfo[] m_Streams;\n        public byte[] m_DataSize;\n\n        public VertexData(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            if (version[0] < 2018)//2018 down\n            {\n                m_CurrentChannels = reader.ReadUInt32();\n            }\n\n            m_VertexCount = reader.ReadUInt32();\n\n            if (version[0] >= 4) //4.0 and up\n            {\n                var m_ChannelsSize = reader.ReadInt32();\n                m_Channels = new ChannelInfo[m_ChannelsSize];\n                for (int i = 0; i < m_ChannelsSize; i++)\n                {\n                    m_Channels[i] = new ChannelInfo(reader);\n                }\n            }\n\n            if (version[0] < 5) //5.0 down\n            {\n                if (version[0] < 4)\n                {\n                    m_Streams = new StreamInfo[4];\n                }\n                else\n                {\n                    m_Streams = new StreamInfo[reader.ReadInt32()];\n                }\n\n                for (int i = 0; i < m_Streams.Length; i++)\n                {\n                    m_Streams[i] = new StreamInfo(reader);\n                }\n\n                if (version[0] < 4) //4.0 down\n                {\n                    GetChannels(version);\n                }\n            }\n            else //5.0 and up\n            {\n                GetStreams(version);\n            }\n\n            m_DataSize = reader.ReadUInt8Array();\n            reader.AlignStream();\n        }\n\n        private void GetStreams(int[] version)\n        {\n            var streamCount = m_Channels.Max(x => x.stream) + 1;\n            m_Streams = new StreamInfo[streamCount];\n            uint offset = 0;\n            for (int s = 0; s < streamCount; s++)\n            {\n                uint chnMask = 0;\n                uint stride = 0;\n                for (int chn = 0; chn < m_Channels.Length; chn++)\n                {\n                    var m_Channel = m_Channels[chn];\n                    if (m_Channel.stream == s)\n                    {\n                        if (m_Channel.dimension > 0)\n                        {\n                            chnMask |= 1u << chn;\n                            stride += m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version));\n                        }\n                    }\n                }\n                m_Streams[s] = new StreamInfo\n                {\n                    channelMask = chnMask,\n                    offset = offset,\n                    stride = stride,\n                    dividerOp = 0,\n                    frequency = 0\n                };\n                offset += m_VertexCount * stride;\n                //static size_t AlignStreamSize (size_t size) { return (size + (kVertexStreamAlign-1)) & ~(kVertexStreamAlign-1); }\n                offset = (offset + (16u - 1u)) & ~(16u - 1u);\n            }\n        }\n\n        private void GetChannels(int[] version)\n        {\n            m_Channels = new ChannelInfo[6];\n            for (int i = 0; i < 6; i++)\n            {\n                m_Channels[i] = new ChannelInfo();\n            }\n            for (var s = 0; s < m_Streams.Length; s++)\n            {\n                var m_Stream = m_Streams[s];\n                var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });\n                byte offset = 0;\n                for (int i = 0; i < 6; i++)\n                {\n                    if (channelMask.Get(i))\n                    {\n                        var m_Channel = m_Channels[i];\n                        m_Channel.stream = (byte)s;\n                        m_Channel.offset = offset;\n                        switch (i)\n                        {\n                            case 0: //kShaderChannelVertex\n                            case 1: //kShaderChannelNormal\n                                m_Channel.format = 0; //kChannelFormatFloat\n                                m_Channel.dimension = 3;\n                                break;\n                            case 2: //kShaderChannelColor\n                                m_Channel.format = 2; //kChannelFormatColor\n                                m_Channel.dimension = 4;\n                                break;\n                            case 3: //kShaderChannelTexCoord0\n                            case 4: //kShaderChannelTexCoord1\n                                m_Channel.format = 0; //kChannelFormatFloat\n                                m_Channel.dimension = 2;\n                                break;\n                            case 5: //kShaderChannelTangent\n                                m_Channel.format = 0; //kChannelFormatFloat\n                                m_Channel.dimension = 4;\n                                break;\n                        }\n                        offset += (byte)(m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version)));\n                    }\n                }\n            }\n        }\n    }\n\n    public class BoneWeights4\n    {\n        public float[] weight;\n        public int[] boneIndex;\n\n        public BoneWeights4()\n        {\n            weight = new float[4];\n            boneIndex = new int[4];\n        }\n\n        public BoneWeights4(ObjectReader reader)\n        {\n            weight = reader.ReadSingleArray(4);\n            boneIndex = reader.ReadInt32Array(4);\n        }\n    }\n\n    public class BlendShapeVertex\n    {\n        public Vector3 vertex;\n        public Vector3 normal;\n        public Vector3 tangent;\n        public uint index;\n\n        public BlendShapeVertex(ObjectReader reader)\n        {\n            vertex = reader.ReadVector3();\n            normal = reader.ReadVector3();\n            tangent = reader.ReadVector3();\n            index = reader.ReadUInt32();\n        }\n    }\n\n    public class MeshBlendShape\n    {\n        public uint firstVertex;\n        public uint vertexCount;\n        public bool hasNormals;\n        public bool hasTangents;\n\n        public MeshBlendShape(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            if (version[0] == 4 && version[1] < 3) //4.3 down\n            {\n                var name = reader.ReadAlignedString();\n            }\n            firstVertex = reader.ReadUInt32();\n            vertexCount = reader.ReadUInt32();\n            if (version[0] == 4 && version[1] < 3) //4.3 down\n            {\n                var aabbMinDelta = reader.ReadVector3();\n                var aabbMaxDelta = reader.ReadVector3();\n            }\n            hasNormals = reader.ReadBoolean();\n            hasTangents = reader.ReadBoolean();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                reader.AlignStream();\n            }\n        }\n    }\n\n    public class MeshBlendShapeChannel\n    {\n        public string name;\n        public uint nameHash;\n        public int frameIndex;\n        public int frameCount;\n\n        public MeshBlendShapeChannel(ObjectReader reader)\n        {\n            name = reader.ReadAlignedString();\n            nameHash = reader.ReadUInt32();\n            frameIndex = reader.ReadInt32();\n            frameCount = reader.ReadInt32();\n        }\n    }\n\n    public class BlendShapeData\n    {\n        public BlendShapeVertex[] vertices;\n        public MeshBlendShape[] shapes;\n        public MeshBlendShapeChannel[] channels;\n        public float[] fullWeights;\n\n        public BlendShapeData(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                int numVerts = reader.ReadInt32();\n                vertices = new BlendShapeVertex[numVerts];\n                for (int i = 0; i < numVerts; i++)\n                {\n                    vertices[i] = new BlendShapeVertex(reader);\n                }\n\n                int numShapes = reader.ReadInt32();\n                shapes = new MeshBlendShape[numShapes];\n                for (int i = 0; i < numShapes; i++)\n                {\n                    shapes[i] = new MeshBlendShape(reader);\n                }\n\n                int numChannels = reader.ReadInt32();\n                channels = new MeshBlendShapeChannel[numChannels];\n                for (int i = 0; i < numChannels; i++)\n                {\n                    channels[i] = new MeshBlendShapeChannel(reader);\n                }\n\n                fullWeights = reader.ReadSingleArray();\n            }\n            else\n            {\n                var m_ShapesSize = reader.ReadInt32();\n                var m_Shapes = new MeshBlendShape[m_ShapesSize];\n                for (int i = 0; i < m_ShapesSize; i++)\n                {\n                    m_Shapes[i] = new MeshBlendShape(reader);\n                }\n                reader.AlignStream();\n                var m_ShapeVerticesSize = reader.ReadInt32();\n                var m_ShapeVertices = new BlendShapeVertex[m_ShapeVerticesSize]; //MeshBlendShapeVertex\n                for (int i = 0; i < m_ShapeVerticesSize; i++)\n                {\n                    m_ShapeVertices[i] = new BlendShapeVertex(reader);\n                }\n            }\n        }\n    }\n\n    public enum GfxPrimitiveType\n    {\n        Triangles = 0,\n        TriangleStrip = 1,\n        Quads = 2,\n        Lines = 3,\n        LineStrip = 4,\n        Points = 5\n    };\n\n    public class SubMesh\n    {\n        public uint firstByte;\n        public uint indexCount;\n        public GfxPrimitiveType topology;\n        public uint triangleCount;\n        public uint baseVertex;\n        public uint firstVertex;\n        public uint vertexCount;\n        public AABB localAABB;\n\n        public SubMesh(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            firstByte = reader.ReadUInt32();\n            indexCount = reader.ReadUInt32();\n            topology = (GfxPrimitiveType)reader.ReadInt32();\n\n            if (version[0] < 4) //4.0 down\n            {\n                triangleCount = reader.ReadUInt32();\n            }\n\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up\n            {\n                baseVertex = reader.ReadUInt32();\n            }\n\n            if (version[0] >= 3) //3.0 and up\n            {\n                firstVertex = reader.ReadUInt32();\n                vertexCount = reader.ReadUInt32();\n                localAABB = new AABB(reader);\n            }\n        }\n    }\n\n    public sealed class Mesh : NamedObject\n    {\n        private bool m_Use16BitIndices = true;\n        public SubMesh[] m_SubMeshes;\n        private uint[] m_IndexBuffer;\n        public BlendShapeData m_Shapes;\n        public Matrix4x4[] m_BindPose;\n        public uint[] m_BoneNameHashes;\n        public int m_VertexCount;\n        public float[] m_Vertices;\n        public BoneWeights4[] m_Skin;\n        public float[] m_Normals;\n        public float[] m_Colors;\n        public float[] m_UV0;\n        public float[] m_UV1;\n        public float[] m_UV2;\n        public float[] m_UV3;\n        public float[] m_UV4;\n        public float[] m_UV5;\n        public float[] m_UV6;\n        public float[] m_UV7;\n        public float[] m_Tangents;\n        private VertexData m_VertexData;\n        private CompressedMesh m_CompressedMesh;\n        private StreamingInfo m_StreamData;\n\n        public List<uint> m_Indices = new List<uint>();\n\n        public Mesh(ObjectReader reader) : base(reader)\n        {\n            if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) //3.5 down\n            {\n                m_Use16BitIndices = reader.ReadInt32() > 0;\n            }\n\n            if (version[0] == 2 && version[1] <= 5) //2.5 and down\n            {\n                int m_IndexBuffer_size = reader.ReadInt32();\n\n                if (m_Use16BitIndices)\n                {\n                    m_IndexBuffer = new uint[m_IndexBuffer_size / 2];\n                    for (int i = 0; i < m_IndexBuffer_size / 2; i++)\n                    {\n                        m_IndexBuffer[i] = reader.ReadUInt16();\n                    }\n                    reader.AlignStream();\n                }\n                else\n                {\n                    m_IndexBuffer = reader.ReadUInt32Array(m_IndexBuffer_size / 4);\n                }\n            }\n\n            int m_SubMeshesSize = reader.ReadInt32();\n            m_SubMeshes = new SubMesh[m_SubMeshesSize];\n            for (int i = 0; i < m_SubMeshesSize; i++)\n            {\n                m_SubMeshes[i] = new SubMesh(reader);\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up\n            {\n                m_Shapes = new BlendShapeData(reader);\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_BindPose = reader.ReadMatrixArray();\n                m_BoneNameHashes = reader.ReadUInt32Array();\n                var m_RootBoneNameHash = reader.ReadUInt32();\n            }\n\n            if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up\n            {\n                if (version[0] >= 2019) //2019 and up\n                {\n                    var m_BonesAABBSize = reader.ReadInt32();\n                    var m_BonesAABB = new MinMaxAABB[m_BonesAABBSize];\n                    for (int i = 0; i < m_BonesAABBSize; i++)\n                    {\n                        m_BonesAABB[i] = new MinMaxAABB(reader);\n                    }\n\n                    var m_VariableBoneCountWeights = reader.ReadUInt32Array();\n                }\n\n                var m_MeshCompression = reader.ReadByte();\n                if (version[0] >= 4)\n                {\n                    if (version[0] < 5)\n                    {\n                        var m_StreamCompression = reader.ReadByte();\n                    }\n                    var m_IsReadable = reader.ReadBoolean();\n                    var m_KeepVertices = reader.ReadBoolean();\n                    var m_KeepIndices = reader.ReadBoolean();\n                }\n                reader.AlignStream();\n\n                //Unity fixed it in 2017.3.1p1 and later versions\n                if ((version[0] > 2017 || (version[0] == 2017 && version[1] >= 4)) || //2017.4\n                    ((version[0] == 2017 && version[1] == 3 && version[2] == 1) && buildType.IsPatch) || //fixed after 2017.3.1px\n                    ((version[0] == 2017 && version[1] == 3) && m_MeshCompression == 0))//2017.3.xfx with no compression\n                {\n                    var m_IndexFormat = reader.ReadInt32();\n                    m_Use16BitIndices = m_IndexFormat == 0;\n                }\n\n                int m_IndexBuffer_size = reader.ReadInt32();\n                if (m_Use16BitIndices)\n                {\n                    m_IndexBuffer = new uint[m_IndexBuffer_size / 2];\n                    for (int i = 0; i < m_IndexBuffer_size / 2; i++)\n                    {\n                        m_IndexBuffer[i] = reader.ReadUInt16();\n                    }\n                    reader.AlignStream();\n                }\n                else\n                {\n                    m_IndexBuffer = reader.ReadUInt32Array(m_IndexBuffer_size / 4);\n                }\n            }\n\n            if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) //3.4.2 and earlier\n            {\n                m_VertexCount = reader.ReadInt32();\n                m_Vertices = reader.ReadSingleArray(m_VertexCount * 3); //Vector3\n\n                m_Skin = new BoneWeights4[reader.ReadInt32()];\n                for (int s = 0; s < m_Skin.Length; s++)\n                {\n                    m_Skin[s] = new BoneWeights4(reader);\n                }\n\n                m_BindPose = reader.ReadMatrixArray();\n\n                m_UV0 = reader.ReadSingleArray(reader.ReadInt32() * 2); //Vector2\n\n                m_UV1 = reader.ReadSingleArray(reader.ReadInt32() * 2); //Vector2\n\n                if (version[0] == 2 && version[1] <= 5) //2.5 and down\n                {\n                    int m_TangentSpace_size = reader.ReadInt32();\n                    m_Normals = new float[m_TangentSpace_size * 3];\n                    m_Tangents = new float[m_TangentSpace_size * 4];\n                    for (int v = 0; v < m_TangentSpace_size; v++)\n                    {\n                        m_Normals[v * 3] = reader.ReadSingle();\n                        m_Normals[v * 3 + 1] = reader.ReadSingle();\n                        m_Normals[v * 3 + 2] = reader.ReadSingle();\n                        m_Tangents[v * 3] = reader.ReadSingle();\n                        m_Tangents[v * 3 + 1] = reader.ReadSingle();\n                        m_Tangents[v * 3 + 2] = reader.ReadSingle();\n                        m_Tangents[v * 3 + 3] = reader.ReadSingle(); //handedness\n                    }\n                }\n                else //2.6.0 and later\n                {\n                    m_Tangents = reader.ReadSingleArray(reader.ReadInt32() * 4); //Vector4\n\n                    m_Normals = reader.ReadSingleArray(reader.ReadInt32() * 3); //Vector3\n                }\n            }\n            else\n            {\n                if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down\n                {\n                    m_Skin = new BoneWeights4[reader.ReadInt32()];\n                    for (int s = 0; s < m_Skin.Length; s++)\n                    {\n                        m_Skin[s] = new BoneWeights4(reader);\n                    }\n                }\n\n                if (version[0] == 3 || (version[0] == 4 && version[1] <= 2)) //4.2 and down\n                {\n                    m_BindPose = reader.ReadMatrixArray();\n                }\n\n                m_VertexData = new VertexData(reader);\n            }\n\n            if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later\n            {\n                m_CompressedMesh = new CompressedMesh(reader);\n            }\n\n            reader.Position += 24; //AABB m_LocalAABB\n\n            if (version[0] < 3 || (version[0] == 3 && version[1] <= 4)) //3.4.2 and earlier\n            {\n                int m_Colors_size = reader.ReadInt32();\n                m_Colors = new float[m_Colors_size * 4];\n                for (int v = 0; v < m_Colors_size * 4; v++)\n                {\n                    m_Colors[v] = (float)reader.ReadByte() / 0xFF;\n                }\n\n                int m_CollisionTriangles_size = reader.ReadInt32();\n                reader.Position += m_CollisionTriangles_size * 4; //UInt32 indices\n                int m_CollisionVertexCount = reader.ReadInt32();\n            }\n\n            int m_MeshUsageFlags = reader.ReadInt32();\n\n            if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up\n            {\n                int m_CookingOptions = reader.ReadInt32();\n            }\n\n            if (version[0] >= 5) //5.0 and up\n            {\n                var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();\n                reader.AlignStream();\n                var m_BakedTriangleCollisionMesh = reader.ReadUInt8Array();\n                reader.AlignStream();\n            }\n\n            if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up\n            {\n                var m_MeshMetrics = new float[2];\n                m_MeshMetrics[0] = reader.ReadSingle();\n                m_MeshMetrics[1] = reader.ReadSingle();\n            }\n\n            if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up\n            {\n                reader.AlignStream();\n                m_StreamData = new StreamingInfo(reader);\n            }\n\n            ProcessData();\n        }\n\n        private void ProcessData()\n        {\n            if (!string.IsNullOrEmpty(m_StreamData?.path))\n            {\n                if (m_VertexData.m_VertexCount > 0)\n                {\n                    var resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);\n                    m_VertexData.m_DataSize = resourceReader.GetData();\n                }\n            }\n            if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up\n            {\n                ReadVertexData();\n            }\n\n            if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later\n            {\n                DecompressCompressedMesh();\n            }\n\n            GetTriangles();\n        }\n\n        private void ReadVertexData()\n        {\n            m_VertexCount = (int)m_VertexData.m_VertexCount;\n\n            for (var chn = 0; chn < m_VertexData.m_Channels.Length; chn++)\n            {\n                var m_Channel = m_VertexData.m_Channels[chn];\n                if (m_Channel.dimension > 0)\n                {\n                    var m_Stream = m_VertexData.m_Streams[m_Channel.stream];\n                    var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });\n                    if (channelMask.Get(chn))\n                    {\n                        if (version[0] < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor\n                        {\n                            m_Channel.dimension = 4;\n                        }\n\n                        var vertexFormat = MeshHelper.ToVertexFormat(m_Channel.format, version);\n                        var componentByteSize = (int)MeshHelper.GetFormatSize(vertexFormat);\n                        var componentBytes = new byte[m_VertexCount * m_Channel.dimension * componentByteSize];\n                        for (int v = 0; v < m_VertexCount; v++)\n                        {\n                            var vertexOffset = (int)m_Stream.offset + m_Channel.offset + (int)m_Stream.stride * v;\n                            for (int d = 0; d < m_Channel.dimension; d++)\n                            {\n                                var componentOffset = vertexOffset + componentByteSize * d;\n                                Buffer.BlockCopy(m_VertexData.m_DataSize, componentOffset, componentBytes, componentByteSize * (v * m_Channel.dimension + d), componentByteSize);\n                            }\n                        }\n\n                        if (reader.Endian == EndianType.BigEndian && componentByteSize > 1) //swap bytes\n                        {\n                            for (var i = 0; i < componentBytes.Length / componentByteSize; i++)\n                            {\n                                var buff = new byte[componentByteSize];\n                                Buffer.BlockCopy(componentBytes, i * componentByteSize, buff, 0, componentByteSize);\n                                buff = buff.Reverse().ToArray();\n                                Buffer.BlockCopy(buff, 0, componentBytes, i * componentByteSize, componentByteSize);\n                            }\n                        }\n\n                        int[] componentsIntArray = null;\n                        float[] componentsFloatArray = null;\n                        if (MeshHelper.IsIntFormat(vertexFormat))\n                            componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);\n                        else\n                            componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);\n\n                        if (version[0] >= 2018)\n                        {\n                            switch (chn)\n                            {\n                                case 0: //kShaderChannelVertex\n                                    m_Vertices = componentsFloatArray;\n                                    break;\n                                case 1: //kShaderChannelNormal\n                                    m_Normals = componentsFloatArray;\n                                    break;\n                                case 2: //kShaderChannelTangent\n                                    m_Tangents = componentsFloatArray;\n                                    break;\n                                case 3: //kShaderChannelColor\n                                    m_Colors = componentsFloatArray;\n                                    break;\n                                case 4: //kShaderChannelTexCoord0\n                                    m_UV0 = componentsFloatArray;\n                                    break;\n                                case 5: //kShaderChannelTexCoord1\n                                    m_UV1 = componentsFloatArray;\n                                    break;\n                                case 6: //kShaderChannelTexCoord2\n                                    m_UV2 = componentsFloatArray;\n                                    break;\n                                case 7: //kShaderChannelTexCoord3\n                                    m_UV3 = componentsFloatArray;\n                                    break;\n                                case 8: //kShaderChannelTexCoord4\n                                    m_UV4 = componentsFloatArray;\n                                    break;\n                                case 9: //kShaderChannelTexCoord5\n                                    m_UV5 = componentsFloatArray;\n                                    break;\n                                case 10: //kShaderChannelTexCoord6\n                                    m_UV6 = componentsFloatArray;\n                                    break;\n                                case 11: //kShaderChannelTexCoord7\n                                    m_UV7 = componentsFloatArray;\n                                    break;\n                                //2018.2 and up\n                                case 12: //kShaderChannelBlendWeight\n                                    if (m_Skin == null)\n                                    {\n                                        InitMSkin();\n                                    }\n                                    for (int i = 0; i < m_VertexCount; i++)\n                                    {\n                                        for (int j = 0; j < m_Channel.dimension; j++)\n                                        {\n                                            m_Skin[i].weight[j] = componentsFloatArray[i * m_Channel.dimension + j];\n                                        }\n                                    }\n                                    break;\n                                case 13: //kShaderChannelBlendIndices\n                                    if (m_Skin == null)\n                                    {\n                                        InitMSkin();\n                                    }\n                                    for (int i = 0; i < m_VertexCount; i++)\n                                    {\n                                        for (int j = 0; j < m_Channel.dimension; j++)\n                                        {\n                                            m_Skin[i].boneIndex[j] = componentsIntArray[i * m_Channel.dimension + j];\n                                        }\n                                    }\n                                    break;\n                            }\n                        }\n                        else\n                        {\n                            switch (chn)\n                            {\n                                case 0: //kShaderChannelVertex\n                                    m_Vertices = componentsFloatArray;\n                                    break;\n                                case 1: //kShaderChannelNormal\n                                    m_Normals = componentsFloatArray;\n                                    break;\n                                case 2: //kShaderChannelColor\n                                    m_Colors = componentsFloatArray;\n                                    break;\n                                case 3: //kShaderChannelTexCoord0\n                                    m_UV0 = componentsFloatArray;\n                                    break;\n                                case 4: //kShaderChannelTexCoord1\n                                    m_UV1 = componentsFloatArray;\n                                    break;\n                                case 5:\n                                    if (version[0] >= 5) //kShaderChannelTexCoord2\n                                    {\n                                        m_UV2 = componentsFloatArray;\n                                    }\n                                    else //kShaderChannelTangent\n                                    {\n                                        m_Tangents = componentsFloatArray;\n                                    }\n                                    break;\n                                case 6: //kShaderChannelTexCoord3\n                                    m_UV3 = componentsFloatArray;\n                                    break;\n                                case 7: //kShaderChannelTangent\n                                    m_Tangents = componentsFloatArray;\n                                    break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        private void DecompressCompressedMesh()\n        {\n            //Vertex\n            if (m_CompressedMesh.m_Vertices.m_NumItems > 0)\n            {\n                m_VertexCount = (int)m_CompressedMesh.m_Vertices.m_NumItems / 3;\n                m_Vertices = m_CompressedMesh.m_Vertices.UnpackFloats(3, 3 * 4);\n            }\n            //UV\n            if (m_CompressedMesh.m_UV.m_NumItems > 0)\n            {\n                var m_UVInfo = m_CompressedMesh.m_UVInfo;\n                if (m_UVInfo != 0)\n                {\n                    const int kInfoBitsPerUV = 4;\n                    const int kUVDimensionMask = 3;\n                    const int kUVChannelExists = 4;\n                    const int kMaxTexCoordShaderChannels = 8;\n\n                    int uvSrcOffset = 0;\n                    for (int uv = 0; uv < kMaxTexCoordShaderChannels; uv++)\n                    {\n                        var texCoordBits = m_UVInfo >> (uv * kInfoBitsPerUV);\n                        texCoordBits &= (1u << kInfoBitsPerUV) - 1u;\n                        if ((texCoordBits & kUVChannelExists) != 0)\n                        {\n                            var uvDim = 1 + (int)(texCoordBits & kUVDimensionMask);\n                            var m_UV = m_CompressedMesh.m_UV.UnpackFloats(uvDim, uvDim * 4, uvSrcOffset, m_VertexCount);\n                            SetUV(uv, m_UV);\n                            uvSrcOffset += uvDim * m_VertexCount;\n                        }\n                    }\n                }\n                else\n                {\n                    m_UV0 = m_CompressedMesh.m_UV.UnpackFloats(2, 2 * 4, 0, m_VertexCount);\n                    if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 4)\n                    {\n                        m_UV1 = m_CompressedMesh.m_UV.UnpackFloats(2, 2 * 4, m_VertexCount * 2, m_VertexCount);\n                    }\n                }\n            }\n            //BindPose\n            if (version[0] < 5)\n            {\n                if (m_CompressedMesh.m_BindPoses.m_NumItems > 0)\n                {\n                    m_BindPose = new Matrix4x4[m_CompressedMesh.m_BindPoses.m_NumItems / 16];\n                    var m_BindPoses_Unpacked = m_CompressedMesh.m_BindPoses.UnpackFloats(16, 4 * 16);\n                    var buffer = new float[16];\n                    for (int i = 0; i < m_BindPose.Length; i++)\n                    {\n                        Array.Copy(m_BindPoses_Unpacked, i * 16, buffer, 0, 16);\n                        m_BindPose[i] = new Matrix4x4(buffer);\n                    }\n                }\n            }\n            //Normal\n            if (m_CompressedMesh.m_Normals.m_NumItems > 0)\n            {\n                var normalData = m_CompressedMesh.m_Normals.UnpackFloats(2, 4 * 2);\n                var signs = m_CompressedMesh.m_NormalSigns.UnpackInts();\n                m_Normals = new float[m_CompressedMesh.m_Normals.m_NumItems / 2 * 3];\n                for (int i = 0; i < m_CompressedMesh.m_Normals.m_NumItems / 2; ++i)\n                {\n                    var x = normalData[i * 2 + 0];\n                    var y = normalData[i * 2 + 1];\n                    var zsqr = 1 - x * x - y * y;\n                    float z;\n                    if (zsqr >= 0f)\n                        z = (float)Math.Sqrt(zsqr);\n                    else\n                    {\n                        z = 0;\n                        var normal = new Vector3(x, y, z);\n                        normal.Normalize();\n                        x = normal.X;\n                        y = normal.Y;\n                        z = normal.Z;\n                    }\n                    if (signs[i] == 0)\n                        z = -z;\n                    m_Normals[i * 3] = x;\n                    m_Normals[i * 3 + 1] = y;\n                    m_Normals[i * 3 + 2] = z;\n                }\n            }\n            //Tangent\n            if (m_CompressedMesh.m_Tangents.m_NumItems > 0)\n            {\n                var tangentData = m_CompressedMesh.m_Tangents.UnpackFloats(2, 4 * 2);\n                var signs = m_CompressedMesh.m_TangentSigns.UnpackInts();\n                m_Tangents = new float[m_CompressedMesh.m_Tangents.m_NumItems / 2 * 4];\n                for (int i = 0; i < m_CompressedMesh.m_Tangents.m_NumItems / 2; ++i)\n                {\n                    var x = tangentData[i * 2 + 0];\n                    var y = tangentData[i * 2 + 1];\n                    var zsqr = 1 - x * x - y * y;\n                    float z;\n                    if (zsqr >= 0f)\n                        z = (float)Math.Sqrt(zsqr);\n                    else\n                    {\n                        z = 0;\n                        var vector3f = new Vector3(x, y, z);\n                        vector3f.Normalize();\n                        x = vector3f.X;\n                        y = vector3f.Y;\n                        z = vector3f.Z;\n                    }\n                    if (signs[i * 2 + 0] == 0)\n                        z = -z;\n                    var w = signs[i * 2 + 1] > 0 ? 1.0f : -1.0f;\n                    m_Tangents[i * 4] = x;\n                    m_Tangents[i * 4 + 1] = y;\n                    m_Tangents[i * 4 + 2] = z;\n                    m_Tangents[i * 4 + 3] = w;\n                }\n            }\n            //FloatColor\n            if (version[0] >= 5)\n            {\n                if (m_CompressedMesh.m_FloatColors.m_NumItems > 0)\n                {\n                    m_Colors = m_CompressedMesh.m_FloatColors.UnpackFloats(1, 4);\n                }\n            }\n            //Skin\n            if (m_CompressedMesh.m_Weights.m_NumItems > 0)\n            {\n                var weights = m_CompressedMesh.m_Weights.UnpackInts();\n                var boneIndices = m_CompressedMesh.m_BoneIndices.UnpackInts();\n\n                InitMSkin();\n\n                int bonePos = 0;\n                int boneIndexPos = 0;\n                int j = 0;\n                int sum = 0;\n\n                for (int i = 0; i < m_CompressedMesh.m_Weights.m_NumItems; i++)\n                {\n                    //read bone index and weight.\n                    m_Skin[bonePos].weight[j] = weights[i] / 31.0f;\n                    m_Skin[bonePos].boneIndex[j] = boneIndices[boneIndexPos++];\n                    j++;\n                    sum += weights[i];\n\n                    //the weights add up to one. fill the rest for this vertex with zero, and continue with next one.\n                    if (sum >= 31)\n                    {\n                        for (; j < 4; j++)\n                        {\n                            m_Skin[bonePos].weight[j] = 0;\n                            m_Skin[bonePos].boneIndex[j] = 0;\n                        }\n                        bonePos++;\n                        j = 0;\n                        sum = 0;\n                    }\n                    //we read three weights, but they don't add up to one. calculate the fourth one, and read\n                    //missing bone index. continue with next vertex.\n                    else if (j == 3)\n                    {\n                        m_Skin[bonePos].weight[j] = (31 - sum) / 31.0f;\n                        m_Skin[bonePos].boneIndex[j] = boneIndices[boneIndexPos++];\n                        bonePos++;\n                        j = 0;\n                        sum = 0;\n                    }\n                }\n            }\n            //IndexBuffer\n            if (m_CompressedMesh.m_Triangles.m_NumItems > 0)\n            {\n                m_IndexBuffer = Array.ConvertAll(m_CompressedMesh.m_Triangles.UnpackInts(), x => (uint)x);\n            }\n            //Color\n            if (m_CompressedMesh.m_Colors?.m_NumItems > 0)\n            {\n                m_CompressedMesh.m_Colors.m_NumItems *= 4;\n                m_CompressedMesh.m_Colors.m_BitSize /= 4;\n                var tempColors = m_CompressedMesh.m_Colors.UnpackInts();\n                m_Colors = new float[m_CompressedMesh.m_Colors.m_NumItems];\n                for (int v = 0; v < m_CompressedMesh.m_Colors.m_NumItems; v++)\n                {\n                    m_Colors[v] = tempColors[v] / 255f;\n                }\n            }\n        }\n\n        private void GetTriangles()\n        {\n            foreach (var m_SubMesh in m_SubMeshes)\n            {\n                var firstIndex = m_SubMesh.firstByte / 2;\n                if (!m_Use16BitIndices)\n                {\n                    firstIndex /= 2;\n                }\n                var indexCount = m_SubMesh.indexCount;\n                var topology = m_SubMesh.topology;\n                if (topology == GfxPrimitiveType.Triangles)\n                {\n                    for (int i = 0; i < indexCount; i += 3)\n                    {\n                        m_Indices.Add(m_IndexBuffer[firstIndex + i]);\n                        m_Indices.Add(m_IndexBuffer[firstIndex + i + 1]);\n                        m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);\n                    }\n                }\n                else if (version[0] < 4 || topology == GfxPrimitiveType.TriangleStrip)\n                {\n                    // de-stripify :\n                    uint triIndex = 0;\n                    for (int i = 0; i < indexCount - 2; i++)\n                    {\n                        var a = m_IndexBuffer[firstIndex + i];\n                        var b = m_IndexBuffer[firstIndex + i + 1];\n                        var c = m_IndexBuffer[firstIndex + i + 2];\n\n                        // skip degenerates\n                        if (a == b || a == c || b == c)\n                            continue;\n\n                        // do the winding flip-flop of strips :\n                        if ((i & 1) == 1)\n                        {\n                            m_Indices.Add(b);\n                            m_Indices.Add(a);\n                        }\n                        else\n                        {\n                            m_Indices.Add(a);\n                            m_Indices.Add(b);\n                        }\n                        m_Indices.Add(c);\n                        triIndex += 3;\n                    }\n                    //fix indexCount\n                    m_SubMesh.indexCount = triIndex;\n                }\n                else if (topology == GfxPrimitiveType.Quads)\n                {\n                    for (int q = 0; q < indexCount; q += 4)\n                    {\n                        m_Indices.Add(m_IndexBuffer[firstIndex + q]);\n                        m_Indices.Add(m_IndexBuffer[firstIndex + q + 1]);\n                        m_Indices.Add(m_IndexBuffer[firstIndex + q + 2]);\n                        m_Indices.Add(m_IndexBuffer[firstIndex + q]);\n                        m_Indices.Add(m_IndexBuffer[firstIndex + q + 2]);\n                        m_Indices.Add(m_IndexBuffer[firstIndex + q + 3]);\n                    }\n                    //fix indexCount\n                    m_SubMesh.indexCount = indexCount / 2 * 3;\n                }\n                else\n                {\n                    throw new NotSupportedException(\"Failed getting triangles. Submesh topology is lines or points.\");\n                }\n            }\n        }\n\n        private void InitMSkin()\n        {\n            m_Skin = new BoneWeights4[m_VertexCount];\n            for (int i = 0; i < m_VertexCount; i++)\n            {\n                m_Skin[i] = new BoneWeights4();\n            }\n        }\n\n        private void SetUV(int uv, float[] m_UV)\n        {\n            switch (uv)\n            {\n                case 0:\n                    m_UV0 = m_UV;\n                    break;\n                case 1:\n                    m_UV1 = m_UV;\n                    break;\n                case 2:\n                    m_UV2 = m_UV;\n                    break;\n                case 3:\n                    m_UV3 = m_UV;\n                    break;\n                case 4:\n                    m_UV4 = m_UV;\n                    break;\n                case 5:\n                    m_UV5 = m_UV;\n                    break;\n                case 6:\n                    m_UV6 = m_UV;\n                    break;\n                case 7:\n                    m_UV7 = m_UV;\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n        }\n\n        public float[] GetUV(int uv)\n        {\n            switch (uv)\n            {\n                case 0:\n                    return m_UV0;\n                case 1:\n                    return m_UV1;\n                case 2:\n                    return m_UV2;\n                case 3:\n                    return m_UV3;\n                case 4:\n                    return m_UV4;\n                case 5:\n                    return m_UV5;\n                case 6:\n                    return m_UV6;\n                case 7:\n                    return m_UV7;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n        }\n    }\n\n    public static class MeshHelper\n    {\n        public enum VertexChannelFormat\n        {\n            Float,\n            Float16,\n            Color,\n            Byte,\n            UInt32\n        }\n\n        public enum VertexFormat2017\n        {\n            Float,\n            Float16,\n            Color,\n            UNorm8,\n            SNorm8,\n            UNorm16,\n            SNorm16,\n            UInt8,\n            SInt8,\n            UInt16,\n            SInt16,\n            UInt32,\n            SInt32\n        }\n\n        public enum VertexFormat\n        {\n            Float,\n            Float16,\n            UNorm8,\n            SNorm8,\n            UNorm16,\n            SNorm16,\n            UInt8,\n            SInt8,\n            UInt16,\n            SInt16,\n            UInt32,\n            SInt32\n        }\n\n        public static VertexFormat ToVertexFormat(int format, int[] version)\n        {\n            if (version[0] < 2017)\n            {\n                switch ((VertexChannelFormat)format)\n                {\n                    case VertexChannelFormat.Float:\n                        return VertexFormat.Float;\n                    case VertexChannelFormat.Float16:\n                        return VertexFormat.Float16;\n                    case VertexChannelFormat.Color: //in 4.x is size 4\n                        return VertexFormat.UNorm8;\n                    case VertexChannelFormat.Byte:\n                        return VertexFormat.UInt8;\n                    case VertexChannelFormat.UInt32: //in 5.x\n                        return VertexFormat.UInt32;\n                    default:\n                        throw new ArgumentOutOfRangeException(nameof(format), format, null);\n                }\n            }\n            else if (version[0] < 2019)\n            {\n                switch ((VertexFormat2017)format)\n                {\n                    case VertexFormat2017.Float:\n                        return VertexFormat.Float;\n                    case VertexFormat2017.Float16:\n                        return VertexFormat.Float16;\n                    case VertexFormat2017.Color:\n                    case VertexFormat2017.UNorm8:\n                        return VertexFormat.UNorm8;\n                    case VertexFormat2017.SNorm8:\n                        return VertexFormat.SNorm8;\n                    case VertexFormat2017.UNorm16:\n                        return VertexFormat.UNorm16;\n                    case VertexFormat2017.SNorm16:\n                        return VertexFormat.SNorm16;\n                    case VertexFormat2017.UInt8:\n                        return VertexFormat.UInt8;\n                    case VertexFormat2017.SInt8:\n                        return VertexFormat.SInt8;\n                    case VertexFormat2017.UInt16:\n                        return VertexFormat.UInt16;\n                    case VertexFormat2017.SInt16:\n                        return VertexFormat.SInt16;\n                    case VertexFormat2017.UInt32:\n                        return VertexFormat.UInt32;\n                    case VertexFormat2017.SInt32:\n                        return VertexFormat.SInt32;\n                    default:\n                        throw new ArgumentOutOfRangeException(nameof(format), format, null);\n                }\n            }\n            else\n            {\n                return (VertexFormat)format;\n            }\n        }\n\n\n        public static uint GetFormatSize(VertexFormat format)\n        {\n            switch (format)\n            {\n                case VertexFormat.Float:\n                case VertexFormat.UInt32:\n                case VertexFormat.SInt32:\n                    return 4u;\n                case VertexFormat.Float16:\n                case VertexFormat.UNorm16:\n                case VertexFormat.SNorm16:\n                case VertexFormat.UInt16:\n                case VertexFormat.SInt16:\n                    return 2u;\n                case VertexFormat.UNorm8:\n                case VertexFormat.SNorm8:\n                case VertexFormat.UInt8:\n                case VertexFormat.SInt8:\n                    return 1u;\n                default:\n                    throw new ArgumentOutOfRangeException(nameof(format), format, null);\n            }\n        }\n\n        public static bool IsIntFormat(VertexFormat format)\n        {\n            return format >= VertexFormat.UInt8;\n        }\n\n        public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)\n        {\n            var size = GetFormatSize(format);\n            var len = inputBytes.Length / size;\n            var result = new float[len];\n            for (int i = 0; i < len; i++)\n            {\n                switch (format)\n                {\n                    case VertexFormat.Float:\n                        result[i] = BitConverter.ToSingle(inputBytes, i * 4);\n                        break;\n                    case VertexFormat.Float16:\n                        result[i] = Half.ToHalf(inputBytes, i * 2);\n                        break;\n                    case VertexFormat.UNorm8:\n                        result[i] = inputBytes[i] / 255f;\n                        break;\n                    case VertexFormat.SNorm8:\n                        result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);\n                        break;\n                    case VertexFormat.UNorm16:\n                        result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;\n                        break;\n                    case VertexFormat.SNorm16:\n                        result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);\n                        break;\n                }\n            }\n            return result;\n        }\n\n        public static int[] BytesToIntArray(byte[] inputBytes, VertexFormat format)\n        {\n            var size = GetFormatSize(format);\n            var len = inputBytes.Length / size;\n            var result = new int[len];\n            for (int i = 0; i < len; i++)\n            {\n                switch (format)\n                {\n                    case VertexFormat.UInt8:\n                    case VertexFormat.SInt8:\n                        result[i] = inputBytes[i];\n                        break;\n                    case VertexFormat.UInt16:\n                    case VertexFormat.SInt16:\n                        result[i] = BitConverter.ToInt16(inputBytes, i * 2);\n                        break;\n                    case VertexFormat.UInt32:\n                    case VertexFormat.SInt32:\n                        result[i] = BitConverter.ToInt32(inputBytes, i * 4);\n                        break;\n                }\n            }\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/MeshFilter.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class MeshFilter : Component\n    {\n        public PPtr<Mesh> m_Mesh;\n\n        public MeshFilter(ObjectReader reader) : base(reader)\n        {\n            m_Mesh = new PPtr<Mesh>(reader);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/MeshRenderer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class MeshRenderer : Renderer\n    {\n        public MeshRenderer(ObjectReader reader) : base(reader)\n        {\n\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/MonoBehaviour.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class MonoBehaviour : Behaviour\n    {\n        public PPtr<MonoScript> m_Script;\n        public string m_Name;\n\n        public MonoBehaviour(ObjectReader reader) : base(reader)\n        {\n            m_Script = new PPtr<MonoScript>(reader);\n            m_Name = reader.ReadAlignedString();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/MonoScript.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class MonoScript : NamedObject\n    {\n        public string m_ClassName;\n        public string m_Namespace;\n        public string m_AssemblyName;\n\n        public MonoScript(ObjectReader reader) : base(reader)\n        {\n            if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up\n            {\n                var m_ExecutionOrder = reader.ReadInt32();\n            }\n            if (version[0] < 5) //5.0 down\n            {\n                var m_PropertiesHash = reader.ReadUInt32();\n            }\n            else\n            {\n                var m_PropertiesHash = reader.ReadBytes(16);\n            }\n            if (version[0] < 3) //3.0 down\n            {\n                var m_PathName = reader.ReadAlignedString();\n            }\n            m_ClassName = reader.ReadAlignedString();\n            if (version[0] >= 3) //3.0 and up\n            {\n                m_Namespace = reader.ReadAlignedString();\n            }\n            m_AssemblyName = reader.ReadAlignedString();\n            if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down\n            {\n                var m_IsEditorScript = reader.ReadBoolean();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/MovieTexture.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class MovieTexture : Texture\n    {\n        public byte[] m_MovieData;\n        public PPtr<AudioClip> m_AudioClip;\n\n        public MovieTexture(ObjectReader reader) : base(reader)\n        {\n            var m_Loop = reader.ReadBoolean();\n            reader.AlignStream();\n            m_AudioClip = new PPtr<AudioClip>(reader);\n            m_MovieData = reader.ReadUInt8Array();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/NamedObject.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class NamedObject : EditorExtension\n    {\n        public string m_Name;\n\n        protected NamedObject(ObjectReader reader) : base(reader)\n        {\n            m_Name = reader.ReadAlignedString();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Object.cs",
    "content": "﻿using System.Collections.Specialized;\n\nnamespace AssetStudio\n{\n    public class Object\n    {\n        public SerializedFile assetsFile;\n        public ObjectReader reader;\n        public long m_PathID;\n        public int[] version;\n        protected BuildType buildType;\n        public BuildTarget platform;\n        public ClassIDType type;\n        public SerializedType serializedType;\n        public uint byteSize;\n\n        public Object(ObjectReader reader)\n        {\n            this.reader = reader;\n            reader.Reset();\n            assetsFile = reader.assetsFile;\n            type = reader.type;\n            m_PathID = reader.m_PathID;\n            version = reader.version;\n            buildType = reader.buildType;\n            platform = reader.platform;\n            serializedType = reader.serializedType;\n            byteSize = reader.byteSize;\n\n            if (platform == BuildTarget.NoTarget)\n            {\n                var m_ObjectHideFlags = reader.ReadUInt32();\n            }\n        }\n\n        public string Dump()\n        {\n            if (serializedType?.m_Type != null)\n            {\n                return TypeTreeHelper.ReadTypeString(serializedType.m_Type, reader);\n            }\n            return null;\n        }\n\n        public string Dump(TypeTree m_Type)\n        {\n            if (m_Type != null)\n            {\n                return TypeTreeHelper.ReadTypeString(m_Type, reader);\n            }\n            return null;\n        }\n\n        public OrderedDictionary ToType()\n        {\n            if (serializedType?.m_Type != null)\n            {\n                return TypeTreeHelper.ReadType(serializedType.m_Type, reader);\n            }\n            return null;\n        }\n\n        public OrderedDictionary ToType(TypeTree m_Type)\n        {\n            if (m_Type != null)\n            {\n                return TypeTreeHelper.ReadType(m_Type, reader);\n            }\n            return null;\n        }\n\n        public byte[] GetRawData()\n        {\n            reader.Reset();\n            return reader.ReadBytes((int)byteSize);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/PPtr.cs",
    "content": "﻿using System;\n\nnamespace AssetStudio\n{\n    public sealed class PPtr<T> where T : Object\n    {\n        public int m_FileID;\n        public long m_PathID;\n\n        private SerializedFile assetsFile;\n        private int index = -2; //-2 - Prepare, -1 - Missing\n\n        public PPtr(ObjectReader reader)\n        {\n            m_FileID = reader.ReadInt32();\n            m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();\n            assetsFile = reader.assetsFile;\n        }\n\n        private bool TryGetAssetsFile(out SerializedFile result)\n        {\n            result = null;\n            if (m_FileID == 0)\n            {\n                result = assetsFile;\n                return true;\n            }\n\n            if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)\n            {\n                var assetsManager = assetsFile.assetsManager;\n                var assetsFileList = assetsManager.assetsFileList;\n                var assetsFileIndexCache = assetsManager.assetsFileIndexCache;\n\n                if (index == -2)\n                {\n                    var m_External = assetsFile.m_Externals[m_FileID - 1];\n                    var name = m_External.fileName;\n                    if (!assetsFileIndexCache.TryGetValue(name, out index))\n                    {\n                        index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));\n                        assetsFileIndexCache.Add(name, index);\n                    }\n                }\n\n                if (index >= 0)\n                {\n                    result = assetsFileList[index];\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public bool TryGet(out T result)\n        {\n            if (TryGetAssetsFile(out var sourceFile))\n            {\n                if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))\n                {\n                    if (obj is T variable)\n                    {\n                        result = variable;\n                        return true;\n                    }\n                }\n            }\n\n            result = null;\n            return false;\n        }\n\n        public bool TryGet<T2>(out T2 result) where T2 : Object\n        {\n            if (TryGetAssetsFile(out var sourceFile))\n            {\n                if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))\n                {\n                    if (obj is T2 variable)\n                    {\n                        result = variable;\n                        return true;\n                    }\n                }\n            }\n\n            result = null;\n            return false;\n        }\n\n        public void Set(T m_Object)\n        {\n            var name = m_Object.assetsFile.fileName;\n            if (string.Equals(assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))\n            {\n                m_FileID = 0;\n            }\n            else\n            {\n                m_FileID = assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase));\n                if (m_FileID == -1)\n                {\n                    assetsFile.m_Externals.Add(new FileIdentifier\n                    {\n                        fileName = m_Object.assetsFile.fileName\n                    });\n                    m_FileID = assetsFile.m_Externals.Count;\n                }\n                else\n                {\n                    m_FileID += 1;\n                }\n            }\n\n            var assetsManager = assetsFile.assetsManager;\n            var assetsFileList = assetsManager.assetsFileList;\n            var assetsFileIndexCache = assetsManager.assetsFileIndexCache;\n\n            if (!assetsFileIndexCache.TryGetValue(name, out index))\n            {\n                index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));\n                assetsFileIndexCache.Add(name, index);\n            }\n\n            m_PathID = m_Object.m_PathID;\n        }\n\n        public bool IsNull => m_PathID == 0 || m_FileID < 0;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/PlayerSettings.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class PlayerSettings : Object\n    {\n        public string companyName;\n        public string productName;\n\n        public PlayerSettings(ObjectReader reader) : base(reader)\n        {\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4.0 nad up\n            {\n                var productGUID = reader.ReadBytes(16);\n            }\n\n            var AndroidProfiler = reader.ReadBoolean();\n            //bool AndroidFilterTouchesWhenObscured 2017.2 and up\n            //bool AndroidEnableSustainedPerformanceMode 2018 and up\n            reader.AlignStream();\n            int defaultScreenOrientation = reader.ReadInt32();\n            int targetDevice = reader.ReadInt32();\n            if (version[0] < 5 || (version[0] == 5 && version[1] < 3)) //5.3 down\n            {\n                if (version[0] < 5) //5.0 down\n                {\n                    int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics\n                    if (version[0] > 4 || (version[0] == 4 && version[1] >= 6)) //4.6 and up\n                    {\n                        var targetIOSGraphics = reader.ReadInt32();\n                    }\n                }\n                int targetResolution = reader.ReadInt32();\n            }\n            else\n            {\n                var useOnDemandResources = reader.ReadBoolean();\n                reader.AlignStream();\n            }\n            if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up\n            {\n                var accelerometerFrequency = reader.ReadInt32();\n            }\n            companyName = reader.ReadAlignedString();\n            productName = reader.ReadAlignedString();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/RectTransform.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class RectTransform : Transform\n    {\n        public RectTransform(ObjectReader reader) : base(reader)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Renderer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class StaticBatchInfo\n    {\n        public ushort firstSubMesh;\n        public ushort subMeshCount;\n\n        public StaticBatchInfo(ObjectReader reader)\n        {\n            firstSubMesh = reader.ReadUInt16();\n            subMeshCount = reader.ReadUInt16();\n        }\n    }\n\n    public abstract class Renderer : Component\n    {\n        public PPtr<Material>[] m_Materials;\n        public StaticBatchInfo m_StaticBatchInfo;\n        public uint[] m_SubsetIndices;\n\n        protected Renderer(ObjectReader reader) : base(reader)\n        {\n            if (version[0] < 5) //5.0 down\n            {\n                var m_Enabled = reader.ReadBoolean();\n                var m_CastShadows = reader.ReadBoolean();\n                var m_ReceiveShadows = reader.ReadBoolean();\n                var m_LightmapIndex = reader.ReadByte();\n            }\n            else //5.0 and up\n            {\n                if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up\n                {\n                    var m_Enabled = reader.ReadBoolean();\n                    var m_CastShadows = reader.ReadByte();\n                    var m_ReceiveShadows = reader.ReadByte();\n                    if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up\n                    {\n                        var m_DynamicOccludee = reader.ReadByte();\n                    }\n                    if (version[0] >= 2021) //2021.1 and up\n                    {\n                        var m_StaticShadowCaster = reader.ReadByte();\n                    }\n                    var m_MotionVectors = reader.ReadByte();\n                    var m_LightProbeUsage = reader.ReadByte();\n                    var m_ReflectionProbeUsage = reader.ReadByte();\n                    if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up\n                    {\n                        var m_RayTracingMode = reader.ReadByte();\n                    }\n                    if (version[0] >= 2020) //2020.1 and up\n                    {\n                        var m_RayTraceProcedural = reader.ReadByte();\n                    }\n                    reader.AlignStream();\n                }\n                else\n                {\n                    var m_Enabled = reader.ReadBoolean();\n                    reader.AlignStream();\n                    var m_CastShadows = reader.ReadByte();\n                    var m_ReceiveShadows = reader.ReadBoolean();\n                    reader.AlignStream();\n                }\n\n                if (version[0] >= 2018) //2018 and up\n                {\n                    var m_RenderingLayerMask = reader.ReadUInt32();\n                }\n\n                if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up\n                {\n                    var m_RendererPriority = reader.ReadInt32();\n                }\n\n                var m_LightmapIndex = reader.ReadUInt16();\n                var m_LightmapIndexDynamic = reader.ReadUInt16();\n            }\n\n            if (version[0] >= 3) //3.0 and up\n            {\n                var m_LightmapTilingOffset = reader.ReadVector4();\n            }\n\n            if (version[0] >= 5) //5.0 and up\n            {\n                var m_LightmapTilingOffsetDynamic = reader.ReadVector4();\n            }\n\n            var m_MaterialsSize = reader.ReadInt32();\n            m_Materials = new PPtr<Material>[m_MaterialsSize];\n            for (int i = 0; i < m_MaterialsSize; i++)\n            {\n                m_Materials[i] = new PPtr<Material>(reader);\n            }\n\n            if (version[0] < 3) //3.0 down\n            {\n                var m_LightmapTilingOffset = reader.ReadVector4();\n            }\n            else //3.0 and up\n            {\n                if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up\n                {\n                    m_StaticBatchInfo = new StaticBatchInfo(reader);\n                }\n                else\n                {\n                    m_SubsetIndices = reader.ReadUInt32Array();\n                }\n\n                var m_StaticBatchRoot = new PPtr<Transform>(reader);\n            }\n\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up\n            {\n                var m_ProbeAnchor = new PPtr<Transform>(reader);\n                var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);\n            }\n            else if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 - 5.3\n            {\n                var m_UseLightProbes = reader.ReadBoolean();\n                reader.AlignStream();\n\n                if (version[0] >= 5)//5.0 and up\n                {\n                    var m_ReflectionProbeUsage = reader.ReadInt32();\n                }\n\n                var m_LightProbeAnchor = new PPtr<Transform>(reader); //5.0 and up m_ProbeAnchor\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                if (version[0] == 4 && version[1] == 3) //4.3\n                {\n                    var m_SortingLayer = reader.ReadInt16();\n                }\n                else\n                {\n                    var m_SortingLayerID = reader.ReadUInt32();\n                }\n\n                //SInt16 m_SortingLayer 5.6 and up\n                var m_SortingOrder = reader.ReadInt16();\n                reader.AlignStream();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/ResourceManager.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace AssetStudio\n{\n    public class ResourceManager : Object\n    {\n        public KeyValuePair<string, PPtr<Object>>[] m_Container;\n\n        public ResourceManager(ObjectReader reader) : base(reader)\n        {\n            var m_ContainerSize = reader.ReadInt32();\n            m_Container = new KeyValuePair<string, PPtr<Object>>[m_ContainerSize];\n            for (int i = 0; i < m_ContainerSize; i++)\n            {\n                m_Container[i] = new KeyValuePair<string, PPtr<Object>>(reader.ReadAlignedString(), new PPtr<Object>(reader));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/RuntimeAnimatorController.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public abstract class RuntimeAnimatorController : NamedObject\n    {\n        protected RuntimeAnimatorController(ObjectReader reader) : base(reader)\n        {\n\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Shader.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\nnamespace AssetStudio\n{\n    public class Hash128\n    {\n        public byte[] bytes;\n\n        public Hash128(BinaryReader reader)\n        {\n            bytes = reader.ReadBytes(16);\n        }\n    }\n\n    public class StructParameter\n    {\n        public MatrixParameter[] m_MatrixParams;\n        public VectorParameter[] m_VectorParams;\n\n        public StructParameter(BinaryReader reader)\n        {\n            var m_NameIndex = reader.ReadInt32();\n            var m_Index = reader.ReadInt32();\n            var m_ArraySize = reader.ReadInt32();\n            var m_StructSize = reader.ReadInt32();\n\n            int numVectorParams = reader.ReadInt32();\n            m_VectorParams = new VectorParameter[numVectorParams];\n            for (int i = 0; i < numVectorParams; i++)\n            {\n                m_VectorParams[i] = new VectorParameter(reader);\n            }\n\n            int numMatrixParams = reader.ReadInt32();\n            m_MatrixParams = new MatrixParameter[numMatrixParams];\n            for (int i = 0; i < numMatrixParams; i++)\n            {\n                m_MatrixParams[i] = new MatrixParameter(reader);\n            }\n        }\n    }\n\n    public class SamplerParameter\n    {\n        public uint sampler;\n        public int bindPoint;\n\n        public SamplerParameter(BinaryReader reader)\n        {\n            sampler = reader.ReadUInt32();\n            bindPoint = reader.ReadInt32();\n        }\n    }\n    public enum TextureDimension\n    {\n        Unknown = -1,\n        None = 0,\n        Any = 1,\n        Tex2D = 2,\n        Tex3D = 3,\n        Cube = 4,\n        Tex2DArray = 5,\n        CubeArray = 6\n    };\n\n    public class SerializedTextureProperty\n    {\n        public string m_DefaultName;\n        public TextureDimension m_TexDim;\n\n        public SerializedTextureProperty(BinaryReader reader)\n        {\n            m_DefaultName = reader.ReadAlignedString();\n            m_TexDim = (TextureDimension)reader.ReadInt32();\n        }\n    }\n\n    public enum SerializedPropertyType\n    {\n        Color = 0,\n        Vector = 1,\n        Float = 2,\n        Range = 3,\n        Texture = 4,\n        Int = 5\n    };\n\n    public class SerializedProperty\n    {\n        public string m_Name;\n        public string m_Description;\n        public string[] m_Attributes;\n        public SerializedPropertyType m_Type;\n        public uint m_Flags;\n        public float[] m_DefValue;\n        public SerializedTextureProperty m_DefTexture;\n\n        public SerializedProperty(BinaryReader reader)\n        {\n            m_Name = reader.ReadAlignedString();\n            m_Description = reader.ReadAlignedString();\n            m_Attributes = reader.ReadStringArray();\n            m_Type = (SerializedPropertyType)reader.ReadInt32();\n            m_Flags = reader.ReadUInt32();\n            m_DefValue = reader.ReadSingleArray(4);\n            m_DefTexture = new SerializedTextureProperty(reader);\n        }\n    }\n\n    public class SerializedProperties\n    {\n        public SerializedProperty[] m_Props;\n\n        public SerializedProperties(BinaryReader reader)\n        {\n            int numProps = reader.ReadInt32();\n            m_Props = new SerializedProperty[numProps];\n            for (int i = 0; i < numProps; i++)\n            {\n                m_Props[i] = new SerializedProperty(reader);\n            }\n        }\n    }\n\n    public class SerializedShaderFloatValue\n    {\n        public float val;\n        public string name;\n\n        public SerializedShaderFloatValue(BinaryReader reader)\n        {\n            val = reader.ReadSingle();\n            name = reader.ReadAlignedString();\n        }\n    }\n\n    public class SerializedShaderRTBlendState\n    {\n        public SerializedShaderFloatValue srcBlend;\n        public SerializedShaderFloatValue destBlend;\n        public SerializedShaderFloatValue srcBlendAlpha;\n        public SerializedShaderFloatValue destBlendAlpha;\n        public SerializedShaderFloatValue blendOp;\n        public SerializedShaderFloatValue blendOpAlpha;\n        public SerializedShaderFloatValue colMask;\n\n        public SerializedShaderRTBlendState(BinaryReader reader)\n        {\n            srcBlend = new SerializedShaderFloatValue(reader);\n            destBlend = new SerializedShaderFloatValue(reader);\n            srcBlendAlpha = new SerializedShaderFloatValue(reader);\n            destBlendAlpha = new SerializedShaderFloatValue(reader);\n            blendOp = new SerializedShaderFloatValue(reader);\n            blendOpAlpha = new SerializedShaderFloatValue(reader);\n            colMask = new SerializedShaderFloatValue(reader);\n        }\n    }\n\n    public class SerializedStencilOp\n    {\n        public SerializedShaderFloatValue pass;\n        public SerializedShaderFloatValue fail;\n        public SerializedShaderFloatValue zFail;\n        public SerializedShaderFloatValue comp;\n\n        public SerializedStencilOp(BinaryReader reader)\n        {\n            pass = new SerializedShaderFloatValue(reader);\n            fail = new SerializedShaderFloatValue(reader);\n            zFail = new SerializedShaderFloatValue(reader);\n            comp = new SerializedShaderFloatValue(reader);\n        }\n    }\n\n    public class SerializedShaderVectorValue\n    {\n        public SerializedShaderFloatValue x;\n        public SerializedShaderFloatValue y;\n        public SerializedShaderFloatValue z;\n        public SerializedShaderFloatValue w;\n        public string name;\n\n        public SerializedShaderVectorValue(BinaryReader reader)\n        {\n            x = new SerializedShaderFloatValue(reader);\n            y = new SerializedShaderFloatValue(reader);\n            z = new SerializedShaderFloatValue(reader);\n            w = new SerializedShaderFloatValue(reader);\n            name = reader.ReadAlignedString();\n        }\n    }\n\n    public enum FogMode\n    {\n        Unknown = -1,\n        Disabled = 0,\n        Linear = 1,\n        Exp = 2,\n        Exp2 = 3\n    };\n\n    public class SerializedShaderState\n    {\n        public string m_Name;\n        public SerializedShaderRTBlendState[] rtBlend;\n        public bool rtSeparateBlend;\n        public SerializedShaderFloatValue zClip;\n        public SerializedShaderFloatValue zTest;\n        public SerializedShaderFloatValue zWrite;\n        public SerializedShaderFloatValue culling;\n        public SerializedShaderFloatValue conservative;\n        public SerializedShaderFloatValue offsetFactor;\n        public SerializedShaderFloatValue offsetUnits;\n        public SerializedShaderFloatValue alphaToMask;\n        public SerializedStencilOp stencilOp;\n        public SerializedStencilOp stencilOpFront;\n        public SerializedStencilOp stencilOpBack;\n        public SerializedShaderFloatValue stencilReadMask;\n        public SerializedShaderFloatValue stencilWriteMask;\n        public SerializedShaderFloatValue stencilRef;\n        public SerializedShaderFloatValue fogStart;\n        public SerializedShaderFloatValue fogEnd;\n        public SerializedShaderFloatValue fogDensity;\n        public SerializedShaderVectorValue fogColor;\n        public FogMode fogMode;\n        public int gpuProgramID;\n        public SerializedTagMap m_Tags;\n        public int m_LOD;\n        public bool lighting;\n\n        public SerializedShaderState(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_Name = reader.ReadAlignedString();\n            rtBlend = new SerializedShaderRTBlendState[8];\n            for (int i = 0; i < 8; i++)\n            {\n                rtBlend[i] = new SerializedShaderRTBlendState(reader);\n            }\n            rtSeparateBlend = reader.ReadBoolean();\n            reader.AlignStream();\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up\n            {\n                zClip = new SerializedShaderFloatValue(reader);\n            }\n            zTest = new SerializedShaderFloatValue(reader);\n            zWrite = new SerializedShaderFloatValue(reader);\n            culling = new SerializedShaderFloatValue(reader);\n            if (version[0] >= 2020) //2020.1 and up\n            {\n                conservative = new SerializedShaderFloatValue(reader);\n            }\n            offsetFactor = new SerializedShaderFloatValue(reader);\n            offsetUnits = new SerializedShaderFloatValue(reader);\n            alphaToMask = new SerializedShaderFloatValue(reader);\n            stencilOp = new SerializedStencilOp(reader);\n            stencilOpFront = new SerializedStencilOp(reader);\n            stencilOpBack = new SerializedStencilOp(reader);\n            stencilReadMask = new SerializedShaderFloatValue(reader);\n            stencilWriteMask = new SerializedShaderFloatValue(reader);\n            stencilRef = new SerializedShaderFloatValue(reader);\n            fogStart = new SerializedShaderFloatValue(reader);\n            fogEnd = new SerializedShaderFloatValue(reader);\n            fogDensity = new SerializedShaderFloatValue(reader);\n            fogColor = new SerializedShaderVectorValue(reader);\n            fogMode = (FogMode)reader.ReadInt32();\n            gpuProgramID = reader.ReadInt32();\n            m_Tags = new SerializedTagMap(reader);\n            m_LOD = reader.ReadInt32();\n            lighting = reader.ReadBoolean();\n            reader.AlignStream();\n        }\n    }\n\n    public class ShaderBindChannel\n    {\n        public sbyte source;\n        public sbyte target;\n\n        public ShaderBindChannel(BinaryReader reader)\n        {\n            source = reader.ReadSByte();\n            target = reader.ReadSByte();\n        }\n    }\n\n    public class ParserBindChannels\n    {\n        public ShaderBindChannel[] m_Channels;\n        public uint m_SourceMap;\n\n        public ParserBindChannels(BinaryReader reader)\n        {\n            int numChannels = reader.ReadInt32();\n            m_Channels = new ShaderBindChannel[numChannels];\n            for (int i = 0; i < numChannels; i++)\n            {\n                m_Channels[i] = new ShaderBindChannel(reader);\n            }\n            reader.AlignStream();\n\n            m_SourceMap = reader.ReadUInt32();\n        }\n    }\n\n    public class VectorParameter\n    {\n        public int m_NameIndex;\n        public int m_Index;\n        public int m_ArraySize;\n        public sbyte m_Type;\n        public sbyte m_Dim;\n\n        public VectorParameter(BinaryReader reader)\n        {\n            m_NameIndex = reader.ReadInt32();\n            m_Index = reader.ReadInt32();\n            m_ArraySize = reader.ReadInt32();\n            m_Type = reader.ReadSByte();\n            m_Dim = reader.ReadSByte();\n            reader.AlignStream();\n        }\n    }\n\n    public class MatrixParameter\n    {\n        public int m_NameIndex;\n        public int m_Index;\n        public int m_ArraySize;\n        public sbyte m_Type;\n        public sbyte m_RowCount;\n\n        public MatrixParameter(BinaryReader reader)\n        {\n            m_NameIndex = reader.ReadInt32();\n            m_Index = reader.ReadInt32();\n            m_ArraySize = reader.ReadInt32();\n            m_Type = reader.ReadSByte();\n            m_RowCount = reader.ReadSByte();\n            reader.AlignStream();\n        }\n    }\n\n    public class TextureParameter\n    {\n        public int m_NameIndex;\n        public int m_Index;\n        public int m_SamplerIndex;\n        public sbyte m_Dim;\n\n        public TextureParameter(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_NameIndex = reader.ReadInt32();\n            m_Index = reader.ReadInt32();\n            m_SamplerIndex = reader.ReadInt32();\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up\n            {\n                var m_MultiSampled = reader.ReadBoolean();\n            }\n            m_Dim = reader.ReadSByte();\n            reader.AlignStream();\n        }\n    }\n\n    public class BufferBinding\n    {\n        public int m_NameIndex;\n        public int m_Index;\n        public int m_ArraySize;\n\n        public BufferBinding(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_NameIndex = reader.ReadInt32();\n            m_Index = reader.ReadInt32();\n            if (version[0] >= 2020) //2020.1 and up\n            {\n                m_ArraySize = reader.ReadInt32();\n            }\n        }\n    }\n\n    public class ConstantBuffer\n    {\n        public int m_NameIndex;\n        public MatrixParameter[] m_MatrixParams;\n        public VectorParameter[] m_VectorParams;\n        public StructParameter[] m_StructParams;\n        public int m_Size;\n        public bool m_IsPartialCB;\n\n        public ConstantBuffer(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_NameIndex = reader.ReadInt32();\n\n            int numMatrixParams = reader.ReadInt32();\n            m_MatrixParams = new MatrixParameter[numMatrixParams];\n            for (int i = 0; i < numMatrixParams; i++)\n            {\n                m_MatrixParams[i] = new MatrixParameter(reader);\n            }\n\n            int numVectorParams = reader.ReadInt32();\n            m_VectorParams = new VectorParameter[numVectorParams];\n            for (int i = 0; i < numVectorParams; i++)\n            {\n                m_VectorParams[i] = new VectorParameter(reader);\n            }\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up\n            {\n                int numStructParams = reader.ReadInt32();\n                m_StructParams = new StructParameter[numStructParams];\n                for (int i = 0; i < numStructParams; i++)\n                {\n                    m_StructParams[i] = new StructParameter(reader);\n                }\n            }\n            m_Size = reader.ReadInt32();\n\n            if ((version[0] == 2020 && version[1] > 3) ||\n               (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up\n               (version[0] > 2021) ||\n               (version[0] == 2021 && version[1] > 1) ||\n               (version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up\n            {\n                m_IsPartialCB = reader.ReadBoolean();\n                reader.AlignStream();\n            }\n        }\n    }\n\n    public class UAVParameter\n    {\n        public int m_NameIndex;\n        public int m_Index;\n        public int m_OriginalIndex;\n\n        public UAVParameter(BinaryReader reader)\n        {\n            m_NameIndex = reader.ReadInt32();\n            m_Index = reader.ReadInt32();\n            m_OriginalIndex = reader.ReadInt32();\n        }\n    }\n\n    public enum ShaderGpuProgramType\n    {\n        Unknown = 0,\n        GLLegacy = 1,\n        GLES31AEP = 2,\n        GLES31 = 3,\n        GLES3 = 4,\n        GLES = 5,\n        GLCore32 = 6,\n        GLCore41 = 7,\n        GLCore43 = 8,\n        DX9VertexSM20 = 9,\n        DX9VertexSM30 = 10,\n        DX9PixelSM20 = 11,\n        DX9PixelSM30 = 12,\n        DX10Level9Vertex = 13,\n        DX10Level9Pixel = 14,\n        DX11VertexSM40 = 15,\n        DX11VertexSM50 = 16,\n        DX11PixelSM40 = 17,\n        DX11PixelSM50 = 18,\n        DX11GeometrySM40 = 19,\n        DX11GeometrySM50 = 20,\n        DX11HullSM50 = 21,\n        DX11DomainSM50 = 22,\n        MetalVS = 23,\n        MetalFS = 24,\n        SPIRV = 25,\n        ConsoleVS = 26,\n        ConsoleFS = 27,\n        ConsoleHS = 28,\n        ConsoleDS = 29,\n        ConsoleGS = 30,\n        RayTracing = 31,\n        PS5NGGC = 32\n    };\n\n    public class SerializedProgramParameters\n    {\n        public VectorParameter[] m_VectorParams;\n        public MatrixParameter[] m_MatrixParams;\n        public TextureParameter[] m_TextureParams;\n        public BufferBinding[] m_BufferParams;\n        public ConstantBuffer[] m_ConstantBuffers;\n        public BufferBinding[] m_ConstantBufferBindings;\n        public UAVParameter[] m_UAVParams;\n        public SamplerParameter[] m_Samplers;\n\n        public SerializedProgramParameters(ObjectReader reader)\n        {\n            int numVectorParams = reader.ReadInt32();\n            m_VectorParams = new VectorParameter[numVectorParams];\n            for (int i = 0; i < numVectorParams; i++)\n            {\n                m_VectorParams[i] = new VectorParameter(reader);\n            }\n\n            int numMatrixParams = reader.ReadInt32();\n            m_MatrixParams = new MatrixParameter[numMatrixParams];\n            for (int i = 0; i < numMatrixParams; i++)\n            {\n                m_MatrixParams[i] = new MatrixParameter(reader);\n            }\n\n            int numTextureParams = reader.ReadInt32();\n            m_TextureParams = new TextureParameter[numTextureParams];\n            for (int i = 0; i < numTextureParams; i++)\n            {\n                m_TextureParams[i] = new TextureParameter(reader);\n            }\n\n            int numBufferParams = reader.ReadInt32();\n            m_BufferParams = new BufferBinding[numBufferParams];\n            for (int i = 0; i < numBufferParams; i++)\n            {\n                m_BufferParams[i] = new BufferBinding(reader);\n            }\n\n            int numConstantBuffers = reader.ReadInt32();\n            m_ConstantBuffers = new ConstantBuffer[numConstantBuffers];\n            for (int i = 0; i < numConstantBuffers; i++)\n            {\n                m_ConstantBuffers[i] = new ConstantBuffer(reader);\n            }\n\n            int numConstantBufferBindings = reader.ReadInt32();\n            m_ConstantBufferBindings = new BufferBinding[numConstantBufferBindings];\n            for (int i = 0; i < numConstantBufferBindings; i++)\n            {\n                m_ConstantBufferBindings[i] = new BufferBinding(reader);\n            }\n\n            int numUAVParams = reader.ReadInt32();\n            m_UAVParams = new UAVParameter[numUAVParams];\n            for (int i = 0; i < numUAVParams; i++)\n            {\n                m_UAVParams[i] = new UAVParameter(reader);\n            }\n\n            int numSamplers = reader.ReadInt32();\n            m_Samplers = new SamplerParameter[numSamplers];\n            for (int i = 0; i < numSamplers; i++)\n            {\n                m_Samplers[i] = new SamplerParameter(reader);\n            }\n        }\n    }\n\n    public class SerializedSubProgram\n    {\n        public uint m_BlobIndex;\n        public ParserBindChannels m_Channels;\n        public ushort[] m_KeywordIndices;\n        public sbyte m_ShaderHardwareTier;\n        public ShaderGpuProgramType m_GpuProgramType;\n        public SerializedProgramParameters m_Parameters;\n        public VectorParameter[] m_VectorParams;\n        public MatrixParameter[] m_MatrixParams;\n        public TextureParameter[] m_TextureParams;\n        public BufferBinding[] m_BufferParams;\n        public ConstantBuffer[] m_ConstantBuffers;\n        public BufferBinding[] m_ConstantBufferBindings;\n        public UAVParameter[] m_UAVParams;\n        public SamplerParameter[] m_Samplers;\n\n        public SerializedSubProgram(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_BlobIndex = reader.ReadUInt32();\n            m_Channels = new ParserBindChannels(reader);\n\n            if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1\n            {\n                var m_GlobalKeywordIndices = reader.ReadUInt16Array();\n                reader.AlignStream();\n                var m_LocalKeywordIndices = reader.ReadUInt16Array();\n                reader.AlignStream();\n            }\n            else\n            {\n                m_KeywordIndices = reader.ReadUInt16Array();\n                if (version[0] >= 2017) //2017 and up\n                {\n                    reader.AlignStream();\n                }\n            }\n\n            m_ShaderHardwareTier = reader.ReadSByte();\n            m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();\n            reader.AlignStream();\n\n            if ((version[0] == 2020 && version[1] > 3) ||\n               (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up\n               (version[0] > 2021) ||\n               (version[0] == 2021 && version[1] > 1) ||\n               (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up\n            {\n                m_Parameters = new SerializedProgramParameters(reader);\n            }\n            else\n            {\n                int numVectorParams = reader.ReadInt32();\n                m_VectorParams = new VectorParameter[numVectorParams];\n                for (int i = 0; i < numVectorParams; i++)\n                {\n                    m_VectorParams[i] = new VectorParameter(reader);\n                }\n\n                int numMatrixParams = reader.ReadInt32();\n                m_MatrixParams = new MatrixParameter[numMatrixParams];\n                for (int i = 0; i < numMatrixParams; i++)\n                {\n                    m_MatrixParams[i] = new MatrixParameter(reader);\n                }\n\n                int numTextureParams = reader.ReadInt32();\n                m_TextureParams = new TextureParameter[numTextureParams];\n                for (int i = 0; i < numTextureParams; i++)\n                {\n                    m_TextureParams[i] = new TextureParameter(reader);\n                }\n\n                int numBufferParams = reader.ReadInt32();\n                m_BufferParams = new BufferBinding[numBufferParams];\n                for (int i = 0; i < numBufferParams; i++)\n                {\n                    m_BufferParams[i] = new BufferBinding(reader);\n                }\n\n                int numConstantBuffers = reader.ReadInt32();\n                m_ConstantBuffers = new ConstantBuffer[numConstantBuffers];\n                for (int i = 0; i < numConstantBuffers; i++)\n                {\n                    m_ConstantBuffers[i] = new ConstantBuffer(reader);\n                }\n\n                int numConstantBufferBindings = reader.ReadInt32();\n                m_ConstantBufferBindings = new BufferBinding[numConstantBufferBindings];\n                for (int i = 0; i < numConstantBufferBindings; i++)\n                {\n                    m_ConstantBufferBindings[i] = new BufferBinding(reader);\n                }\n\n                int numUAVParams = reader.ReadInt32();\n                m_UAVParams = new UAVParameter[numUAVParams];\n                for (int i = 0; i < numUAVParams; i++)\n                {\n                    m_UAVParams[i] = new UAVParameter(reader);\n                }\n\n                if (version[0] >= 2017) //2017 and up\n                {\n                    int numSamplers = reader.ReadInt32();\n                    m_Samplers = new SamplerParameter[numSamplers];\n                    for (int i = 0; i < numSamplers; i++)\n                    {\n                        m_Samplers[i] = new SamplerParameter(reader);\n                    }\n                }\n            }\n\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up\n            {\n                if (version[0] >= 2021) //2021.1 and up\n                {\n                    var m_ShaderRequirements = reader.ReadInt64();\n                }\n                else\n                {\n                    var m_ShaderRequirements = reader.ReadInt32();\n                }\n            }\n        }\n    }\n\n    public class SerializedProgram\n    {\n        public SerializedSubProgram[] m_SubPrograms;\n        public SerializedProgramParameters m_CommonParameters;\n        public ushort[] m_SerializedKeywordStateMask;\n\n        public SerializedProgram(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            int numSubPrograms = reader.ReadInt32();\n            m_SubPrograms = new SerializedSubProgram[numSubPrograms];\n            for (int i = 0; i < numSubPrograms; i++)\n            {\n                m_SubPrograms[i] = new SerializedSubProgram(reader);\n            }\n\n            if ((version[0] == 2020 && version[1] > 3) ||\n               (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up\n               (version[0] > 2021) ||\n               (version[0] == 2021 && version[1] > 1) ||\n               (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up\n            {\n                m_CommonParameters = new SerializedProgramParameters(reader);\n            }\n\n            if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up\n            {\n                m_SerializedKeywordStateMask = reader.ReadUInt16Array();\n                reader.AlignStream();\n            }\n        }\n    }\n\n    public enum PassType\n    {\n        Normal = 0,\n        Use = 1,\n        Grab = 2\n    };\n\n    public class SerializedPass\n    {\n        public Hash128[] m_EditorDataHash;\n        public byte[] m_Platforms;\n        public ushort[] m_LocalKeywordMask;\n        public ushort[] m_GlobalKeywordMask;\n        public KeyValuePair<string, int>[] m_NameIndices;\n        public PassType m_Type;\n        public SerializedShaderState m_State;\n        public uint m_ProgramMask;\n        public SerializedProgram progVertex;\n        public SerializedProgram progFragment;\n        public SerializedProgram progGeometry;\n        public SerializedProgram progHull;\n        public SerializedProgram progDomain;\n        public SerializedProgram progRayTracing;\n        public bool m_HasInstancingVariant;\n        public string m_UseName;\n        public string m_Name;\n        public string m_TextureName;\n        public SerializedTagMap m_Tags;\n        public ushort[] m_SerializedKeywordStateMask;\n\n        public SerializedPass(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up\n            {\n                int numEditorDataHash = reader.ReadInt32();\n                m_EditorDataHash = new Hash128[numEditorDataHash];\n                for (int i = 0; i < numEditorDataHash; i++)\n                {\n                    m_EditorDataHash[i] = new Hash128(reader);\n                }\n                reader.AlignStream();\n                m_Platforms = reader.ReadUInt8Array();\n                reader.AlignStream();\n                if (version[0] < 2021 || (version[0] == 2021 && version[1] < 2)) //2021.1 and down\n                {\n                    m_LocalKeywordMask = reader.ReadUInt16Array();\n                    reader.AlignStream();\n                    m_GlobalKeywordMask = reader.ReadUInt16Array();\n                    reader.AlignStream();\n                }\n            }\n\n            int numIndices = reader.ReadInt32();\n            m_NameIndices = new KeyValuePair<string, int>[numIndices];\n            for (int i = 0; i < numIndices; i++)\n            {\n                m_NameIndices[i] = new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32());\n            }\n\n            m_Type = (PassType)reader.ReadInt32();\n            m_State = new SerializedShaderState(reader);\n            m_ProgramMask = reader.ReadUInt32();\n            progVertex = new SerializedProgram(reader);\n            progFragment = new SerializedProgram(reader);\n            progGeometry = new SerializedProgram(reader);\n            progHull = new SerializedProgram(reader);\n            progDomain = new SerializedProgram(reader);\n            if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up\n            {\n                progRayTracing = new SerializedProgram(reader);\n            }\n            m_HasInstancingVariant = reader.ReadBoolean();\n            if (version[0] >= 2018) //2018 and up\n            {\n                var m_HasProceduralInstancingVariant = reader.ReadBoolean();\n            }\n            reader.AlignStream();\n            m_UseName = reader.ReadAlignedString();\n            m_Name = reader.ReadAlignedString();\n            m_TextureName = reader.ReadAlignedString();\n            m_Tags = new SerializedTagMap(reader);\n            if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x\n            {\n                m_SerializedKeywordStateMask = reader.ReadUInt16Array();\n                reader.AlignStream();\n            }\n        }\n    }\n\n    public class SerializedTagMap\n    {\n        public KeyValuePair<string, string>[] tags;\n\n        public SerializedTagMap(BinaryReader reader)\n        {\n            int numTags = reader.ReadInt32();\n            tags = new KeyValuePair<string, string>[numTags];\n            for (int i = 0; i < numTags; i++)\n            {\n                tags[i] = new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString());\n            }\n        }\n    }\n\n    public class SerializedSubShader\n    {\n        public SerializedPass[] m_Passes;\n        public SerializedTagMap m_Tags;\n        public int m_LOD;\n\n        public SerializedSubShader(ObjectReader reader)\n        {\n            int numPasses = reader.ReadInt32();\n            m_Passes = new SerializedPass[numPasses];\n            for (int i = 0; i < numPasses; i++)\n            {\n                m_Passes[i] = new SerializedPass(reader);\n            }\n\n            m_Tags = new SerializedTagMap(reader);\n            m_LOD = reader.ReadInt32();\n        }\n    }\n\n    public class SerializedShaderDependency\n    {\n        public string from;\n        public string to;\n\n        public SerializedShaderDependency(BinaryReader reader)\n        {\n            from = reader.ReadAlignedString();\n            to = reader.ReadAlignedString();\n        }\n    }\n\n    public class SerializedCustomEditorForRenderPipeline\n    {\n        public string customEditorName;\n        public string renderPipelineType;\n\n        public SerializedCustomEditorForRenderPipeline(BinaryReader reader)\n        {\n            customEditorName = reader.ReadAlignedString();\n            renderPipelineType = reader.ReadAlignedString();\n        }\n    }\n\n    public class SerializedShader\n    {\n        public SerializedProperties m_PropInfo;\n        public SerializedSubShader[] m_SubShaders;\n        public string[] m_KeywordNames;\n        public byte[] m_KeywordFlags;\n        public string m_Name;\n        public string m_CustomEditorName;\n        public string m_FallbackName;\n        public SerializedShaderDependency[] m_Dependencies;\n        public SerializedCustomEditorForRenderPipeline[] m_CustomEditorForRenderPipelines;\n        public bool m_DisableNoSubshadersMessage;\n\n        public SerializedShader(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_PropInfo = new SerializedProperties(reader);\n\n            int numSubShaders = reader.ReadInt32();\n            m_SubShaders = new SerializedSubShader[numSubShaders];\n            for (int i = 0; i < numSubShaders; i++)\n            {\n                m_SubShaders[i] = new SerializedSubShader(reader);\n            }\n\n            if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up\n            {\n                m_KeywordNames = reader.ReadStringArray();\n                m_KeywordFlags = reader.ReadUInt8Array();\n                reader.AlignStream();\n            }\n\n            m_Name = reader.ReadAlignedString();\n            m_CustomEditorName = reader.ReadAlignedString();\n            m_FallbackName = reader.ReadAlignedString();\n\n            int numDependencies = reader.ReadInt32();\n            m_Dependencies = new SerializedShaderDependency[numDependencies];\n            for (int i = 0; i < numDependencies; i++)\n            {\n                m_Dependencies[i] = new SerializedShaderDependency(reader);\n            }\n\n            if (version[0] >= 2021) //2021.1 and up\n            {\n                int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32();\n                m_CustomEditorForRenderPipelines = new SerializedCustomEditorForRenderPipeline[m_CustomEditorForRenderPipelinesSize];\n                for (int i = 0; i < m_CustomEditorForRenderPipelinesSize; i++)\n                {\n                    m_CustomEditorForRenderPipelines[i] = new SerializedCustomEditorForRenderPipeline(reader);\n                }\n            }\n\n            m_DisableNoSubshadersMessage = reader.ReadBoolean();\n            reader.AlignStream();\n        }\n    }\n\n    public enum ShaderCompilerPlatform\n    {\n        None = -1,\n        GL = 0,\n        D3D9 = 1,\n        Xbox360 = 2,\n        PS3 = 3,\n        D3D11 = 4,\n        GLES20 = 5,\n        NaCl = 6,\n        Flash = 7,\n        D3D11_9x = 8,\n        GLES3Plus = 9,\n        PSP2 = 10,\n        PS4 = 11,\n        XboxOne = 12,\n        PSM = 13,\n        Metal = 14,\n        OpenGLCore = 15,\n        N3DS = 16,\n        WiiU = 17,\n        Vulkan = 18,\n        Switch = 19,\n        XboxOneD3D12 = 20,\n        GameCoreXboxOne = 21,\n        GameCoreScarlett = 22,\n        PS5 = 23,\n        PS5NGGC = 24\n    };\n\n    public class Shader : NamedObject\n    {\n        public byte[] m_Script;\n        //5.3 - 5.4\n        public uint decompressedSize;\n        public byte[] m_SubProgramBlob;\n        //5.5 and up\n        public SerializedShader m_ParsedForm;\n        public ShaderCompilerPlatform[] platforms;\n        public uint[][] offsets;\n        public uint[][] compressedLengths;\n        public uint[][] decompressedLengths;\n        public byte[] compressedBlob;\n\n        public Shader(ObjectReader reader) : base(reader)\n        {\n            if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up\n            {\n                m_ParsedForm = new SerializedShader(reader);\n                platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();\n                if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up\n                {\n                    offsets = reader.ReadUInt32ArrayArray();\n                    compressedLengths = reader.ReadUInt32ArrayArray();\n                    decompressedLengths = reader.ReadUInt32ArrayArray();\n                }\n                else\n                {\n                    offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();\n                    compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();\n                    decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();\n                }\n                compressedBlob = reader.ReadUInt8Array();\n                reader.AlignStream();\n\n                var m_DependenciesCount = reader.ReadInt32();\n                for (int i = 0; i < m_DependenciesCount; i++)\n                {\n                    new PPtr<Shader>(reader);\n                }\n\n                if (version[0] >= 2018)\n                {\n                    var m_NonModifiableTexturesCount = reader.ReadInt32();\n                    for (int i = 0; i < m_NonModifiableTexturesCount; i++)\n                    {\n                        var first = reader.ReadAlignedString();\n                        new PPtr<Texture>(reader);\n                    }\n                }\n\n                var m_ShaderIsBaked = reader.ReadBoolean();\n                reader.AlignStream();\n            }\n            else\n            {\n                m_Script = reader.ReadUInt8Array();\n                reader.AlignStream();\n                var m_PathName = reader.ReadAlignedString();\n                if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4\n                {\n                    decompressedSize = reader.ReadUInt32();\n                    m_SubProgramBlob = reader.ReadUInt8Array();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/SkinnedMeshRenderer.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class SkinnedMeshRenderer : Renderer\n    {\n        public PPtr<Mesh> m_Mesh;\n        public PPtr<Transform>[] m_Bones;\n        public float[] m_BlendShapeWeights;\n\n        public SkinnedMeshRenderer(ObjectReader reader) : base(reader)\n        {\n            int m_Quality = reader.ReadInt32();\n            var m_UpdateWhenOffscreen = reader.ReadBoolean();\n            var m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below\n            reader.AlignStream();\n\n            if (version[0] == 2 && version[1] < 6) //2.6 down\n            {\n                var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);\n            }\n\n            m_Mesh = new PPtr<Mesh>(reader);\n\n            m_Bones = new PPtr<Transform>[reader.ReadInt32()];\n            for (int b = 0; b < m_Bones.Length; b++)\n            {\n                m_Bones[b] = new PPtr<Transform>(reader);\n            }\n\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up\n            {\n                m_BlendShapeWeights = reader.ReadSingleArray();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Sprite.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace AssetStudio\n{\n    public class SecondarySpriteTexture\n    {\n        public PPtr<Texture2D> texture;\n        public string name;\n\n        public SecondarySpriteTexture(ObjectReader reader)\n        {\n            texture = new PPtr<Texture2D>(reader);\n            name = reader.ReadStringToNull();\n        }\n    }\n\n    public enum SpritePackingRotation\n    {\n        None = 0,\n        FlipHorizontal = 1,\n        FlipVertical = 2,\n        Rotate180 = 3,\n        Rotate90 = 4\n    };\n\n    public enum SpritePackingMode\n    {\n        Tight = 0,\n        Rectangle\n    };\n\n    public enum SpriteMeshType\n    {\n        FullRect,\n        Tight\n    };\n\n    public class SpriteSettings\n    {\n        public uint settingsRaw;\n\n        public uint packed;\n        public SpritePackingMode packingMode;\n        public SpritePackingRotation packingRotation;\n        public SpriteMeshType meshType;\n\n        public SpriteSettings(BinaryReader reader)\n        {\n            settingsRaw = reader.ReadUInt32();\n\n            packed = settingsRaw & 1; //1\n            packingMode = (SpritePackingMode)((settingsRaw >> 1) & 1); //1\n            packingRotation = (SpritePackingRotation)((settingsRaw >> 2) & 0xf); //4\n            meshType = (SpriteMeshType)((settingsRaw >> 6) & 1); //1\n            //reserved\n        }\n    }\n\n    public class SpriteVertex\n    {\n        public Vector3 pos;\n        public Vector2 uv;\n\n        public SpriteVertex(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            pos = reader.ReadVector3();\n            if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down\n            {\n                uv = reader.ReadVector2();\n            }\n        }\n    }\n\n    public class SpriteRenderData\n    {\n        public PPtr<Texture2D> texture;\n        public PPtr<Texture2D> alphaTexture;\n        public SecondarySpriteTexture[] secondaryTextures;\n        public SubMesh[] m_SubMeshes;\n        public byte[] m_IndexBuffer;\n        public VertexData m_VertexData;\n        public SpriteVertex[] vertices;\n        public ushort[] indices;\n        public Matrix4x4[] m_Bindpose;\n        public BoneWeights4[] m_SourceSkin;\n        public Rectf textureRect;\n        public Vector2 textureRectOffset;\n        public Vector2 atlasRectOffset;\n        public SpriteSettings settingsRaw;\n        public Vector4 uvTransform;\n        public float downscaleMultiplier;\n\n        public SpriteRenderData(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            texture = new PPtr<Texture2D>(reader);\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up\n            {\n                alphaTexture = new PPtr<Texture2D>(reader);\n            }\n\n            if (version[0] >= 2019) //2019 and up\n            {\n                var secondaryTexturesSize = reader.ReadInt32();\n                secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];\n                for (int i = 0; i < secondaryTexturesSize; i++)\n                {\n                    secondaryTextures[i] = new SecondarySpriteTexture(reader);\n                }\n            }\n\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up\n            {\n                var m_SubMeshesSize = reader.ReadInt32();\n                m_SubMeshes = new SubMesh[m_SubMeshesSize];\n                for (int i = 0; i < m_SubMeshesSize; i++)\n                {\n                    m_SubMeshes[i] = new SubMesh(reader);\n                }\n\n                m_IndexBuffer = reader.ReadUInt8Array();\n                reader.AlignStream();\n\n                m_VertexData = new VertexData(reader);\n            }\n            else\n            {\n                var verticesSize = reader.ReadInt32();\n                vertices = new SpriteVertex[verticesSize];\n                for (int i = 0; i < verticesSize; i++)\n                {\n                    vertices[i] = new SpriteVertex(reader);\n                }\n\n                indices = reader.ReadUInt16Array();\n                reader.AlignStream();\n            }\n\n            if (version[0] >= 2018) //2018 and up\n            {\n                m_Bindpose = reader.ReadMatrixArray();\n\n                if (version[0] == 2018 && version[1] < 2) //2018.2 down\n                {\n                    var m_SourceSkinSize = reader.ReadInt32();\n                    for (int i = 0; i < m_SourceSkinSize; i++)\n                    {\n                        m_SourceSkin[i] = new BoneWeights4(reader);\n                    }\n                }\n            }\n\n            textureRect = new Rectf(reader);\n            textureRectOffset = reader.ReadVector2();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up\n            {\n                atlasRectOffset = reader.ReadVector2();\n            }\n\n            settingsRaw = new SpriteSettings(reader);\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up\n            {\n                uvTransform = reader.ReadVector4();\n            }\n\n            if (version[0] >= 2017) //2017 and up\n            {\n                downscaleMultiplier = reader.ReadSingle();\n            }\n        }\n    }\n\n    public class Rectf\n    {\n        public float x;\n        public float y;\n        public float width;\n        public float height;\n\n        public Rectf(BinaryReader reader)\n        {\n            x = reader.ReadSingle();\n            y = reader.ReadSingle();\n            width = reader.ReadSingle();\n            height = reader.ReadSingle();\n        }\n    }\n\n    public sealed class Sprite : NamedObject\n    {\n        public Rectf m_Rect;\n        public Vector2 m_Offset;\n        public Vector4 m_Border;\n        public float m_PixelsToUnits;\n        public Vector2 m_Pivot = new Vector2(0.5f, 0.5f);\n        public uint m_Extrude;\n        public bool m_IsPolygon;\n        public KeyValuePair<Guid, long> m_RenderDataKey;\n        public string[] m_AtlasTags;\n        public PPtr<SpriteAtlas> m_SpriteAtlas;\n        public SpriteRenderData m_RD;\n        public Vector2[][] m_PhysicsShape;\n\n        public Sprite(ObjectReader reader) : base(reader)\n        {\n            m_Rect = new Rectf(reader);\n            m_Offset = reader.ReadVector2();\n            if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up\n            {\n                m_Border = reader.ReadVector4();\n            }\n\n            m_PixelsToUnits = reader.ReadSingle();\n            if (version[0] > 5\n                || (version[0] == 5 && version[1] > 4)\n                || (version[0] == 5 && version[1] == 4 && version[2] >= 2)\n                || (version[0] == 5 && version[1] == 4 && version[2] == 1 && buildType.IsPatch && version[3] >= 3)) //5.4.1p3 and up\n            {\n                m_Pivot = reader.ReadVector2();\n            }\n\n            m_Extrude = reader.ReadUInt32();\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up\n            {\n                m_IsPolygon = reader.ReadBoolean();\n                reader.AlignStream();\n            }\n\n            if (version[0] >= 2017) //2017 and up\n            {\n                var first = new Guid(reader.ReadBytes(16));\n                var second = reader.ReadInt64();\n                m_RenderDataKey = new KeyValuePair<Guid, long>(first, second);\n\n                m_AtlasTags = reader.ReadStringArray();\n\n                m_SpriteAtlas = new PPtr<SpriteAtlas>(reader);\n            }\n\n            m_RD = new SpriteRenderData(reader);\n\n            if (version[0] >= 2017) //2017 and up\n            {\n                var m_PhysicsShapeSize = reader.ReadInt32();\n                m_PhysicsShape = new Vector2[m_PhysicsShapeSize][];\n                for (int i = 0; i < m_PhysicsShapeSize; i++)\n                {\n                    m_PhysicsShape[i] = reader.ReadVector2Array();\n                }\n            }\n\n            //vector m_Bones 2018 and up\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/SpriteAtlas.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace AssetStudio\n{\n    public class SpriteAtlasData\n    {\n        public PPtr<Texture2D> texture;\n        public PPtr<Texture2D> alphaTexture;\n        public Rectf textureRect;\n        public Vector2 textureRectOffset;\n        public Vector2 atlasRectOffset;\n        public Vector4 uvTransform;\n        public float downscaleMultiplier;\n        public SpriteSettings settingsRaw;\n        public SecondarySpriteTexture[] secondaryTextures;\n\n        public SpriteAtlasData(ObjectReader reader)\n        {\n            var version = reader.version;\n            texture = new PPtr<Texture2D>(reader);\n            alphaTexture = new PPtr<Texture2D>(reader);\n            textureRect = new Rectf(reader);\n            textureRectOffset = reader.ReadVector2();\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up\n            {\n                atlasRectOffset = reader.ReadVector2();\n            }\n            uvTransform = reader.ReadVector4();\n            downscaleMultiplier = reader.ReadSingle();\n            settingsRaw = new SpriteSettings(reader);\n            if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up\n            {\n                var secondaryTexturesSize = reader.ReadInt32();\n                secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];\n                for (int i = 0; i < secondaryTexturesSize; i++)\n                {\n                    secondaryTextures[i] = new SecondarySpriteTexture(reader);\n                }\n                reader.AlignStream();\n            }\n        }\n    }\n\n    public sealed class SpriteAtlas : NamedObject\n    {\n        public PPtr<Sprite>[] m_PackedSprites;\n        public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;\n        public bool m_IsVariant;\n\n        public SpriteAtlas(ObjectReader reader) : base(reader)\n        {\n            var m_PackedSpritesSize = reader.ReadInt32();\n            m_PackedSprites = new PPtr<Sprite>[m_PackedSpritesSize];\n            for (int i = 0; i < m_PackedSpritesSize; i++)\n            {\n                m_PackedSprites[i] = new PPtr<Sprite>(reader);\n            }\n\n            var m_PackedSpriteNamesToIndex = reader.ReadStringArray();\n\n            var m_RenderDataMapSize = reader.ReadInt32();\n            m_RenderDataMap = new Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData>(m_RenderDataMapSize);\n            for (int i = 0; i < m_RenderDataMapSize; i++)\n            {\n                var first = new Guid(reader.ReadBytes(16));\n                var second = reader.ReadInt64();\n                var value = new SpriteAtlasData(reader);\n                m_RenderDataMap.Add(new KeyValuePair<Guid, long>(first, second), value);\n            }\n            var m_Tag = reader.ReadAlignedString();\n            m_IsVariant = reader.ReadBoolean();\n            reader.AlignStream();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/TextAsset.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Linq.Expressions;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public sealed class TextAsset : NamedObject\n    {\n        public byte[] m_Script;\n\n        public TextAsset(ObjectReader reader) : base(reader)\n        {\n            m_Script = reader.ReadUInt8Array();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Texture.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public abstract class Texture : NamedObject\n    {\n        protected Texture(ObjectReader reader) : base(reader)\n        {\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up\n            {\n                var m_ForcedFallbackFormat = reader.ReadInt32();\n                var m_DownscaleFallback = reader.ReadBoolean();\n                if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up\n                {\n                    var m_IsAlphaChannelOptional = reader.ReadBoolean();\n                }\n                reader.AlignStream();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/Texture2D.cs",
    "content": "﻿using System;\n\nnamespace AssetStudio\n{\n    public class StreamingInfo\n    {\n        public long offset; //ulong\n        public uint size;\n        public string path;\n\n        public StreamingInfo(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            if (version[0] >= 2020) //2020.1 and up\n            {\n                offset = reader.ReadInt64();\n            }\n            else\n            {\n                offset = reader.ReadUInt32();\n            }\n            size = reader.ReadUInt32();\n            path = reader.ReadAlignedString();\n        }\n    }\n\n    public class GLTextureSettings\n    {\n        public int m_FilterMode;\n        public int m_Aniso;\n        public float m_MipBias;\n        public int m_WrapMode;\n\n        public GLTextureSettings(ObjectReader reader)\n        {\n            var version = reader.version;\n\n            m_FilterMode = reader.ReadInt32();\n            m_Aniso = reader.ReadInt32();\n            m_MipBias = reader.ReadSingle();\n            if (version[0] >= 2017)//2017.x and up\n            {\n                m_WrapMode = reader.ReadInt32(); //m_WrapU\n                int m_WrapV = reader.ReadInt32();\n                int m_WrapW = reader.ReadInt32();\n            }\n            else\n            {\n                m_WrapMode = reader.ReadInt32();\n            }\n        }\n    }\n\n    public sealed class Texture2D : Texture\n    {\n        public int m_Width;\n        public int m_Height;\n        public TextureFormat m_TextureFormat;\n        public bool m_MipMap;\n        public int m_MipCount;\n        public GLTextureSettings m_TextureSettings;\n        public ResourceReader image_data;\n        public StreamingInfo m_StreamData;\n\n        public Texture2D(ObjectReader reader) : base(reader)\n        {\n            m_Width = reader.ReadInt32();\n            m_Height = reader.ReadInt32();\n            var m_CompleteImageSize = reader.ReadInt32();\n            if (version[0] >= 2020) //2020.1 and up\n            {\n                var m_MipsStripped = reader.ReadInt32();\n            }\n            m_TextureFormat = (TextureFormat)reader.ReadInt32();\n            if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down\n            {\n                m_MipMap = reader.ReadBoolean();\n            }\n            else\n            {\n                m_MipCount = reader.ReadInt32();\n            }\n            if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up\n            {\n                var m_IsReadable = reader.ReadBoolean();\n            }\n            if (version[0] >= 2020) //2020.1 and up\n            {\n                var m_IsPreProcessed = reader.ReadBoolean();\n            }\n            if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up\n            {\n                var m_IgnoreMasterTextureLimit = reader.ReadBoolean();\n            }\n            if (version[0] >= 3) //3.0.0 - 5.4\n            {\n                if (version[0] < 5 || (version[0] == 5 && version[1] <= 4))\n                {\n                    var m_ReadAllowed = reader.ReadBoolean();\n                }\n            }\n            if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up\n            {\n                var m_StreamingMipmaps = reader.ReadBoolean();\n            }\n            reader.AlignStream();\n            if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up\n            {\n                var m_StreamingMipmapsPriority = reader.ReadInt32();\n            }\n            var m_ImageCount = reader.ReadInt32();\n            var m_TextureDimension = reader.ReadInt32();\n            m_TextureSettings = new GLTextureSettings(reader);\n            if (version[0] >= 3) //3.0 and up\n            {\n                var m_LightmapFormat = reader.ReadInt32();\n            }\n            if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5.0 and up\n            {\n                var m_ColorSpace = reader.ReadInt32();\n            }\n            if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up\n            {\n                var m_PlatformBlob = reader.ReadUInt8Array();\n                reader.AlignStream();\n            }\n            var image_data_size = reader.ReadInt32();\n            if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up\n            {\n                m_StreamData = new StreamingInfo(reader);\n            }\n\n            ResourceReader resourceReader;\n            if (!string.IsNullOrEmpty(m_StreamData?.path))\n            {\n                resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);\n            }\n            else\n            {\n                resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);\n            }\n            image_data = resourceReader;\n        }\n    }\n\n    public enum TextureFormat\n    {\n        Alpha8 = 1,\n        ARGB4444,\n        RGB24,\n        RGBA32,\n        ARGB32,\n        ARGBFloat,\n        RGB565,\n        BGR24,\n        R16,\n        DXT1,\n        DXT3,\n        DXT5,\n        RGBA4444,\n        BGRA32,\n        RHalf,\n        RGHalf,\n        RGBAHalf,\n        RFloat,\n        RGFloat,\n        RGBAFloat,\n        YUY2,\n        RGB9e5Float,\n        RGBFloat,\n        BC6H,\n        BC7,\n        BC4,\n        BC5,\n        DXT1Crunched,\n        DXT5Crunched,\n        PVRTC_RGB2,\n        PVRTC_RGBA2,\n        PVRTC_RGB4,\n        PVRTC_RGBA4,\n        ETC_RGB4,\n        ATC_RGB4,\n        ATC_RGBA8,\n        EAC_R = 41,\n        EAC_R_SIGNED,\n        EAC_RG,\n        EAC_RG_SIGNED,\n        ETC2_RGB,\n        ETC2_RGBA1,\n        ETC2_RGBA8,\n        ASTC_RGB_4x4,\n        ASTC_RGB_5x5,\n        ASTC_RGB_6x6,\n        ASTC_RGB_8x8,\n        ASTC_RGB_10x10,\n        ASTC_RGB_12x12,\n        ASTC_RGBA_4x4,\n        ASTC_RGBA_5x5,\n        ASTC_RGBA_6x6,\n        ASTC_RGBA_8x8,\n        ASTC_RGBA_10x10,\n        ASTC_RGBA_12x12,\n        ETC_RGB4_3DS,\n        ETC_RGBA8_3DS,\n        RG16,\n        R8,\n        ETC_RGB4Crunched,\n        ETC2_RGBA8Crunched,\n        ASTC_HDR_4x4,\n        ASTC_HDR_5x5,\n        ASTC_HDR_6x6,\n        ASTC_HDR_8x8,\n        ASTC_HDR_10x10,\n        ASTC_HDR_12x12,\n        RG32,\n        RGB48,\n        RGBA64\n    }\n}"
  },
  {
    "path": "AssetStudio/Classes/Transform.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class Transform : Component\n    {\n        public Quaternion m_LocalRotation;\n        public Vector3 m_LocalPosition;\n        public Vector3 m_LocalScale;\n        public PPtr<Transform>[] m_Children;\n        public PPtr<Transform> m_Father;\n\n        public Transform(ObjectReader reader) : base(reader)\n        {\n            m_LocalRotation = reader.ReadQuaternion();\n            m_LocalPosition = reader.ReadVector3();\n            m_LocalScale = reader.ReadVector3();\n\n            int m_ChildrenCount = reader.ReadInt32();\n            m_Children = new PPtr<Transform>[m_ChildrenCount];\n            for (int i = 0; i < m_ChildrenCount; i++)\n            {\n                m_Children[i] = new PPtr<Transform>(reader);\n            }\n            m_Father = new PPtr<Transform>(reader);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Classes/VideoClip.cs",
    "content": "﻿using System.IO;\n\nnamespace AssetStudio\n{\n    public class StreamedResource\n    {\n        public string m_Source;\n        public long m_Offset; //ulong\n        public long m_Size; //ulong\n\n        public StreamedResource(BinaryReader reader)\n        {\n            m_Source = reader.ReadAlignedString();\n            m_Offset = reader.ReadInt64();\n            m_Size = reader.ReadInt64();\n        }\n    }\n\n    public sealed class VideoClip : NamedObject\n    {\n        public ResourceReader m_VideoData;\n        public string m_OriginalPath;\n        public StreamedResource m_ExternalResources;\n\n        public VideoClip(ObjectReader reader) : base(reader)\n        {\n            m_OriginalPath = reader.ReadAlignedString();\n            var m_ProxyWidth = reader.ReadUInt32();\n            var m_ProxyHeight = reader.ReadUInt32();\n            var Width = reader.ReadUInt32();\n            var Height = reader.ReadUInt32();\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up\n            {\n                var m_PixelAspecRatioNum = reader.ReadUInt32();\n                var m_PixelAspecRatioDen = reader.ReadUInt32();\n            }\n            var m_FrameRate = reader.ReadDouble();\n            var m_FrameCount = reader.ReadUInt64();\n            var m_Format = reader.ReadInt32();\n            var m_AudioChannelCount = reader.ReadUInt16Array();\n            reader.AlignStream();\n            var m_AudioSampleRate = reader.ReadUInt32Array();\n            var m_AudioLanguage = reader.ReadStringArray();\n            if (version[0] >= 2020) //2020.1 and up\n            {\n                var m_VideoShadersSize = reader.ReadInt32();\n                var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize];\n                for (int i = 0; i < m_VideoShadersSize; i++)\n                {\n                    m_VideoShaders[i] = new PPtr<Shader>(reader);\n                }\n            }\n            m_ExternalResources = new StreamedResource(reader);\n            var m_HasSplitAlpha = reader.ReadBoolean();\n            if (version[0] >= 2020) //2020.1 and up\n            {\n                var m_sRGB = reader.ReadBoolean();\n            }\n\n            ResourceReader resourceReader;\n            if (!string.IsNullOrEmpty(m_ExternalResources.m_Source))\n            {\n                resourceReader = new ResourceReader(m_ExternalResources.m_Source, assetsFile, m_ExternalResources.m_Offset, m_ExternalResources.m_Size);\n            }\n            else\n            {\n                resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_ExternalResources.m_Size);\n            }\n            m_VideoData = resourceReader;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/CommonString.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace AssetStudio\n{\n    public static class CommonString\n    {\n        public static readonly Dictionary<uint, string> StringBuffer = new Dictionary<uint, string>\n        {\n            {0, \"AABB\"},\n            {5, \"AnimationClip\"},\n            {19, \"AnimationCurve\"},\n            {34, \"AnimationState\"},\n            {49, \"Array\"},\n            {55, \"Base\"},\n            {60, \"BitField\"},\n            {69, \"bitset\"},\n            {76, \"bool\"},\n            {81, \"char\"},\n            {86, \"ColorRGBA\"},\n            {96, \"Component\"},\n            {106, \"data\"},\n            {111, \"deque\"},\n            {117, \"double\"},\n            {124, \"dynamic_array\"},\n            {138, \"FastPropertyName\"},\n            {155, \"first\"},\n            {161, \"float\"},\n            {167, \"Font\"},\n            {172, \"GameObject\"},\n            {183, \"Generic Mono\"},\n            {196, \"GradientNEW\"},\n            {208, \"GUID\"},\n            {213, \"GUIStyle\"},\n            {222, \"int\"},\n            {226, \"list\"},\n            {231, \"long long\"},\n            {241, \"map\"},\n            {245, \"Matrix4x4f\"},\n            {256, \"MdFour\"},\n            {263, \"MonoBehaviour\"},\n            {277, \"MonoScript\"},\n            {288, \"m_ByteSize\"},\n            {299, \"m_Curve\"},\n            {307, \"m_EditorClassIdentifier\"},\n            {331, \"m_EditorHideFlags\"},\n            {349, \"m_Enabled\"},\n            {359, \"m_ExtensionPtr\"},\n            {374, \"m_GameObject\"},\n            {387, \"m_Index\"},\n            {395, \"m_IsArray\"},\n            {405, \"m_IsStatic\"},\n            {416, \"m_MetaFlag\"},\n            {427, \"m_Name\"},\n            {434, \"m_ObjectHideFlags\"},\n            {452, \"m_PrefabInternal\"},\n            {469, \"m_PrefabParentObject\"},\n            {490, \"m_Script\"},\n            {499, \"m_StaticEditorFlags\"},\n            {519, \"m_Type\"},\n            {526, \"m_Version\"},\n            {536, \"Object\"},\n            {543, \"pair\"},\n            {548, \"PPtr<Component>\"},\n            {564, \"PPtr<GameObject>\"},\n            {581, \"PPtr<Material>\"},\n            {596, \"PPtr<MonoBehaviour>\"},\n            {616, \"PPtr<MonoScript>\"},\n            {633, \"PPtr<Object>\"},\n            {646, \"PPtr<Prefab>\"},\n            {659, \"PPtr<Sprite>\"},\n            {672, \"PPtr<TextAsset>\"},\n            {688, \"PPtr<Texture>\"},\n            {702, \"PPtr<Texture2D>\"},\n            {718, \"PPtr<Transform>\"},\n            {734, \"Prefab\"},\n            {741, \"Quaternionf\"},\n            {753, \"Rectf\"},\n            {759, \"RectInt\"},\n            {767, \"RectOffset\"},\n            {778, \"second\"},\n            {785, \"set\"},\n            {789, \"short\"},\n            {795, \"size\"},\n            {800, \"SInt16\"},\n            {807, \"SInt32\"},\n            {814, \"SInt64\"},\n            {821, \"SInt8\"},\n            {827, \"staticvector\"},\n            {840, \"string\"},\n            {847, \"TextAsset\"},\n            {857, \"TextMesh\"},\n            {866, \"Texture\"},\n            {874, \"Texture2D\"},\n            {884, \"Transform\"},\n            {894, \"TypelessData\"},\n            {907, \"UInt16\"},\n            {914, \"UInt32\"},\n            {921, \"UInt64\"},\n            {928, \"UInt8\"},\n            {934, \"unsigned int\"},\n            {947, \"unsigned long long\"},\n            {966, \"unsigned short\"},\n            {981, \"vector\"},\n            {988, \"Vector2f\"},\n            {997, \"Vector3f\"},\n            {1006, \"Vector4f\"},\n            {1015, \"m_ScriptingClassIdentifier\"},\n            {1042, \"Gradient\"},\n            {1051, \"Type*\"},\n            {1057, \"int2_storage\"},\n            {1070, \"int3_storage\"},\n            {1083, \"BoundsInt\"},\n            {1093, \"m_CorrespondingSourceObject\"},\n            {1121, \"m_PrefabInstance\"},\n            {1138, \"m_PrefabAsset\"},\n            {1152, \"FileSize\"},\n            {1161, \"Hash128\"}\n        };\n    }\n}\n"
  },
  {
    "path": "AssetStudio/EndianBinaryReader.cs",
    "content": "﻿using System;\nusing System.Buffers.Binary;\nusing System.IO;\n\nnamespace AssetStudio\n{\n    public class EndianBinaryReader : BinaryReader\n    {\n        private readonly byte[] buffer;\n\n        public EndianType Endian;\n\n        public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)\n        {\n            Endian = endian;\n            buffer = new byte[8];\n        }\n\n        public long Position\n        {\n            get => BaseStream.Position;\n            set => BaseStream.Position = value;\n        }\n\n        public override short ReadInt16()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 2);\n                return BinaryPrimitives.ReadInt16BigEndian(buffer);\n            }\n            return base.ReadInt16();\n        }\n\n        public override int ReadInt32()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 4);\n                return BinaryPrimitives.ReadInt32BigEndian(buffer);\n            }\n            return base.ReadInt32();\n        }\n\n        public override long ReadInt64()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 8);\n                return BinaryPrimitives.ReadInt64BigEndian(buffer);\n            }\n            return base.ReadInt64();\n        }\n\n        public override ushort ReadUInt16()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 2);\n                return BinaryPrimitives.ReadUInt16BigEndian(buffer);\n            }\n            return base.ReadUInt16();\n        }\n\n        public override uint ReadUInt32()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 4);\n                return BinaryPrimitives.ReadUInt32BigEndian(buffer);\n            }\n            return base.ReadUInt32();\n        }\n\n        public override ulong ReadUInt64()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 8);\n                return BinaryPrimitives.ReadUInt64BigEndian(buffer);\n            }\n            return base.ReadUInt64();\n        }\n\n        public override float ReadSingle()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 4);\n                Array.Reverse(buffer, 0, 4);\n                return BitConverter.ToSingle(buffer, 0);\n            }\n            return base.ReadSingle();\n        }\n\n        public override double ReadDouble()\n        {\n            if (Endian == EndianType.BigEndian)\n            {\n                Read(buffer, 0, 8);\n                Array.Reverse(buffer);\n                return BitConverter.ToDouble(buffer, 0);\n            }\n            return base.ReadDouble();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/EndianType.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace AssetStudio\n{\n    public enum EndianType\n    {\n        LittleEndian,\n        BigEndian\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Extensions/BinaryReaderExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public static class BinaryReaderExtensions\n    {\n        public static void AlignStream(this BinaryReader reader)\n        {\n            reader.AlignStream(4);\n        }\n\n        public static void AlignStream(this BinaryReader reader, int alignment)\n        {\n            var pos = reader.BaseStream.Position;\n            var mod = pos % alignment;\n            if (mod != 0)\n            {\n                reader.BaseStream.Position += alignment - mod;\n            }\n        }\n\n        public static string ReadAlignedString(this BinaryReader reader)\n        {\n            var length = reader.ReadInt32();\n            if (length > 0 && length <= reader.BaseStream.Length - reader.BaseStream.Position)\n            {\n                var stringData = reader.ReadBytes(length);\n                var result = Encoding.UTF8.GetString(stringData);\n                reader.AlignStream(4);\n                return result;\n            }\n            return \"\";\n        }\n\n        public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767)\n        {\n            var bytes = new List<byte>();\n            int count = 0;\n            while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)\n            {\n                var b = reader.ReadByte();\n                if (b == 0)\n                {\n                    break;\n                }\n                bytes.Add(b);\n                count++;\n            }\n            return Encoding.UTF8.GetString(bytes.ToArray());\n        }\n\n        public static Quaternion ReadQuaternion(this BinaryReader reader)\n        {\n            return new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());\n        }\n\n        public static Vector2 ReadVector2(this BinaryReader reader)\n        {\n            return new Vector2(reader.ReadSingle(), reader.ReadSingle());\n        }\n\n        public static Vector3 ReadVector3(this BinaryReader reader)\n        {\n            return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());\n        }\n\n        public static Vector4 ReadVector4(this BinaryReader reader)\n        {\n            return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());\n        }\n\n        public static Color ReadColor4(this BinaryReader reader)\n        {\n            return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());\n        }\n\n        public static Matrix4x4 ReadMatrix(this BinaryReader reader)\n        {\n            return new Matrix4x4(reader.ReadSingleArray(16));\n        }\n\n        private static T[] ReadArray<T>(Func<T> del, int length)\n        {\n            var array = new T[length];\n            for (int i = 0; i < length; i++)\n            {\n                array[i] = del();\n            }\n            return array;\n        }\n\n        public static bool[] ReadBooleanArray(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadBoolean, reader.ReadInt32());\n        }\n\n        public static byte[] ReadUInt8Array(this BinaryReader reader)\n        {\n            return reader.ReadBytes(reader.ReadInt32());\n        }\n\n        public static ushort[] ReadUInt16Array(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadUInt16, reader.ReadInt32());\n        }\n\n        public static int[] ReadInt32Array(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadInt32, reader.ReadInt32());\n        }\n\n        public static int[] ReadInt32Array(this BinaryReader reader, int length)\n        {\n            return ReadArray(reader.ReadInt32, length);\n        }\n\n        public static uint[] ReadUInt32Array(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadUInt32, reader.ReadInt32());\n        }\n\n        public static uint[][] ReadUInt32ArrayArray(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadUInt32Array, reader.ReadInt32());\n        }\n\n        public static uint[] ReadUInt32Array(this BinaryReader reader, int length)\n        {\n            return ReadArray(reader.ReadUInt32, length);\n        }\n\n        public static float[] ReadSingleArray(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadSingle, reader.ReadInt32());\n        }\n\n        public static float[] ReadSingleArray(this BinaryReader reader, int length)\n        {\n            return ReadArray(reader.ReadSingle, length);\n        }\n\n        public static string[] ReadStringArray(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadAlignedString, reader.ReadInt32());\n        }\n\n        public static Vector2[] ReadVector2Array(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadVector2, reader.ReadInt32());\n        }\n\n        public static Vector4[] ReadVector4Array(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadVector4, reader.ReadInt32());\n        }\n\n        public static Matrix4x4[] ReadMatrixArray(this BinaryReader reader)\n        {\n            return ReadArray(reader.ReadMatrix, reader.ReadInt32());\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Extensions/BinaryWriterExtensions.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public static class BinaryWriterExtensions\n    {\n        public static void AlignStream(this BinaryWriter writer, int alignment)\n        {\n            var pos = writer.BaseStream.Position;\n            var mod = pos % alignment;\n            if (mod != 0)\n            {\n                writer.Write(new byte[alignment - mod]);\n            }\n        }\n\n        public static void WriteAlignedString(this BinaryWriter writer, string str)\n        {\n            var bytes = Encoding.UTF8.GetBytes(str);\n            writer.Write(bytes.Length);\n            writer.Write(bytes);\n            writer.AlignStream(4);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Extensions/StreamExtensions.cs",
    "content": "﻿using System.IO;\n\nnamespace AssetStudio\n{\n    public static class StreamExtensions\n    {\n        private const int BufferSize = 81920;\n\n        public static void CopyTo(this Stream source, Stream destination, long size)\n        {\n            var buffer = new byte[BufferSize];\n            for (var left = size; left > 0; left -= BufferSize)\n            {\n                int toRead = BufferSize < left ? BufferSize : (int)left;\n                int read = source.Read(buffer, 0, toRead);\n                destination.Write(buffer, 0, read);\n                if (read != toRead)\n                {\n                    return;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/FileIdentifier.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class FileIdentifier\n    {\n        public Guid guid;\n        public int type; //enum { kNonAssetType = 0, kDeprecatedCachedAssetType = 1, kSerializedAssetType = 2, kMetaAssetType = 3 };\n        public string pathName;\n\n        //custom\n        public string fileName;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/FileReader.cs",
    "content": "﻿using System.IO;\nusing System.Linq;\n\nnamespace AssetStudio\n{\n    public class FileReader : EndianBinaryReader\n    {\n        public string FullPath;\n        public string FileName;\n        public FileType FileType;\n\n        private static readonly byte[] gzipMagic = { 0x1f, 0x8b };\n        private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };\n        private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 };\n        private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 };\n\n        public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }\n\n        public FileReader(string path, Stream stream) : base(stream, EndianType.BigEndian)\n        {\n            FullPath = Path.GetFullPath(path);\n            FileName = Path.GetFileName(path);\n            FileType = CheckFileType();\n        }\n\n        private FileType CheckFileType()\n        {\n            var signature = this.ReadStringToNull(20);\n            Position = 0;\n            switch (signature)\n            {\n                case \"UnityWeb\":\n                case \"UnityRaw\":\n                case \"UnityArchive\":\n                case \"UnityFS\":\n                    return FileType.BundleFile;\n                case \"UnityWebData1.0\":\n                    return FileType.WebFile;\n                default:\n                    {\n                        byte[] magic = ReadBytes(2);\n                        Position = 0;\n                        if (gzipMagic.SequenceEqual(magic))\n                        {\n                            return FileType.GZipFile;\n                        }\n                        Position = 0x20;\n                        magic = ReadBytes(6);\n                        Position = 0;\n                        if (brotliMagic.SequenceEqual(magic))\n                        {\n                            return FileType.BrotliFile;\n                        }\n                        if (IsSerializedFile())\n                        {\n                            return FileType.AssetsFile;\n                        }\n                        magic = ReadBytes(4);\n                        Position = 0;\n                        if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))\n                            return FileType.ZipFile;\n                        return FileType.ResourceFile;\n                    }\n            }\n        }\n\n        private bool IsSerializedFile()\n        {\n            var fileSize = BaseStream.Length;\n            if (fileSize < 20)\n            {\n                return false;\n            }\n            var m_MetadataSize = ReadUInt32();\n            long m_FileSize = ReadUInt32();\n            var m_Version = ReadUInt32();\n            long m_DataOffset = ReadUInt32();\n            var m_Endianess = ReadByte();\n            var m_Reserved = ReadBytes(3);\n            if (m_Version >= 22)\n            {\n                if (fileSize < 48)\n                {\n                    Position = 0;\n                    return false;\n                }\n                m_MetadataSize = ReadUInt32();\n                m_FileSize = ReadInt64();\n                m_DataOffset = ReadInt64();\n            }\n            Position = 0;\n            if (m_FileSize != fileSize)\n            {\n                return false;\n            }\n            if (m_DataOffset > fileSize)\n            {\n                return false;\n            }\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/FileType.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace AssetStudio\n{\n    public enum FileType\n    {\n        AssetsFile,\n        BundleFile,\n        WebFile,\n        ResourceFile,\n        GZipFile,\n        BrotliFile,\n        ZipFile\n    }\n}\n"
  },
  {
    "path": "AssetStudio/IImported.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace AssetStudio\n{\n    public interface IImported\n    {\n        ImportedFrame RootFrame { get; }\n        List<ImportedMesh> MeshList { get; }\n        List<ImportedMaterial> MaterialList { get; }\n        List<ImportedTexture> TextureList { get; }\n        List<ImportedKeyframedAnimation> AnimationList { get; }\n        List<ImportedMorph> MorphList { get; }\n    }\n\n    public class ImportedFrame\n    {\n        public string Name { get; set; }\n        public Vector3 LocalRotation { get; set; }\n        public Vector3 LocalPosition { get; set; }\n        public Vector3 LocalScale { get; set; }\n        public ImportedFrame Parent { get; set; }\n\n        private List<ImportedFrame> children;\n\n        public ImportedFrame this[int i] => children[i];\n\n        public int Count => children.Count;\n\n        public string Path\n        {\n            get\n            {\n                var frame = this;\n                var path = frame.Name;\n                while (frame.Parent != null)\n                {\n                    frame = frame.Parent;\n                    path = frame.Name + \"/\" + path;\n                }\n                return path;\n            }\n        }\n\n        public ImportedFrame(int childrenCount = 0)\n        {\n            children = new List<ImportedFrame>(childrenCount);\n        }\n\n        public void AddChild(ImportedFrame obj)\n        {\n            children.Add(obj);\n            obj.Parent?.Remove(obj);\n            obj.Parent = this;\n        }\n\n        public void Remove(ImportedFrame frame)\n        {\n            children.Remove(frame);\n        }\n\n        public ImportedFrame FindFrameByPath(string path)\n        {\n            var name = path.Substring(path.LastIndexOf('/') + 1);\n            foreach (var frame in FindChilds(name))\n            {\n                if (frame.Path.EndsWith(path, StringComparison.Ordinal))\n                {\n                    return frame;\n                }\n            }\n            return null;\n        }\n\n        public ImportedFrame FindRelativeFrameWithPath(string path)\n        {\n            var subs = path.Split(new[] { '/' }, 2);\n            foreach (var child in children)\n            {\n                if (child.Name == subs[0])\n                {\n                    if (subs.Length == 1)\n                    {\n                        return child;\n                    }\n                    else\n                    {\n                        var result = child.FindRelativeFrameWithPath(subs[1]);\n                        if (result != null)\n                            return result;\n                    }\n                }\n            }\n            return null;\n        }\n\n        public ImportedFrame FindFrame(string name)\n        {\n            if (Name == name)\n            {\n                return this;\n            }\n            foreach (var child in children)\n            {\n                var frame = child.FindFrame(name);\n                if (frame != null)\n                {\n                    return frame;\n                }\n            }\n            return null;\n        }\n\n        public ImportedFrame FindChild(string name, bool recursive = true)\n        {\n            foreach (var child in children)\n            {\n                if (recursive)\n                {\n                    var frame = child.FindFrame(name);\n                    if (frame != null)\n                    {\n                        return frame;\n                    }\n                }\n                else\n                {\n                    if (child.Name == name)\n                    {\n                        return child;\n                    }\n                }\n            }\n            return null;\n        }\n\n        public IEnumerable<ImportedFrame> FindChilds(string name)\n        {\n            if (Name == name)\n            {\n                yield return this;\n            }\n            foreach (var child in children)\n            {\n                foreach (var item in child.FindChilds(name))\n                {\n                    yield return item;\n                }\n            }\n        }\n    }\n\n    public class ImportedMesh\n    {\n        public string Path { get; set; }\n        public List<ImportedVertex> VertexList { get; set; }\n        public List<ImportedSubmesh> SubmeshList { get; set; }\n        public List<ImportedBone> BoneList { get; set; }\n        public bool hasNormal { get; set; }\n        public bool[] hasUV { get; set; }\n        public bool hasTangent { get; set; }\n        public bool hasColor { get; set; }\n    }\n\n    public class ImportedSubmesh\n    {\n        public List<ImportedFace> FaceList { get; set; }\n        public string Material { get; set; }\n        public int BaseVertex { get; set; }\n    }\n\n    public class ImportedVertex\n    {\n        public Vector3 Vertex { get; set; }\n        public Vector3 Normal { get; set; }\n        public float[][] UV { get; set; }\n        public Vector4 Tangent { get; set; }\n        public Color Color { get; set; }\n        public float[] Weights { get; set; }\n        public int[] BoneIndices { get; set; }\n    }\n\n    public class ImportedFace\n    {\n        public int[] VertexIndices { get; set; }\n    }\n\n    public class ImportedBone\n    {\n        public string Path { get; set; }\n        public Matrix4x4 Matrix { get; set; }\n    }\n\n    public class ImportedMaterial\n    {\n        public string Name { get; set; }\n        public Color Diffuse { get; set; }\n        public Color Ambient { get; set; }\n        public Color Specular { get; set; }\n        public Color Emissive { get; set; }\n        public Color Reflection { get; set; }\n        public float Shininess { get; set; }\n        public float Transparency { get; set; }\n        public List<ImportedMaterialTexture> Textures { get; set; }\n    }\n\n    public class ImportedMaterialTexture\n    {\n        public string Name { get; set; }\n        public int Dest { get; set; }\n        public Vector2 Offset { get; set; }\n        public Vector2 Scale { get; set; }\n    }\n\n    public class ImportedTexture\n    {\n        public string Name { get; set; }\n        public byte[] Data { get; set; }\n\n        public ImportedTexture(MemoryStream stream, string name)\n        {\n            Name = name;\n            Data = stream.ToArray();\n        }\n    }\n\n    public class ImportedKeyframedAnimation\n    {\n        public string Name { get; set; }\n        public float SampleRate { get; set; }\n        public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }\n\n        public ImportedAnimationKeyframedTrack FindTrack(string path)\n        {\n            var track = TrackList.Find(x => x.Path == path);\n            if (track == null)\n            {\n                track = new ImportedAnimationKeyframedTrack { Path = path };\n                TrackList.Add(track);\n            }\n\n            return track;\n        }\n    }\n\n    public class ImportedAnimationKeyframedTrack\n    {\n        public string Path { get; set; }\n        public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();\n        public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();\n        public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();\n        public ImportedBlendShape BlendShape;\n    }\n\n    public class ImportedKeyframe<T>\n    {\n        public float time { get; set; }\n        public T value { get; set; }\n\n        public ImportedKeyframe(float time, T value)\n        {\n            this.time = time;\n            this.value = value;\n        }\n    }\n\n    public class ImportedBlendShape\n    {\n        public string ChannelName;\n        public List<ImportedKeyframe<float>> Keyframes = new List<ImportedKeyframe<float>>();\n    }\n\n    public class ImportedMorph\n    {\n        public string Path { get; set; }\n        public List<ImportedMorphChannel> Channels { get; set; }\n    }\n\n    public class ImportedMorphChannel\n    {\n        public string Name { get; set; }\n        public List<ImportedMorphKeyframe> KeyframeList { get; set; }\n    }\n\n    public class ImportedMorphKeyframe\n    {\n        public bool hasNormals { get; set; }\n        public bool hasTangents { get; set; }\n        public float Weight { get; set; }\n        public List<ImportedMorphVertex> VertexList { get; set; }\n    }\n\n    public class ImportedMorphVertex\n    {\n        public uint Index { get; set; }\n        public ImportedVertex Vertex { get; set; }\n    }\n\n    public static class ImportedHelpers\n    {\n        public static ImportedMesh FindMesh(string path, List<ImportedMesh> importedMeshList)\n        {\n            foreach (var mesh in importedMeshList)\n            {\n                if (mesh.Path == path)\n                {\n                    return mesh;\n                }\n            }\n\n            return null;\n        }\n\n        public static ImportedMaterial FindMaterial(string name, List<ImportedMaterial> importedMats)\n        {\n            foreach (var mat in importedMats)\n            {\n                if (mat.Name == name)\n                {\n                    return mat;\n                }\n            }\n\n            return null;\n        }\n\n        public static ImportedTexture FindTexture(string name, List<ImportedTexture> importedTextureList)\n        {\n            if (string.IsNullOrEmpty(name))\n            {\n                return null;\n            }\n\n            foreach (var tex in importedTextureList)\n            {\n                if (tex.Name == name)\n                {\n                    return tex;\n                }\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/ILogger.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public enum LoggerEvent\n    {\n        Verbose,\n        Debug,\n        Info,\n        Warning,\n        Error,\n    }\n\n    public interface ILogger\n    {\n        void Log(LoggerEvent loggerEvent, string message);\n    }\n\n    public sealed class DummyLogger : ILogger\n    {\n        public void Log(LoggerEvent loggerEvent, string message) { }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/ImportHelper.cs",
    "content": "﻿using Org.Brotli.Dec;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\n\nnamespace AssetStudio\n{\n    public static class ImportHelper\n    {\n        public static void MergeSplitAssets(string path, bool allDirectories = false)\n        {\n            var splitFiles = Directory.GetFiles(path, \"*.split0\", allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);\n            foreach (var splitFile in splitFiles)\n            {\n                var destFile = Path.GetFileNameWithoutExtension(splitFile);\n                var destPath = Path.GetDirectoryName(splitFile);\n                var destFull = Path.Combine(destPath, destFile);\n                if (!File.Exists(destFull))\n                {\n                    var splitParts = Directory.GetFiles(destPath, destFile + \".split*\");\n                    using (var destStream = File.Create(destFull))\n                    {\n                        for (int i = 0; i < splitParts.Length; i++)\n                        {\n                            var splitPart = destFull + \".split\" + i;\n                            using (var sourceStream = File.OpenRead(splitPart))\n                            {\n                                sourceStream.CopyTo(destStream);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        public static string[] ProcessingSplitFiles(List<string> selectFile)\n        {\n            var splitFiles = selectFile.Where(x => x.Contains(\".split\"))\n                .Select(x => Path.Combine(Path.GetDirectoryName(x), Path.GetFileNameWithoutExtension(x)))\n                .Distinct()\n                .ToList();\n            selectFile.RemoveAll(x => x.Contains(\".split\"));\n            foreach (var file in splitFiles)\n            {\n                if (File.Exists(file))\n                {\n                    selectFile.Add(file);\n                }\n            }\n            return selectFile.Distinct().ToArray();\n        }\n\n        public static FileReader DecompressGZip(FileReader reader)\n        {\n            using (reader)\n            {\n                var stream = new MemoryStream();\n                using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))\n                {\n                    gs.CopyTo(stream);\n                }\n                stream.Position = 0;\n                return new FileReader(reader.FullPath, stream);\n            }\n        }\n\n        public static FileReader DecompressBrotli(FileReader reader)\n        {\n            using (reader)\n            {\n                var stream = new MemoryStream();\n                using (var brotliStream = new BrotliInputStream(reader.BaseStream))\n                {\n                    brotliStream.CopyTo(stream);\n                }\n                stream.Position = 0;\n                return new FileReader(reader.FullPath, stream);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/LocalSerializedObjectIdentifier.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class LocalSerializedObjectIdentifier\n    {\n        public int localSerializedFileIndex;\n        public long localIdentifierInFile;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Logger.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public static class Logger\n    {\n        public static ILogger Default = new DummyLogger();\n\n        public static void Verbose(string message) => Default.Log(LoggerEvent.Verbose, message);\n        public static void Debug(string message) => Default.Log(LoggerEvent.Debug, message);\n        public static void Info(string message) => Default.Log(LoggerEvent.Info, message);\n        public static void Warning(string message) => Default.Log(LoggerEvent.Warning, message);\n        public static void Error(string message) => Default.Log(LoggerEvent.Error, message);\n\n        public static void Error(string message, Exception e)\n        {\n            var sb = new StringBuilder();\n            sb.AppendLine(message);\n            sb.AppendLine(e.ToString());\n            Default.Log(LoggerEvent.Error, sb.ToString());\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/Color.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct Color : IEquatable<Color>\n    {\n        public float R;\n        public float G;\n        public float B;\n        public float A;\n\n        public Color(float r, float g, float b, float a)\n        {\n            R = r;\n            G = g;\n            B = b;\n            A = a;\n        }\n\n        public override int GetHashCode()\n        {\n            return ((Vector4)this).GetHashCode();\n        }\n\n        public override bool Equals(object other)\n        {\n            if (!(other is Color))\n                return false;\n            return Equals((Color)other);\n        }\n\n        public bool Equals(Color other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);\n        }\n\n        public static Color operator +(Color a, Color b)\n        {\n            return new Color(a.R + b.R, a.G + b.G, a.B + b.B, a.A + b.A);\n        }\n\n        public static Color operator -(Color a, Color b)\n        {\n            return new Color(a.R - b.R, a.G - b.G, a.B - b.B, a.A - b.A);\n        }\n\n        public static Color operator *(Color a, Color b)\n        {\n            return new Color(a.R * b.R, a.G * b.G, a.B * b.B, a.A * b.A);\n        }\n\n        public static Color operator *(Color a, float b)\n        {\n            return new Color(a.R * b, a.G * b, a.B * b, a.A * b);\n        }\n\n        public static Color operator *(float b, Color a)\n        {\n            return new Color(a.R * b, a.G * b, a.B * b, a.A * b);\n        }\n\n        public static Color operator /(Color a, float b)\n        {\n            return new Color(a.R / b, a.G / b, a.B / b, a.A / b);\n        }\n\n        public static bool operator ==(Color lhs, Color rhs)\n        {\n            return (Vector4)lhs == (Vector4)rhs;\n        }\n\n        public static bool operator !=(Color lhs, Color rhs)\n        {\n            return !(lhs == rhs);\n        }\n\n        public static implicit operator Vector4(Color c)\n        {\n            return new Vector4(c.R, c.G, c.B, c.A);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/Half.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Globalization;\n\nnamespace AssetStudio\n{\n    /// <summary>\n    /// Represents a half-precision floating point number. \n    /// </summary>\n    /// <remarks>\n    /// Note:\n    ///     Half is not fast enought and precision is also very bad, \n    ///     so is should not be used for matemathical computation (use Single instead).\n    ///     The main advantage of Half type is lower memory cost: two bytes per number. \n    ///     Half is typically used in graphical applications.\n    ///     \n    /// Note: \n    ///     All functions, where is used conversion half->float/float->half, \n    ///     are approx. ten times slower than float->double/double->float, i.e. ~3ns on 2GHz CPU.\n    ///\n    /// References:\n    ///     - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf\n    ///     - IEEE 754 revision, link: http://grouper.ieee.org/groups/754/\n    /// </remarks>\n    [Serializable]\n    public struct Half : IComparable, IFormattable, IConvertible, IComparable<Half>, IEquatable<Half>\n    {\n        /// <summary>\n        /// Internal representation of the half-precision floating-point number.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        internal ushort value;\n\n        #region Constants\n        /// <summary>\n        /// Represents the smallest positive System.Half value greater than zero. This field is constant.\n        /// </summary>\n        public static readonly Half Epsilon = Half.ToHalf(0x0001);\n        /// <summary>\n        /// Represents the largest possible value of System.Half. This field is constant.\n        /// </summary>\n        public static readonly Half MaxValue = Half.ToHalf(0x7bff);\n        /// <summary>\n        /// Represents the smallest possible value of System.Half. This field is constant.\n        /// </summary>\n        public static readonly Half MinValue = Half.ToHalf(0xfbff);\n        /// <summary>\n        /// Represents not a number (NaN). This field is constant.\n        /// </summary>\n        public static readonly Half NaN = Half.ToHalf(0xfe00);\n        /// <summary>\n        /// Represents negative infinity. This field is constant.\n        /// </summary>\n        public static readonly Half NegativeInfinity = Half.ToHalf(0xfc00);\n        /// <summary>\n        /// Represents positive infinity. This field is constant.\n        /// </summary>\n        public static readonly Half PositiveInfinity = Half.ToHalf(0x7c00);\n        #endregion\n\n        #region Constructors\n        /// <summary>\n        /// Initializes a new instance of System.Half to the value of the specified single-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a System.Half.</param>\n        public Half(float value) { this = HalfHelper.SingleToHalf(value); }\n        /// <summary>\n        /// Initializes a new instance of System.Half to the value of the specified 32-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a System.Half.</param>\n        public Half(int value) : this((float)value) { }\n        /// <summary>\n        /// Initializes a new instance of System.Half to the value of the specified 64-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a System.Half.</param>\n        public Half(long value) : this((float)value) { }\n        /// <summary>\n        /// Initializes a new instance of System.Half to the value of the specified double-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a System.Half.</param>\n        public Half(double value) : this((float)value) { }\n        /// <summary>\n        /// Initializes a new instance of System.Half to the value of the specified decimal number.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a System.Half.</param>\n        public Half(decimal value) : this((float)value) { }\n        /// <summary>\n        /// Initializes a new instance of System.Half to the value of the specified 32-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a System.Half.</param>\n        public Half(uint value) : this((float)value) { }\n        /// <summary>\n        /// Initializes a new instance of System.Half to the value of the specified 64-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a System.Half.</param>\n        public Half(ulong value) : this((float)value) { }\n        #endregion\n\n        #region Numeric operators\n\n        /// <summary>\n        /// Returns the result of multiplying the specified System.Half value by negative one.\n        /// </summary>\n        /// <param name=\"half\">A System.Half.</param>\n        /// <returns>A System.Half with the value of half, but the opposite sign. -or- Zero, if half is zero.</returns>\n        public static Half Negate(Half half) { return -half; }\n        /// <summary>\n        /// Adds two specified System.Half values.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>A System.Half value that is the sum of half1 and half2.</returns>\n        public static Half Add(Half half1, Half half2) { return half1 + half2; }\n        /// <summary>\n        /// Subtracts one specified System.Half value from another.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half (the minuend).</param>\n        /// <param name=\"half2\">A System.Half (the subtrahend).</param>\n        /// <returns>The System.Half result of subtracting half2 from half1.</returns>\n        public static Half Subtract(Half half1, Half half2) { return half1 - half2; }\n        /// <summary>\n        /// Multiplies two specified System.Half values.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half (the multiplicand).</param>\n        /// <param name=\"half2\">A System.Half (the multiplier).</param>\n        /// <returns>A System.Half that is the result of multiplying half1 and half2.</returns>\n        public static Half Multiply(Half half1, Half half2) { return half1 * half2; }\n        /// <summary>\n        /// Divides two specified System.Half values.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half (the dividend).</param>\n        /// <param name=\"half2\">A System.Half (the divisor).</param>\n        /// <returns>The System.Half that is the result of dividing half1 by half2.</returns>\n        /// <exception cref=\"System.DivideByZeroException\">half2 is zero.</exception>\n        public static Half Divide(Half half1, Half half2) { return half1 / half2; }\n\n        /// <summary>\n        /// Returns the value of the System.Half operand (the sign of the operand is unchanged).\n        /// </summary>\n        /// <param name=\"half\">The System.Half operand.</param>\n        /// <returns>The value of the operand, half.</returns>\n        public static Half operator +(Half half) { return half; }\n        /// <summary>\n        /// Negates the value of the specified System.Half operand.\n        /// </summary>\n        /// <param name=\"half\">The System.Half operand.</param>\n        /// <returns>The result of half multiplied by negative one (-1).</returns>\n        public static Half operator -(Half half) { return HalfHelper.Negate(half); }\n        /// <summary>\n        /// Increments the System.Half operand by 1.\n        /// </summary>\n        /// <param name=\"half\">The System.Half operand.</param>\n        /// <returns>The value of half incremented by 1.</returns>\n        public static Half operator ++(Half half) { return (Half)(half + 1f); }\n        /// <summary>\n        /// Decrements the System.Half operand by one.\n        /// </summary>\n        /// <param name=\"half\">The System.Half operand.</param>\n        /// <returns>The value of half decremented by 1.</returns>\n        public static Half operator --(Half half) { return (Half)(half - 1f); }\n        /// <summary>\n        /// Adds two specified System.Half values.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>The System.Half result of adding half1 and half2.</returns>\n        public static Half operator +(Half half1, Half half2) { return (Half)((float)half1 + (float)half2); }\n        /// <summary>\n        /// Subtracts two specified System.Half values.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>The System.Half result of subtracting half1 and half2.</returns>        \n        public static Half operator -(Half half1, Half half2) { return (Half)((float)half1 - (float)half2); }\n        /// <summary>\n        /// Multiplies two specified System.Half values.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>The System.Half result of multiplying half1 by half2.</returns>\n        public static Half operator *(Half half1, Half half2) { return (Half)((float)half1 * (float)half2); }\n        /// <summary>\n        /// Divides two specified System.Half values.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half (the dividend).</param>\n        /// <param name=\"half2\">A System.Half (the divisor).</param>\n        /// <returns>The System.Half result of half1 by half2.</returns>\n        public static Half operator /(Half half1, Half half2) { return (Half)((float)half1 / (float)half2); }\n        /// <summary>\n        /// Returns a value indicating whether two instances of System.Half are equal.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>true if half1 and half2 are equal; otherwise, false.</returns>\n        public static bool operator ==(Half half1, Half half2) { return (!IsNaN(half1) && (half1.value == half2.value)); }\n        /// <summary>\n        /// Returns a value indicating whether two instances of System.Half are not equal.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>true if half1 and half2 are not equal; otherwise, false.</returns>\n        public static bool operator !=(Half half1, Half half2) { return !(half1.value == half2.value); }\n        /// <summary>\n        /// Returns a value indicating whether a specified System.Half is less than another specified System.Half.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>true if half1 is less than half1; otherwise, false.</returns>\n        public static bool operator <(Half half1, Half half2) { return (float)half1 < (float)half2; }\n        /// <summary>\n        /// Returns a value indicating whether a specified System.Half is greater than another specified System.Half.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>true if half1 is greater than half2; otherwise, false.</returns>\n        public static bool operator >(Half half1, Half half2) { return (float)half1 > (float)half2; }\n        /// <summary>\n        /// Returns a value indicating whether a specified System.Half is less than or equal to another specified System.Half.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>true if half1 is less than or equal to half2; otherwise, false.</returns>\n        public static bool operator <=(Half half1, Half half2) { return (half1 == half2) || (half1 < half2); }\n        /// <summary>\n        /// Returns a value indicating whether a specified System.Half is greater than or equal to another specified System.Half.\n        /// </summary>\n        /// <param name=\"half1\">A System.Half.</param>\n        /// <param name=\"half2\">A System.Half.</param>\n        /// <returns>true if half1 is greater than or equal to half2; otherwise, false.</returns>\n        public static bool operator >=(Half half1, Half half2) { return (half1 == half2) || (half1 > half2); }\n        #endregion\n\n        #region Type casting operators\n        /// <summary>\n        /// Converts an 8-bit unsigned integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">An 8-bit unsigned integer.</param>\n        /// <returns>A System.Half that represents the converted 8-bit unsigned integer.</returns>\n        public static implicit operator Half(byte value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a 16-bit signed integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A 16-bit signed integer.</param>\n        /// <returns>A System.Half that represents the converted 16-bit signed integer.</returns>\n        public static implicit operator Half(short value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a Unicode character to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A Unicode character.</param>\n        /// <returns>A System.Half that represents the converted Unicode character.</returns>\n        public static implicit operator Half(char value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a 32-bit signed integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A 32-bit signed integer.</param>\n        /// <returns>A System.Half that represents the converted 32-bit signed integer.</returns>\n        public static implicit operator Half(int value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a 64-bit signed integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A 64-bit signed integer.</param>\n        /// <returns>A System.Half that represents the converted 64-bit signed integer.</returns>\n        public static implicit operator Half(long value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a single-precision floating-point number to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A single-precision floating-point number.</param>\n        /// <returns>A System.Half that represents the converted single-precision floating point number.</returns>\n        public static explicit operator Half(float value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a double-precision floating-point number to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A double-precision floating-point number.</param>\n        /// <returns>A System.Half that represents the converted double-precision floating point number.</returns>\n        public static explicit operator Half(double value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a decimal number to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">decimal number</param>\n        /// <returns>A System.Half that represents the converted decimal number.</returns>\n        public static explicit operator Half(decimal value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a System.Half to an 8-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>An 8-bit unsigned integer that represents the converted System.Half.</returns>\n        public static explicit operator byte(Half value) { return (byte)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a Unicode character.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A Unicode character that represents the converted System.Half.</returns>\n        public static explicit operator char(Half value) { return (char)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a 16-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A 16-bit signed integer that represents the converted System.Half.</returns>\n        public static explicit operator short(Half value) { return (short)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a 32-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A 32-bit signed integer that represents the converted System.Half.</returns>\n        public static explicit operator int(Half value) { return (int)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a 64-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A 64-bit signed integer that represents the converted System.Half.</returns>\n        public static explicit operator long(Half value) { return (long)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a single-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A single-precision floating-point number that represents the converted System.Half.</returns>\n        public static implicit operator float(Half value) { return (float)HalfHelper.HalfToSingle(value); }\n        /// <summary>\n        /// Converts a System.Half to a double-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A double-precision floating-point number that represents the converted System.Half.</returns>\n        public static implicit operator double(Half value) { return (double)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a decimal number.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A decimal number that represents the converted System.Half.</returns>\n        public static explicit operator decimal(Half value) { return (decimal)(float)value; }\n        /// <summary>\n        /// Converts an 8-bit signed integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">An 8-bit signed integer.</param>\n        /// <returns>A System.Half that represents the converted 8-bit signed integer.</returns>\n        public static implicit operator Half(sbyte value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a 16-bit unsigned integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A 16-bit unsigned integer.</param>\n        /// <returns>A System.Half that represents the converted 16-bit unsigned integer.</returns>\n        public static implicit operator Half(ushort value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a 32-bit unsigned integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A 32-bit unsigned integer.</param>\n        /// <returns>A System.Half that represents the converted 32-bit unsigned integer.</returns>\n        public static implicit operator Half(uint value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a 64-bit unsigned integer to a System.Half.\n        /// </summary>\n        /// <param name=\"value\">A 64-bit unsigned integer.</param>\n        /// <returns>A System.Half that represents the converted 64-bit unsigned integer.</returns>\n        public static implicit operator Half(ulong value) { return new Half((float)value); }\n        /// <summary>\n        /// Converts a System.Half to an 8-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>An 8-bit signed integer that represents the converted System.Half.</returns>\n        public static explicit operator sbyte(Half value) { return (sbyte)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a 16-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A 16-bit unsigned integer that represents the converted System.Half.</returns>\n        public static explicit operator ushort(Half value) { return (ushort)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a 32-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A 32-bit unsigned integer that represents the converted System.Half.</returns>\n        public static explicit operator uint(Half value) { return (uint)(float)value; }\n        /// <summary>\n        /// Converts a System.Half to a 64-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A System.Half to convert.</param>\n        /// <returns>A 64-bit unsigned integer that represents the converted System.Half.</returns>\n        public static explicit operator ulong(Half value) { return (ulong)(float)value; }\n        #endregion\n\n        /// <summary>\n        /// Compares this instance to a specified System.Half object.\n        /// </summary>\n        /// <param name=\"other\">A System.Half object.</param>\n        /// <returns>\n        /// A signed number indicating the relative values of this instance and value.\n        /// Return Value Meaning Less than zero This instance is less than value. Zero\n        /// This instance is equal to value. Greater than zero This instance is greater than value.\n        /// </returns>\n        public int CompareTo(Half other)\n        {\n            int result = 0;\n            if (this < other)\n            {\n                result = -1;\n            }\n            else if (this > other)\n            {\n                result = 1;\n            }\n            else if (this != other)\n            {\n                if (!IsNaN(this))\n                {\n                    result = 1;\n                }\n                else if (!IsNaN(other))\n                {\n                    result = -1;\n                }\n            }\n\n            return result;\n        }\n        /// <summary>\n        /// Compares this instance to a specified System.Object.\n        /// </summary>\n        /// <param name=\"obj\">An System.Object or null.</param>\n        /// <returns>\n        /// A signed number indicating the relative values of this instance and value.\n        /// Return Value Meaning Less than zero This instance is less than value. Zero\n        /// This instance is equal to value. Greater than zero This instance is greater\n        /// than value. -or- value is null.\n        /// </returns>\n        /// <exception cref=\"System.ArgumentException\">value is not a System.Half</exception>\n        public int CompareTo(object obj)\n        {\n            int result = 0;\n            if (obj == null)\n            {\n                result = 1;\n            }\n            else\n            {\n                if (obj is Half)\n                {\n                    result = CompareTo((Half)obj);\n                }\n                else\n                {\n                    throw new ArgumentException(\"Object must be of type Half.\");\n                }\n            }\n\n            return result;\n        }\n        /// <summary>\n        /// Returns a value indicating whether this instance and a specified System.Half object represent the same value.\n        /// </summary>\n        /// <param name=\"other\">A System.Half object to compare to this instance.</param>\n        /// <returns>true if value is equal to this instance; otherwise, false.</returns>\n        public bool Equals(Half other)\n        {\n            return ((other == this) || (IsNaN(other) && IsNaN(this)));\n        }\n        /// <summary>\n        /// Returns a value indicating whether this instance and a specified System.Object\n        /// represent the same type and value.\n        /// </summary>\n        /// <param name=\"obj\">An System.Object.</param>\n        /// <returns>true if value is a System.Half and equal to this instance; otherwise, false.</returns>\n        public override bool Equals(object obj)\n        {\n            bool result = false;\n            if (obj is Half)\n            {\n                Half half = (Half)obj;\n                if ((half == this) || (IsNaN(half) && IsNaN(this)))\n                {\n                    result = true;\n                }\n            }\n\n            return result;\n        }\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns>A 32-bit signed integer hash code.</returns>\n        public override int GetHashCode()\n        {\n            return value.GetHashCode();\n        }\n        /// <summary>\n        /// Returns the System.TypeCode for value type System.Half.\n        /// </summary>\n        /// <returns>The enumerated constant (TypeCode)255.</returns>\n        public TypeCode GetTypeCode()\n        {\n            return (TypeCode)255;\n        }\n\n        #region BitConverter & Math methods for Half\n        /// <summary>\n        /// Returns the specified half-precision floating point value as an array of bytes.\n        /// </summary>\n        /// <param name=\"value\">The number to convert.</param>\n        /// <returns>An array of bytes with length 2.</returns>\n        public static byte[] GetBytes(Half value)\n        {\n            return BitConverter.GetBytes(value.value);\n        }\n        /// <summary>\n        /// Converts the value of a specified instance of System.Half to its equivalent binary representation.\n        /// </summary>\n        /// <param name=\"value\">A System.Half value.</param>\n        /// <returns>A 16-bit unsigned integer that contain the binary representation of value.</returns>        \n        public static ushort GetBits(Half value)\n        {\n            return value.value;\n        }\n        /// <summary>\n        /// Returns a half-precision floating point number converted from two bytes\n        /// at a specified position in a byte array.\n        /// </summary>\n        /// <param name=\"value\">An array of bytes.</param>\n        /// <param name=\"startIndex\">The starting position within value.</param>\n        /// <returns>A half-precision floating point number formed by two bytes beginning at startIndex.</returns>\n        /// <exception cref=\"System.ArgumentException\">\n        /// startIndex is greater than or equal to the length of value minus 1, and is\n        /// less than or equal to the length of value minus 1.\n        /// </exception>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.ArgumentOutOfRangeException\">startIndex is less than zero or greater than the length of value minus 1.</exception>\n        public static Half ToHalf(byte[] value, int startIndex)\n        {\n            return Half.ToHalf((ushort)BitConverter.ToInt16(value, startIndex));\n        }\n        /// <summary>\n        /// Returns a half-precision floating point number converted from its binary representation.\n        /// </summary>\n        /// <param name=\"bits\">Binary representation of System.Half value</param>\n        /// <returns>A half-precision floating point number formed by its binary representation.</returns>\n        public static Half ToHalf(ushort bits)\n        {\n            return new Half { value = bits };\n        }\n\n        /// <summary>\n        /// Returns a value indicating the sign of a half-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A signed number.</param>\n        /// <returns>\n        /// A number indicating the sign of value. Number Description -1 value is less\n        /// than zero. 0 value is equal to zero. 1 value is greater than zero.\n        /// </returns>\n        /// <exception cref=\"System.ArithmeticException\">value is equal to System.Half.NaN.</exception>\n        public static int Sign(Half value)\n        {\n            if (value < 0)\n            {\n                return -1;\n            }\n            else if (value > 0)\n            {\n                return 1;\n            }\n            else\n            {\n                if (value != 0)\n                {\n                    throw new ArithmeticException(\"Function does not accept floating point Not-a-Number values.\");\n                }\n            }\n\n            return 0;\n        }\n        /// <summary>\n        /// Returns the absolute value of a half-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A number in the range System.Half.MinValue ≤ value ≤ System.Half.MaxValue.</param>\n        /// <returns>A half-precision floating-point number, x, such that 0 ≤ x ≤System.Half.MaxValue.</returns>\n        public static Half Abs(Half value)\n        {\n            return HalfHelper.Abs(value);\n        }\n        /// <summary>\n        /// Returns the larger of two half-precision floating-point numbers.\n        /// </summary>\n        /// <param name=\"value1\">The first of two half-precision floating-point numbers to compare.</param>\n        /// <param name=\"value2\">The second of two half-precision floating-point numbers to compare.</param>\n        /// <returns>\n        /// Parameter value1 or value2, whichever is larger. If value1, or value2, or both val1\n        /// and value2 are equal to System.Half.NaN, System.Half.NaN is returned.\n        /// </returns>\n        public static Half Max(Half value1, Half value2)\n        {\n            return (value1 < value2) ? value2 : value1;\n        }\n        /// <summary>\n        /// Returns the smaller of two half-precision floating-point numbers.\n        /// </summary>\n        /// <param name=\"value1\">The first of two half-precision floating-point numbers to compare.</param>\n        /// <param name=\"value2\">The second of two half-precision floating-point numbers to compare.</param>\n        /// <returns>\n        /// Parameter value1 or value2, whichever is smaller. If value1, or value2, or both val1\n        /// and value2 are equal to System.Half.NaN, System.Half.NaN is returned.\n        /// </returns>\n        public static Half Min(Half value1, Half value2)\n        {\n            return (value1 < value2) ? value1 : value2;\n        }\n        #endregion\n\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to not a number (System.Half.NaN).\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if value evaluates to not a number (System.Half.NaN); otherwise, false.</returns>\n        public static bool IsNaN(Half half)\n        {\n            return HalfHelper.IsNaN(half);\n        }\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to negative or positive infinity.\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if half evaluates to System.Half.PositiveInfinity or System.Half.NegativeInfinity; otherwise, false.</returns>\n        public static bool IsInfinity(Half half)\n        {\n            return HalfHelper.IsInfinity(half);\n        }\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to negative infinity.\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if half evaluates to System.Half.NegativeInfinity; otherwise, false.</returns>\n        public static bool IsNegativeInfinity(Half half)\n        {\n            return HalfHelper.IsNegativeInfinity(half);\n        }\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to positive infinity.\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if half evaluates to System.Half.PositiveInfinity; otherwise, false.</returns>\n        public static bool IsPositiveInfinity(Half half)\n        {\n            return HalfHelper.IsPositiveInfinity(half);\n        }\n\n        #region String operations (Parse and ToString)\n        /// <summary>\n        /// Converts the string representation of a number to its System.Half equivalent.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <returns>The System.Half number equivalent to the number contained in value.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>\n        public static Half Parse(string value)\n        {\n            return (Half)float.Parse(value, CultureInfo.InvariantCulture);\n        }\n        /// <summary>\n        /// Converts the string representation of a number to its System.Half equivalent \n        /// using the specified culture-specific format information.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"provider\">An System.IFormatProvider that supplies culture-specific parsing information about value.</param>\n        /// <returns>The System.Half number equivalent to the number contained in s as specified by provider.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>\n        public static Half Parse(string value, IFormatProvider provider)\n        {\n            return (Half)float.Parse(value, provider);\n        }\n        /// <summary>\n        /// Converts the string representation of a number in a specified style to its System.Half equivalent.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"style\">\n        /// A bitwise combination of System.Globalization.NumberStyles values that indicates\n        /// the style elements that can be present in value. A typical value to specify is\n        /// System.Globalization.NumberStyles.Number.\n        /// </param>\n        /// <returns>The System.Half number equivalent to the number contained in s as specified by style.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.ArgumentException\">\n        /// style is not a System.Globalization.NumberStyles value. -or- style is the\n        /// System.Globalization.NumberStyles.AllowHexSpecifier value.\n        /// </exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>\n        public static Half Parse(string value, NumberStyles style)\n        {\n            return (Half)float.Parse(value, style, CultureInfo.InvariantCulture);\n        }\n        /// <summary>\n        /// Converts the string representation of a number to its System.Half equivalent \n        /// using the specified style and culture-specific format.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"style\">\n        /// A bitwise combination of System.Globalization.NumberStyles values that indicates\n        /// the style elements that can be present in value. A typical value to specify is \n        /// System.Globalization.NumberStyles.Number.\n        /// </param>\n        /// <param name=\"provider\">An System.IFormatProvider object that supplies culture-specific information about the format of value.</param>\n        /// <returns>The System.Half number equivalent to the number contained in s as specified by style and provider.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.ArgumentException\">\n        /// style is not a System.Globalization.NumberStyles value. -or- style is the\n        /// System.Globalization.NumberStyles.AllowHexSpecifier value.\n        /// </exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>\n        public static Half Parse(string value, NumberStyles style, IFormatProvider provider)\n        {\n            return (Half)float.Parse(value, style, provider);\n        }\n        /// <summary>\n        /// Converts the string representation of a number to its System.Half equivalent.\n        /// A return value indicates whether the conversion succeeded or failed.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"result\">\n        /// When this method returns, contains the System.Half number that is equivalent\n        /// to the numeric value contained in value, if the conversion succeeded, or is zero\n        /// if the conversion failed. The conversion fails if the s parameter is null,\n        /// is not a number in a valid format, or represents a number less than System.Half.MinValue\n        /// or greater than System.Half.MaxValue. This parameter is passed uninitialized.\n        /// </param>\n        /// <returns>true if s was converted successfully; otherwise, false.</returns>\n        public static bool TryParse(string value, out Half result)\n        {\n            float f;\n            if (float.TryParse(value, out f))\n            {\n                result = (Half)f;\n                return true;\n            }\n\n            result = new Half();\n            return false;\n        }\n        /// <summary>\n        /// Converts the string representation of a number to its System.Half equivalent\n        /// using the specified style and culture-specific format. A return value indicates\n        /// whether the conversion succeeded or failed.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"style\">\n        /// A bitwise combination of System.Globalization.NumberStyles values that indicates\n        /// the permitted format of value. A typical value to specify is System.Globalization.NumberStyles.Number.\n        /// </param>\n        /// <param name=\"provider\">An System.IFormatProvider object that supplies culture-specific parsing information about value.</param>\n        /// <param name=\"result\">\n        /// When this method returns, contains the System.Half number that is equivalent\n        /// to the numeric value contained in value, if the conversion succeeded, or is zero\n        /// if the conversion failed. The conversion fails if the s parameter is null,\n        /// is not in a format compliant with style, or represents a number less than\n        /// System.Half.MinValue or greater than System.Half.MaxValue. This parameter is passed uninitialized.\n        /// </param>\n        /// <returns>true if s was converted successfully; otherwise, false.</returns>\n        /// <exception cref=\"System.ArgumentException\">\n        /// style is not a System.Globalization.NumberStyles value. -or- style \n        /// is the System.Globalization.NumberStyles.AllowHexSpecifier value.\n        /// </exception>\n        public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out Half result)\n        {\n            bool parseResult = false;\n            float f;\n            if (float.TryParse(value, style, provider, out f))\n            {\n                result = (Half)f;\n                parseResult = true;\n            }\n            else\n            {\n                result = new Half();\n            }\n\n            return parseResult;\n        }\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation.\n        /// </summary>\n        /// <returns>A string that represents the value of this instance.</returns>\n        public override string ToString()\n        {\n            return ((float)this).ToString(CultureInfo.InvariantCulture);\n        }\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation\n        /// using the specified culture-specific format information.\n        /// </summary>\n        /// <param name=\"formatProvider\">An System.IFormatProvider that supplies culture-specific formatting information.</param>\n        /// <returns>The string representation of the value of this instance as specified by provider.</returns>\n        public string ToString(IFormatProvider formatProvider)\n        {\n            return ((float)this).ToString(formatProvider);\n        }\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation, using the specified format.\n        /// </summary>\n        /// <param name=\"format\">A numeric format string.</param>\n        /// <returns>The string representation of the value of this instance as specified by format.</returns>\n        public string ToString(string format)\n        {\n            return ((float)this).ToString(format, CultureInfo.InvariantCulture);\n        }\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation \n        /// using the specified format and culture-specific format information.\n        /// </summary>\n        /// <param name=\"format\">A numeric format string.</param>\n        /// <param name=\"formatProvider\">An System.IFormatProvider that supplies culture-specific formatting information.</param>\n        /// <returns>The string representation of the value of this instance as specified by format and provider.</returns>\n        /// <exception cref=\"System.FormatException\">format is invalid.</exception>\n        public string ToString(string format, IFormatProvider formatProvider)\n        {\n            return ((float)this).ToString(format, formatProvider);\n        }\n        #endregion\n\n        #region IConvertible Members\n        float IConvertible.ToSingle(IFormatProvider provider)\n        {\n            return (float)this;\n        }\n        TypeCode IConvertible.GetTypeCode()\n        {\n            return GetTypeCode();\n        }\n        bool IConvertible.ToBoolean(IFormatProvider provider)\n        {\n            return Convert.ToBoolean((float)this);\n        }\n        byte IConvertible.ToByte(IFormatProvider provider)\n        {\n            return Convert.ToByte((float)this);\n        }\n        char IConvertible.ToChar(IFormatProvider provider)\n        {\n            throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, \"Invalid cast from '{0}' to '{1}'.\", \"Half\", \"Char\"));\n        }\n        DateTime IConvertible.ToDateTime(IFormatProvider provider)\n        {\n            throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, \"Invalid cast from '{0}' to '{1}'.\", \"Half\", \"DateTime\"));\n        }\n        decimal IConvertible.ToDecimal(IFormatProvider provider)\n        {\n            return Convert.ToDecimal((float)this);\n        }\n        double IConvertible.ToDouble(IFormatProvider provider)\n        {\n            return Convert.ToDouble((float)this);\n        }\n        short IConvertible.ToInt16(IFormatProvider provider)\n        {\n            return Convert.ToInt16((float)this);\n        }\n        int IConvertible.ToInt32(IFormatProvider provider)\n        {\n            return Convert.ToInt32((float)this);\n        }\n        long IConvertible.ToInt64(IFormatProvider provider)\n        {\n            return Convert.ToInt64((float)this);\n        }\n        sbyte IConvertible.ToSByte(IFormatProvider provider)\n        {\n            return Convert.ToSByte((float)this);\n        }\n        string IConvertible.ToString(IFormatProvider provider)\n        {\n            return Convert.ToString((float)this, CultureInfo.InvariantCulture);\n        }\n        object IConvertible.ToType(Type conversionType, IFormatProvider provider)\n        {\n            return (((float)this) as IConvertible).ToType(conversionType, provider);\n        }\n        ushort IConvertible.ToUInt16(IFormatProvider provider)\n        {\n            return Convert.ToUInt16((float)this);\n        }\n        uint IConvertible.ToUInt32(IFormatProvider provider)\n        {\n            return Convert.ToUInt32((float)this);\n        }\n        ulong IConvertible.ToUInt64(IFormatProvider provider)\n        {\n            return Convert.ToUInt64((float)this);\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/HalfHelper.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    /// <summary>\n    /// Helper class for Half conversions and some low level operations.\n    /// This class is internally used in the Half class.\n    /// </summary>\n    /// <remarks>\n    /// References:\n    ///     - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf\n    /// </remarks>\n    [ComVisible(false)]\n    internal static class HalfHelper\n    {\n        private static uint[] mantissaTable = GenerateMantissaTable();\n        private static uint[] exponentTable = GenerateExponentTable();\n        private static ushort[] offsetTable = GenerateOffsetTable();\n        private static ushort[] baseTable = GenerateBaseTable();\n        private static sbyte[] shiftTable = GenerateShiftTable();\n\n        // Transforms the subnormal representation to a normalized one. \n        private static uint ConvertMantissa(int i)\n        {\n            uint m = (uint)(i << 13); // Zero pad mantissa bits\n            uint e = 0; // Zero exponent\n\n            // While not normalized\n            while ((m & 0x00800000) == 0)\n            {\n                e -= 0x00800000; // Decrement exponent (1<<23)\n                m <<= 1; // Shift mantissa                \n            }\n            m &= unchecked((uint)~0x00800000); // Clear leading 1 bit\n            e += 0x38800000; // Adjust bias ((127-14)<<23)\n            return m | e; // Return combined number\n        }\n\n        private static uint[] GenerateMantissaTable()\n        {\n            uint[] mantissaTable = new uint[2048];\n            mantissaTable[0] = 0;\n            for (int i = 1; i < 1024; i++)\n            {\n                mantissaTable[i] = ConvertMantissa(i);\n            }\n            for (int i = 1024; i < 2048; i++)\n            {\n                mantissaTable[i] = (uint)(0x38000000 + ((i - 1024) << 13));\n            }\n\n            return mantissaTable;\n        }\n        private static uint[] GenerateExponentTable()\n        {\n            uint[] exponentTable = new uint[64];\n            exponentTable[0] = 0;\n            for (int i = 1; i < 31; i++)\n            {\n                exponentTable[i] = (uint)(i << 23);\n            }\n            exponentTable[31] = 0x47800000;\n            exponentTable[32] = 0x80000000;\n            for (int i = 33; i < 63; i++)\n            {\n                exponentTable[i] = (uint)(0x80000000 + ((i - 32) << 23));\n            }\n            exponentTable[63] = 0xc7800000;\n\n            return exponentTable;\n        }\n        private static ushort[] GenerateOffsetTable()\n        {\n            ushort[] offsetTable = new ushort[64];\n            offsetTable[0] = 0;\n            for (int i = 1; i < 32; i++)\n            {\n                offsetTable[i] = 1024;\n            }\n            offsetTable[32] = 0;\n            for (int i = 33; i < 64; i++)\n            {\n                offsetTable[i] = 1024;\n            }\n\n            return offsetTable;\n        }\n        private static ushort[] GenerateBaseTable()\n        {\n            ushort[] baseTable = new ushort[512];\n            for (int i = 0; i < 256; ++i)\n            {\n                sbyte e = (sbyte)(127 - i);\n                if (e > 24)\n                { // Very small numbers map to zero\n                    baseTable[i | 0x000] = 0x0000;\n                    baseTable[i | 0x100] = 0x8000;\n                }\n                else if (e > 14)\n                { // Small numbers map to denorms\n                    baseTable[i | 0x000] = (ushort)(0x0400 >> (18 + e));\n                    baseTable[i | 0x100] = (ushort)((0x0400 >> (18 + e)) | 0x8000);\n                }\n                else if (e >= -15)\n                { // Normal numbers just lose precision\n                    baseTable[i | 0x000] = (ushort)((15 - e) << 10);\n                    baseTable[i | 0x100] = (ushort)(((15 - e) << 10) | 0x8000);\n                }\n                else if (e > -128)\n                { // Large numbers map to Infinity\n                    baseTable[i | 0x000] = 0x7c00;\n                    baseTable[i | 0x100] = 0xfc00;\n                }\n                else\n                { // Infinity and NaN's stay Infinity and NaN's\n                    baseTable[i | 0x000] = 0x7c00;\n                    baseTable[i | 0x100] = 0xfc00;\n                }\n            }\n\n            return baseTable;\n        }\n        private static sbyte[] GenerateShiftTable()\n        {\n            sbyte[] shiftTable = new sbyte[512];\n            for (int i = 0; i < 256; ++i)\n            {\n                sbyte e = (sbyte)(127 - i);\n                if (e > 24)\n                { // Very small numbers map to zero\n                    shiftTable[i | 0x000] = 24;\n                    shiftTable[i | 0x100] = 24;\n                }\n                else if (e > 14)\n                { // Small numbers map to denorms\n                    shiftTable[i | 0x000] = (sbyte)(e - 1);\n                    shiftTable[i | 0x100] = (sbyte)(e - 1);\n                }\n                else if (e >= -15)\n                { // Normal numbers just lose precision\n                    shiftTable[i | 0x000] = 13;\n                    shiftTable[i | 0x100] = 13;\n                }\n                else if (e > -128)\n                { // Large numbers map to Infinity\n                    shiftTable[i | 0x000] = 24;\n                    shiftTable[i | 0x100] = 24;\n                }\n                else\n                { // Infinity and NaN's stay Infinity and NaN's\n                    shiftTable[i | 0x000] = 13;\n                    shiftTable[i | 0x100] = 13;\n                }\n            }\n\n            return shiftTable;\n        }\n\n        /*public static unsafe float HalfToSingle(Half half)\n        {\n            uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];\n            return *((float*)&result);\n        }\n        public static unsafe Half SingleToHalf(float single)\n        {\n            uint value = *((uint*)&single);\n\n            ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));\n            return Half.ToHalf(result);\n        }*/\n        public static float HalfToSingle(Half half)\n        {\n            uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];\n            byte[] uintBytes = BitConverter.GetBytes(result);\n            return BitConverter.ToSingle(uintBytes, 0);\n        }\n        public static Half SingleToHalf(float single)\n        {\n            byte[] singleBytes = BitConverter.GetBytes(single);\n            uint value = BitConverter.ToUInt32(singleBytes, 0);\n            ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));\n            return Half.ToHalf(result);\n        }\n\n        public static Half Negate(Half half)\n        {\n            return Half.ToHalf((ushort)(half.value ^ 0x8000));\n        }\n        public static Half Abs(Half half)\n        {\n            return Half.ToHalf((ushort)(half.value & 0x7fff));\n        }\n\n        public static bool IsNaN(Half half)\n        {\n            return ((half.value & 0x7fff) > 0x7c00);\n        }\n        public static bool IsInfinity(Half half)\n        {\n            return ((half.value & 0x7fff) == 0x7c00);\n        }\n        public static bool IsPositiveInfinity(Half half)\n        {\n            return (half.value == 0x7c00);\n        }\n        public static bool IsNegativeInfinity(Half half)\n        {\n            return (half.value == 0xfc00);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/Matrix4x4.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct Matrix4x4 : IEquatable<Matrix4x4>\n    {\n        public float M00;\n        public float M10;\n        public float M20;\n        public float M30;\n\n        public float M01;\n        public float M11;\n        public float M21;\n        public float M31;\n\n        public float M02;\n        public float M12;\n        public float M22;\n        public float M32;\n\n        public float M03;\n        public float M13;\n        public float M23;\n        public float M33;\n\n        public Matrix4x4(float[] values)\n        {\n            if (values == null)\n                throw new ArgumentNullException(nameof(values));\n            if (values.Length != 16)\n                throw new ArgumentOutOfRangeException(nameof(values), \"There must be sixteen and only sixteen input values for Matrix.\");\n\n            M00 = values[0];\n            M10 = values[1];\n            M20 = values[2];\n            M30 = values[3];\n\n            M01 = values[4];\n            M11 = values[5];\n            M21 = values[6];\n            M31 = values[7];\n\n            M02 = values[8];\n            M12 = values[9];\n            M22 = values[10];\n            M32 = values[11];\n\n            M03 = values[12];\n            M13 = values[13];\n            M23 = values[14];\n            M33 = values[15];\n        }\n\n        public float this[int row, int column]\n        {\n            get => this[row + column * 4];\n\n            set => this[row + column * 4] = value;\n        }\n\n        public float this[int index]\n        {\n            get\n            {\n                switch (index)\n                {\n                    case 0: return M00;\n                    case 1: return M10;\n                    case 2: return M20;\n                    case 3: return M30;\n                    case 4: return M01;\n                    case 5: return M11;\n                    case 6: return M21;\n                    case 7: return M31;\n                    case 8: return M02;\n                    case 9: return M12;\n                    case 10: return M22;\n                    case 11: return M32;\n                    case 12: return M03;\n                    case 13: return M13;\n                    case 14: return M23;\n                    case 15: return M33;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Matrix4x4 index!\");\n                }\n            }\n\n            set\n            {\n                switch (index)\n                {\n                    case 0: M00 = value; break;\n                    case 1: M10 = value; break;\n                    case 2: M20 = value; break;\n                    case 3: M30 = value; break;\n                    case 4: M01 = value; break;\n                    case 5: M11 = value; break;\n                    case 6: M21 = value; break;\n                    case 7: M31 = value; break;\n                    case 8: M02 = value; break;\n                    case 9: M12 = value; break;\n                    case 10: M22 = value; break;\n                    case 11: M32 = value; break;\n                    case 12: M03 = value; break;\n                    case 13: M13 = value; break;\n                    case 14: M23 = value; break;\n                    case 15: M33 = value; break;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Matrix4x4 index!\");\n                }\n            }\n        }\n\n        public override int GetHashCode()\n        {\n            return GetColumn(0).GetHashCode() ^ (GetColumn(1).GetHashCode() << 2) ^ (GetColumn(2).GetHashCode() >> 2) ^ (GetColumn(3).GetHashCode() >> 1);\n        }\n\n        public override bool Equals(object other)\n        {\n            if (!(other is Matrix4x4))\n                return false;\n            return Equals((Matrix4x4)other);\n        }\n\n        public bool Equals(Matrix4x4 other)\n        {\n            return GetColumn(0).Equals(other.GetColumn(0))\n                   && GetColumn(1).Equals(other.GetColumn(1))\n                   && GetColumn(2).Equals(other.GetColumn(2))\n                   && GetColumn(3).Equals(other.GetColumn(3));\n        }\n\n        public Vector4 GetColumn(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Vector4(M00, M10, M20, M30);\n                case 1: return new Vector4(M01, M11, M21, M31);\n                case 2: return new Vector4(M02, M12, M22, M32);\n                case 3: return new Vector4(M03, M13, M23, M33);\n                default: throw new IndexOutOfRangeException(\"Invalid column index!\");\n            }\n        }\n\n        public Vector4 GetRow(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Vector4(M00, M01, M02, M03);\n                case 1: return new Vector4(M10, M11, M12, M13);\n                case 2: return new Vector4(M20, M21, M22, M23);\n                case 3: return new Vector4(M30, M31, M32, M33);\n                default: throw new IndexOutOfRangeException(\"Invalid row index!\");\n            }\n        }\n\n        public static Matrix4x4 operator *(Matrix4x4 lhs, Matrix4x4 rhs)\n        {\n            Matrix4x4 res;\n            res.M00 = lhs.M00 * rhs.M00 + lhs.M01 * rhs.M10 + lhs.M02 * rhs.M20 + lhs.M03 * rhs.M30;\n            res.M01 = lhs.M00 * rhs.M01 + lhs.M01 * rhs.M11 + lhs.M02 * rhs.M21 + lhs.M03 * rhs.M31;\n            res.M02 = lhs.M00 * rhs.M02 + lhs.M01 * rhs.M12 + lhs.M02 * rhs.M22 + lhs.M03 * rhs.M32;\n            res.M03 = lhs.M00 * rhs.M03 + lhs.M01 * rhs.M13 + lhs.M02 * rhs.M23 + lhs.M03 * rhs.M33;\n\n            res.M10 = lhs.M10 * rhs.M00 + lhs.M11 * rhs.M10 + lhs.M12 * rhs.M20 + lhs.M13 * rhs.M30;\n            res.M11 = lhs.M10 * rhs.M01 + lhs.M11 * rhs.M11 + lhs.M12 * rhs.M21 + lhs.M13 * rhs.M31;\n            res.M12 = lhs.M10 * rhs.M02 + lhs.M11 * rhs.M12 + lhs.M12 * rhs.M22 + lhs.M13 * rhs.M32;\n            res.M13 = lhs.M10 * rhs.M03 + lhs.M11 * rhs.M13 + lhs.M12 * rhs.M23 + lhs.M13 * rhs.M33;\n\n            res.M20 = lhs.M20 * rhs.M00 + lhs.M21 * rhs.M10 + lhs.M22 * rhs.M20 + lhs.M23 * rhs.M30;\n            res.M21 = lhs.M20 * rhs.M01 + lhs.M21 * rhs.M11 + lhs.M22 * rhs.M21 + lhs.M23 * rhs.M31;\n            res.M22 = lhs.M20 * rhs.M02 + lhs.M21 * rhs.M12 + lhs.M22 * rhs.M22 + lhs.M23 * rhs.M32;\n            res.M23 = lhs.M20 * rhs.M03 + lhs.M21 * rhs.M13 + lhs.M22 * rhs.M23 + lhs.M23 * rhs.M33;\n\n            res.M30 = lhs.M30 * rhs.M00 + lhs.M31 * rhs.M10 + lhs.M32 * rhs.M20 + lhs.M33 * rhs.M30;\n            res.M31 = lhs.M30 * rhs.M01 + lhs.M31 * rhs.M11 + lhs.M32 * rhs.M21 + lhs.M33 * rhs.M31;\n            res.M32 = lhs.M30 * rhs.M02 + lhs.M31 * rhs.M12 + lhs.M32 * rhs.M22 + lhs.M33 * rhs.M32;\n            res.M33 = lhs.M30 * rhs.M03 + lhs.M31 * rhs.M13 + lhs.M32 * rhs.M23 + lhs.M33 * rhs.M33;\n\n            return res;\n        }\n\n        public static bool operator ==(Matrix4x4 lhs, Matrix4x4 rhs)\n        {\n            return lhs.GetColumn(0) == rhs.GetColumn(0)\n                && lhs.GetColumn(1) == rhs.GetColumn(1)\n                && lhs.GetColumn(2) == rhs.GetColumn(2)\n                && lhs.GetColumn(3) == rhs.GetColumn(3);\n        }\n\n        public static bool operator !=(Matrix4x4 lhs, Matrix4x4 rhs)\n        {\n            return !(lhs == rhs);\n        }\n\n        public static Matrix4x4 Scale(Vector3 vector)\n        {\n            Matrix4x4 m;\n            m.M00 = vector.X; m.M01 = 0F; m.M02 = 0F; m.M03 = 0F;\n            m.M10 = 0F; m.M11 = vector.Y; m.M12 = 0F; m.M13 = 0F;\n            m.M20 = 0F; m.M21 = 0F; m.M22 = vector.Z; m.M23 = 0F;\n            m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;\n            return m;\n        }\n\n        public static Matrix4x4 Translate(Vector3 vector)\n        {\n            Matrix4x4 m;\n            m.M00 = 1F; m.M01 = 0F; m.M02 = 0F; m.M03 = vector.X;\n            m.M10 = 0F; m.M11 = 1F; m.M12 = 0F; m.M13 = vector.Y;\n            m.M20 = 0F; m.M21 = 0F; m.M22 = 1F; m.M23 = vector.Z;\n            m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;\n            return m;\n        }\n\n        public static Matrix4x4 Rotate(Quaternion q)\n        {\n            float x = q.X * 2.0F;\n            float y = q.Y * 2.0F;\n            float z = q.Z * 2.0F;\n            float xx = q.X * x;\n            float yy = q.Y * y;\n            float zz = q.Z * z;\n            float xy = q.X * y;\n            float xz = q.X * z;\n            float yz = q.Y * z;\n            float wx = q.W * x;\n            float wy = q.W * y;\n            float wz = q.W * z;\n\n            Matrix4x4 m;\n            m.M00 = 1.0f - (yy + zz); m.M10 = xy + wz; m.M20 = xz - wy; m.M30 = 0.0F;\n            m.M01 = xy - wz; m.M11 = 1.0f - (xx + zz); m.M21 = yz + wx; m.M31 = 0.0F;\n            m.M02 = xz + wy; m.M12 = yz - wx; m.M22 = 1.0f - (xx + yy); m.M32 = 0.0F;\n            m.M03 = 0.0F; m.M13 = 0.0F; m.M23 = 0.0F; m.M33 = 1.0F;\n            return m;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/Quaternion.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct Quaternion : IEquatable<Quaternion>\n    {\n        public float X;\n        public float Y;\n        public float Z;\n        public float W;\n\n        public Quaternion(float x, float y, float z, float w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        public float this[int index]\n        {\n            get\n            {\n                switch (index)\n                {\n                    case 0: return X;\n                    case 1: return Y;\n                    case 2: return Z;\n                    case 3: return W;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Quaternion index!\");\n                }\n            }\n\n            set\n            {\n                switch (index)\n                {\n                    case 0: X = value; break;\n                    case 1: Y = value; break;\n                    case 2: Z = value; break;\n                    case 3: W = value; break;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Quaternion index!\");\n                }\n            }\n        }\n\n        public override int GetHashCode()\n        {\n            return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);\n        }\n\n        public override bool Equals(object other)\n        {\n            if (!(other is Quaternion))\n                return false;\n            return Equals((Quaternion)other);\n        }\n\n        public bool Equals(Quaternion other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);\n        }\n\n        public static float Dot(Quaternion a, Quaternion b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;\n        }\n\n        private static bool IsEqualUsingDot(float dot)\n        {\n            return dot > 1.0f - kEpsilon;\n        }\n\n        public static bool operator ==(Quaternion lhs, Quaternion rhs)\n        {\n            return IsEqualUsingDot(Dot(lhs, rhs));\n        }\n\n        public static bool operator !=(Quaternion lhs, Quaternion rhs)\n        {\n            return !(lhs == rhs);\n        }\n\n        private const float kEpsilon = 0.000001F;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/Vector2.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct Vector2 : IEquatable<Vector2>\n    {\n        public float X;\n        public float Y;\n\n        public Vector2(float x, float y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        public float this[int index]\n        {\n            get\n            {\n                switch (index)\n                {\n                    case 0: return X;\n                    case 1: return Y;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Vector2 index!\");\n                }\n            }\n\n            set\n            {\n                switch (index)\n                {\n                    case 0: X = value; break;\n                    case 1: Y = value; break;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Vector2 index!\");\n                }\n            }\n        }\n\n        public override int GetHashCode()\n        {\n            return X.GetHashCode() ^ (Y.GetHashCode() << 2);\n        }\n\n        public override bool Equals(object other)\n        {\n            if (!(other is Vector2))\n                return false;\n            return Equals((Vector2)other);\n        }\n\n        public bool Equals(Vector2 other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y);\n        }\n\n        public void Normalize()\n        {\n            var length = Length();\n            if (length > kEpsilon)\n            {\n                var invNorm = 1.0f / length;\n                X *= invNorm;\n                Y *= invNorm;\n            }\n            else\n            {\n                X = 0;\n                Y = 0;\n            }\n        }\n\n        public float Length()\n        {\n            return (float)Math.Sqrt(LengthSquared());\n        }\n\n        public float LengthSquared()\n        {\n            return X * X + Y * Y;\n        }\n\n        public static Vector2 Zero => new Vector2();\n\n        public static Vector2 operator +(Vector2 a, Vector2 b)\n        {\n            return new Vector2(a.X + b.X, a.Y + b.Y);\n        }\n\n        public static Vector2 operator -(Vector2 a, Vector2 b)\n        {\n            return new Vector2(a.X - b.X, a.Y - b.Y);\n        }\n\n        public static Vector2 operator *(Vector2 a, Vector2 b)\n        {\n            return new Vector2(a.X * b.X, a.Y * b.Y);\n        }\n\n        public static Vector2 operator /(Vector2 a, Vector2 b)\n        {\n            return new Vector2(a.X / b.X, a.Y / b.Y);\n        }\n\n        public static Vector2 operator -(Vector2 a)\n        {\n            return new Vector2(-a.X, -a.Y);\n        }\n\n        public static Vector2 operator *(Vector2 a, float d)\n        {\n            return new Vector2(a.X * d, a.Y * d);\n        }\n\n        public static Vector2 operator *(float d, Vector2 a)\n        {\n            return new Vector2(a.X * d, a.Y * d);\n        }\n\n        public static Vector2 operator /(Vector2 a, float d)\n        {\n            return new Vector2(a.X / d, a.Y / d);\n        }\n\n        public static bool operator ==(Vector2 lhs, Vector2 rhs)\n        {\n            return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;\n        }\n\n        public static bool operator !=(Vector2 lhs, Vector2 rhs)\n        {\n            return !(lhs == rhs);\n        }\n\n        public static implicit operator Vector3(Vector2 v)\n        {\n            return new Vector3(v.X, v.Y, 0);\n        }\n\n        public static implicit operator Vector4(Vector2 v)\n        {\n            return new Vector4(v.X, v.Y, 0.0F, 0.0F);\n        }\n\n        private const float kEpsilon = 0.00001F;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/Vector3.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct Vector3 : IEquatable<Vector3>\n    {\n        public float X;\n        public float Y;\n        public float Z;\n\n        public Vector3(float x, float y, float z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        public float this[int index]\n        {\n            get\n            {\n                switch (index)\n                {\n                    case 0: return X;\n                    case 1: return Y;\n                    case 2: return Z;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Vector3 index!\");\n                }\n            }\n\n            set\n            {\n                switch (index)\n                {\n                    case 0: X = value; break;\n                    case 1: Y = value; break;\n                    case 2: Z = value; break;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Vector3 index!\");\n                }\n            }\n        }\n\n        public override int GetHashCode()\n        {\n            return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2);\n        }\n\n        public override bool Equals(object other)\n        {\n            if (!(other is Vector3))\n                return false;\n            return Equals((Vector3)other);\n        }\n\n        public bool Equals(Vector3 other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n        }\n\n        public void Normalize()\n        {\n            var length = Length();\n            if (length > kEpsilon)\n            {\n                var invNorm = 1.0f / length;\n                X *= invNorm;\n                Y *= invNorm;\n                Z *= invNorm;\n            }\n            else\n            {\n                X = 0;\n                Y = 0;\n                Z = 0;\n            }\n        }\n\n        public float Length()\n        {\n            return (float)Math.Sqrt(LengthSquared());\n        }\n\n        public float LengthSquared()\n        {\n            return X * X + Y * Y + Z * Z;\n        }\n\n        public static Vector3 Zero => new Vector3();\n\n        public static Vector3 One => new Vector3(1.0f, 1.0f, 1.0f);\n\n        public static Vector3 operator +(Vector3 a, Vector3 b)\n        {\n            return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n        }\n\n        public static Vector3 operator -(Vector3 a, Vector3 b)\n        {\n            return new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n        }\n\n        public static Vector3 operator -(Vector3 a)\n        {\n            return new Vector3(-a.X, -a.Y, -a.Z);\n        }\n\n        public static Vector3 operator *(Vector3 a, float d)\n        {\n            return new Vector3(a.X * d, a.Y * d, a.Z * d);\n        }\n\n        public static Vector3 operator *(float d, Vector3 a)\n        {\n            return new Vector3(a.X * d, a.Y * d, a.Z * d);\n        }\n\n        public static Vector3 operator /(Vector3 a, float d)\n        {\n            return new Vector3(a.X / d, a.Y / d, a.Z / d);\n        }\n\n        public static bool operator ==(Vector3 lhs, Vector3 rhs)\n        {\n            return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;\n        }\n\n        public static bool operator !=(Vector3 lhs, Vector3 rhs)\n        {\n            return !(lhs == rhs);\n        }\n\n        public static implicit operator Vector2(Vector3 v)\n        {\n            return new Vector2(v.X, v.Y);\n        }\n\n        public static implicit operator Vector4(Vector3 v)\n        {\n            return new Vector4(v.X, v.Y, v.Z, 0.0F);\n        }\n\n        private const float kEpsilon = 0.00001F;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Math/Vector4.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    [StructLayout(LayoutKind.Sequential, Pack = 4)]\n    public struct Vector4 : IEquatable<Vector4>\n    {\n        public float X;\n        public float Y;\n        public float Z;\n        public float W;\n\n        public Vector4(float x, float y, float z, float w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        public Vector4(Vector3 value, float w)\n        {\n            X = value.X;\n            Y = value.Y;\n            Z = value.Z;\n            W = w;\n        }\n\n        public float this[int index]\n        {\n            get\n            {\n                switch (index)\n                {\n                    case 0: return X;\n                    case 1: return Y;\n                    case 2: return Z;\n                    case 3: return W;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Vector4 index!\");\n                }\n            }\n\n            set\n            {\n                switch (index)\n                {\n                    case 0: X = value; break;\n                    case 1: Y = value; break;\n                    case 2: Z = value; break;\n                    case 3: W = value; break;\n                    default: throw new ArgumentOutOfRangeException(nameof(index), \"Invalid Vector4 index!\");\n                }\n            }\n        }\n\n        public override int GetHashCode()\n        {\n            return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);\n        }\n\n        public override bool Equals(object other)\n        {\n            if (!(other is Vector4))\n                return false;\n            return Equals((Vector4)other);\n        }\n\n        public bool Equals(Vector4 other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);\n        }\n\n        public void Normalize()\n        {\n            var length = Length();\n            if (length > kEpsilon)\n            {\n                var invNorm = 1.0f / length;\n                X *= invNorm;\n                Y *= invNorm;\n                Z *= invNorm;\n                W *= invNorm;\n            }\n            else\n            {\n                X = 0;\n                Y = 0;\n                Z = 0;\n                W = 0;\n            }\n        }\n\n        public float Length()\n        {\n            return (float)Math.Sqrt(LengthSquared());\n        }\n\n        public float LengthSquared()\n        {\n            return X * X + Y * Y + Z * Z + W * W;\n        }\n\n        public static Vector4 Zero => new Vector4();\n\n        public static Vector4 operator +(Vector4 a, Vector4 b)\n        {\n            return new Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);\n        }\n\n        public static Vector4 operator -(Vector4 a, Vector4 b)\n        {\n            return new Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);\n        }\n\n        public static Vector4 operator -(Vector4 a)\n        {\n            return new Vector4(-a.X, -a.Y, -a.Z, -a.W);\n        }\n\n        public static Vector4 operator *(Vector4 a, float d)\n        {\n            return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);\n        }\n\n        public static Vector4 operator *(float d, Vector4 a)\n        {\n            return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);\n        }\n\n        public static Vector4 operator /(Vector4 a, float d)\n        {\n            return new Vector4(a.X / d, a.Y / d, a.Z / d, a.W / d);\n        }\n\n        public static bool operator ==(Vector4 lhs, Vector4 rhs)\n        {\n            return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;\n        }\n\n        public static bool operator !=(Vector4 lhs, Vector4 rhs)\n        {\n            return !(lhs == rhs);\n        }\n\n        public static implicit operator Vector2(Vector4 v)\n        {\n            return new Vector2(v.X, v.Y);\n        }\n\n        public static implicit operator Vector3(Vector4 v)\n        {\n            return new Vector3(v.X, v.Y, v.Z);\n        }\n\n        public static implicit operator Color(Vector4 v)\n        {\n            return new Color(v.X, v.Y, v.Z, v.W);\n        }\n\n        private const float kEpsilon = 0.00001F;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/ObjectInfo.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class ObjectInfo\n    {\n        public long byteStart;\n        public uint byteSize;\n        public int typeID;\n        public int classID;\n        public ushort isDestroyed;\n        public byte stripped;\n\n        public long m_PathID;\n        public SerializedType serializedType;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/ObjectReader.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class ObjectReader : EndianBinaryReader\n    {\n        public SerializedFile assetsFile;\n        public long m_PathID;\n        public long byteStart;\n        public uint byteSize;\n        public ClassIDType type;\n        public SerializedType serializedType;\n        public BuildTarget platform;\n        public SerializedFileFormatVersion m_Version;\n\n        public int[] version => assetsFile.version;\n        public BuildType buildType => assetsFile.buildType;\n\n        public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian)\n        {\n            this.assetsFile = assetsFile;\n            m_PathID = objectInfo.m_PathID;\n            byteStart = objectInfo.byteStart;\n            byteSize = objectInfo.byteSize;\n            if (Enum.IsDefined(typeof(ClassIDType), objectInfo.classID))\n            {\n                type = (ClassIDType)objectInfo.classID;\n            }\n            else\n            {\n                type = ClassIDType.UnknownType;\n            }\n            serializedType = objectInfo.serializedType;\n            platform = assetsFile.m_TargetPlatform;\n            m_Version = assetsFile.header.m_Version;\n        }\n\n        public void Reset()\n        {\n            Position = byteStart;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/Progress.cs",
    "content": "﻿using System;\n\nnamespace AssetStudio\n{\n    public static class Progress\n    {\n        public static IProgress<int> Default = new Progress<int>();\n        private static int preValue;\n\n        public static void Reset()\n        {\n            preValue = 0;\n            Default.Report(0);\n        }\n\n        public static void Report(int current, int total)\n        {\n            var value = (int)(current * 100f / total);\n            Report(value);\n        }\n\n        private static void Report(int value)\n        {\n            if (value > preValue)\n            {\n                preValue = value;\n                Default.Report(value);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/ResourceReader.cs",
    "content": "﻿using System.IO;\n\nnamespace AssetStudio\n{\n    public class ResourceReader\n    {\n        private bool needSearch;\n        private string path;\n        private SerializedFile assetsFile;\n        private long offset;\n        private long size;\n        private BinaryReader reader;\n\n        public int Size { get => (int)size; }\n\n        public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)\n        {\n            needSearch = true;\n            this.path = path;\n            this.assetsFile = assetsFile;\n            this.offset = offset;\n            this.size = size;\n        }\n\n        public ResourceReader(BinaryReader reader, long offset, long size)\n        {\n            this.reader = reader;\n            this.offset = offset;\n            this.size = size;\n        }\n\n        private BinaryReader GetReader()\n        {\n            if (needSearch)\n            {\n                var resourceFileName = Path.GetFileName(path);\n                if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))\n                {\n                    needSearch = false;\n                    return reader;\n                }\n                var assetsFileDirectory = Path.GetDirectoryName(assetsFile.fullName);\n                var resourceFilePath = Path.Combine(assetsFileDirectory, resourceFileName);\n                if (!File.Exists(resourceFilePath))\n                {\n                    var findFiles = Directory.GetFiles(assetsFileDirectory, resourceFileName, SearchOption.AllDirectories);\n                    if (findFiles.Length > 0)\n                    {\n                        resourceFilePath = findFiles[0];\n                    }\n                }\n                if (File.Exists(resourceFilePath))\n                {\n                    needSearch = false;\n                    reader = new BinaryReader(File.OpenRead(resourceFilePath));\n                    assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);\n                    return reader;\n                }\n                throw new FileNotFoundException($\"Can't find the resource file {resourceFileName}\");\n            }\n            else\n            {\n                return reader;\n            }\n        }\n\n        public byte[] GetData()\n        {\n            var binaryReader = GetReader();\n            binaryReader.BaseStream.Position = offset;\n            return binaryReader.ReadBytes((int)size);\n        }\n\n        public void GetData(byte[] buff)\n        {\n            var binaryReader = GetReader();\n            binaryReader.BaseStream.Position = offset;\n            binaryReader.Read(buff, 0, (int)size);\n        }\n\n        public void WriteData(string path)\n        {\n            var binaryReader = GetReader();\n            binaryReader.BaseStream.Position = offset;\n            using (var writer = File.OpenWrite(path))\n            {\n                binaryReader.BaseStream.CopyTo(writer, size);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/SerializedFile.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text.RegularExpressions;\n\nnamespace AssetStudio\n{\n    public class SerializedFile\n    {\n        public AssetsManager assetsManager;\n        public FileReader reader;\n        public string fullName;\n        public string originalPath;\n        public string fileName;\n        public int[] version = { 0, 0, 0, 0 };\n        public BuildType buildType;\n        public List<Object> Objects;\n        public Dictionary<long, Object> ObjectsDic;\n\n        public SerializedFileHeader header;\n        private byte m_FileEndianess;\n        public string unityVersion = \"2.5.0f5\";\n        public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;\n        private bool m_EnableTypeTree = true;\n        public List<SerializedType> m_Types;\n        public int bigIDEnabled = 0;\n        public List<ObjectInfo> m_Objects;\n        private List<LocalSerializedObjectIdentifier> m_ScriptTypes;\n        public List<FileIdentifier> m_Externals;\n        public List<SerializedType> m_RefTypes;\n        public string userInformation;\n\n        public SerializedFile(FileReader reader, AssetsManager assetsManager)\n        {\n            this.assetsManager = assetsManager;\n            this.reader = reader;\n            fullName = reader.FullPath;\n            fileName = reader.FileName;\n\n            // ReadHeader\n            header = new SerializedFileHeader();\n            header.m_MetadataSize = reader.ReadUInt32();\n            header.m_FileSize = reader.ReadUInt32();\n            header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32();\n            header.m_DataOffset = reader.ReadUInt32();\n\n            if (header.m_Version >= SerializedFileFormatVersion.Unknown_9)\n            {\n                header.m_Endianess = reader.ReadByte();\n                header.m_Reserved = reader.ReadBytes(3);\n                m_FileEndianess = header.m_Endianess;\n            }\n            else\n            {\n                reader.Position = header.m_FileSize - header.m_MetadataSize;\n                m_FileEndianess = reader.ReadByte();\n            }\n\n            if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)\n            {\n                header.m_MetadataSize = reader.ReadUInt32();\n                header.m_FileSize = reader.ReadInt64();\n                header.m_DataOffset = reader.ReadInt64();\n                reader.ReadInt64(); // unknown\n            }\n\n            // ReadMetadata\n            if (m_FileEndianess == 0)\n            {\n                reader.Endian = EndianType.LittleEndian;\n            }\n            if (header.m_Version >= SerializedFileFormatVersion.Unknown_7)\n            {\n                unityVersion = reader.ReadStringToNull();\n                SetVersion(unityVersion);\n            }\n            if (header.m_Version >= SerializedFileFormatVersion.Unknown_8)\n            {\n                m_TargetPlatform = (BuildTarget)reader.ReadInt32();\n                if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))\n                {\n                    m_TargetPlatform = BuildTarget.UnknownPlatform;\n                }\n            }\n            if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)\n            {\n                m_EnableTypeTree = reader.ReadBoolean();\n            }\n\n            // Read Types\n            int typeCount = reader.ReadInt32();\n            m_Types = new List<SerializedType>(typeCount);\n            for (int i = 0; i < typeCount; i++)\n            {\n                m_Types.Add(ReadSerializedType(false));\n            }\n\n            if (header.m_Version >= SerializedFileFormatVersion.Unknown_7 && header.m_Version < SerializedFileFormatVersion.Unknown_14)\n            {\n                bigIDEnabled = reader.ReadInt32();\n            }\n\n            // Read Objects\n            int objectCount = reader.ReadInt32();\n            m_Objects = new List<ObjectInfo>(objectCount);\n            Objects = new List<Object>(objectCount);\n            ObjectsDic = new Dictionary<long, Object>(objectCount);\n            for (int i = 0; i < objectCount; i++)\n            {\n                var objectInfo = new ObjectInfo();\n                if (bigIDEnabled != 0)\n                {\n                    objectInfo.m_PathID = reader.ReadInt64();\n                }\n                else if (header.m_Version < SerializedFileFormatVersion.Unknown_14)\n                {\n                    objectInfo.m_PathID = reader.ReadInt32();\n                }\n                else\n                {\n                    reader.AlignStream();\n                    objectInfo.m_PathID = reader.ReadInt64();\n                }\n\n                if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)\n                    objectInfo.byteStart = reader.ReadInt64();\n                else\n                    objectInfo.byteStart = reader.ReadUInt32();\n\n                objectInfo.byteStart += header.m_DataOffset;\n                objectInfo.byteSize = reader.ReadUInt32();\n                objectInfo.typeID = reader.ReadInt32();\n                if (header.m_Version < SerializedFileFormatVersion.RefactoredClassId)\n                {\n                    objectInfo.classID = reader.ReadUInt16();\n                    objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);\n                }\n                else\n                {\n                    var type = m_Types[objectInfo.typeID];\n                    objectInfo.serializedType = type;\n                    objectInfo.classID = type.classID;\n                }\n                if (header.m_Version < SerializedFileFormatVersion.HasScriptTypeIndex)\n                {\n                    objectInfo.isDestroyed = reader.ReadUInt16();\n                }\n                if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.RefactorTypeData)\n                {\n                    var m_ScriptTypeIndex = reader.ReadInt16();\n                    if (objectInfo.serializedType != null)\n                        objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;\n                }\n                if (header.m_Version == SerializedFileFormatVersion.SupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.RefactoredClassId)\n                {\n                    objectInfo.stripped = reader.ReadByte();\n                }\n                m_Objects.Add(objectInfo);\n            }\n\n            if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex)\n            {\n                int scriptCount = reader.ReadInt32();\n                m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);\n                for (int i = 0; i < scriptCount; i++)\n                {\n                    var m_ScriptType = new LocalSerializedObjectIdentifier();\n                    m_ScriptType.localSerializedFileIndex = reader.ReadInt32();\n                    if (header.m_Version < SerializedFileFormatVersion.Unknown_14)\n                    {\n                        m_ScriptType.localIdentifierInFile = reader.ReadInt32();\n                    }\n                    else\n                    {\n                        reader.AlignStream();\n                        m_ScriptType.localIdentifierInFile = reader.ReadInt64();\n                    }\n                    m_ScriptTypes.Add(m_ScriptType);\n                }\n            }\n\n            int externalsCount = reader.ReadInt32();\n            m_Externals = new List<FileIdentifier>(externalsCount);\n            for (int i = 0; i < externalsCount; i++)\n            {\n                var m_External = new FileIdentifier();\n                if (header.m_Version >= SerializedFileFormatVersion.Unknown_6)\n                {\n                    var tempEmpty = reader.ReadStringToNull();\n                }\n                if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)\n                {\n                    m_External.guid = new Guid(reader.ReadBytes(16));\n                    m_External.type = reader.ReadInt32();\n                }\n                m_External.pathName = reader.ReadStringToNull();\n                m_External.fileName = Path.GetFileName(m_External.pathName);\n                m_Externals.Add(m_External);\n            }\n\n            if (header.m_Version >= SerializedFileFormatVersion.SupportsRefObject)\n            {\n                int refTypesCount = reader.ReadInt32();\n                m_RefTypes = new List<SerializedType>(refTypesCount);\n                for (int i = 0; i < refTypesCount; i++)\n                {\n                    m_RefTypes.Add(ReadSerializedType(true));\n                }\n            }\n\n            if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)\n            {\n                userInformation = reader.ReadStringToNull();\n            }\n\n            //reader.AlignStream(16);\n        }\n\n        public void SetVersion(string stringVersion)\n        {\n            if (stringVersion != strippedVersion)\n            {\n                unityVersion = stringVersion;\n                var buildSplit = Regex.Replace(stringVersion, @\"\\d\", \"\").Split(new[] { \".\" }, StringSplitOptions.RemoveEmptyEntries);\n                buildType = new BuildType(buildSplit[0]);\n                var versionSplit = Regex.Replace(stringVersion, @\"\\D\", \".\").Split(new[] { \".\" }, StringSplitOptions.RemoveEmptyEntries);\n                version = versionSplit.Select(int.Parse).ToArray();\n            }\n        }\n\n        private SerializedType ReadSerializedType(bool isRefType)\n        {\n            var type = new SerializedType();\n\n            type.classID = reader.ReadInt32();\n\n            if (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId)\n            {\n                type.m_IsStrippedType = reader.ReadBoolean();\n            }\n\n            if (header.m_Version >= SerializedFileFormatVersion.RefactorTypeData)\n            {\n                type.m_ScriptTypeIndex = reader.ReadInt16();\n            }\n\n            if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)\n            {\n                if (isRefType && type.m_ScriptTypeIndex >= 0)\n                {\n                    type.m_ScriptID = reader.ReadBytes(16);\n                }\n                else if ((header.m_Version < SerializedFileFormatVersion.RefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId && type.classID == 114))\n                {\n                    type.m_ScriptID = reader.ReadBytes(16);\n                }\n                type.m_OldTypeHash = reader.ReadBytes(16);\n            }\n\n            if (m_EnableTypeTree)\n            {\n                type.m_Type = new TypeTree();\n                type.m_Type.m_Nodes = new List<TypeTreeNode>();\n                if (header.m_Version >= SerializedFileFormatVersion.Unknown_12 || header.m_Version == SerializedFileFormatVersion.Unknown_10)\n                {\n                    TypeTreeBlobRead(type.m_Type);\n                }\n                else\n                {\n                    ReadTypeTree(type.m_Type);\n                }\n                if (header.m_Version >= SerializedFileFormatVersion.StoresTypeDependencies)\n                {\n                    if (isRefType)\n                    {\n                        type.m_KlassName = reader.ReadStringToNull();\n                        type.m_NameSpace = reader.ReadStringToNull();\n                        type.m_AsmName = reader.ReadStringToNull();\n                    }\n                    else\n                    {\n                        type.m_TypeDependencies = reader.ReadInt32Array();\n                    }\n                }\n            }\n\n            return type;\n        }\n\n        private void ReadTypeTree(TypeTree m_Type, int level = 0)\n        {\n            var typeTreeNode = new TypeTreeNode();\n            m_Type.m_Nodes.Add(typeTreeNode);\n            typeTreeNode.m_Level = level;\n            typeTreeNode.m_Type = reader.ReadStringToNull();\n            typeTreeNode.m_Name = reader.ReadStringToNull();\n            typeTreeNode.m_ByteSize = reader.ReadInt32();\n            if (header.m_Version == SerializedFileFormatVersion.Unknown_2)\n            {\n                var variableCount = reader.ReadInt32();\n            }\n            if (header.m_Version != SerializedFileFormatVersion.Unknown_3)\n            {\n                typeTreeNode.m_Index = reader.ReadInt32();\n            }\n            typeTreeNode.m_TypeFlags = reader.ReadInt32();\n            typeTreeNode.m_Version = reader.ReadInt32();\n            if (header.m_Version != SerializedFileFormatVersion.Unknown_3)\n            {\n                typeTreeNode.m_MetaFlag = reader.ReadInt32();\n            }\n\n            int childrenCount = reader.ReadInt32();\n            for (int i = 0; i < childrenCount; i++)\n            {\n                ReadTypeTree(m_Type, level + 1);\n            }\n        }\n\n        private void TypeTreeBlobRead(TypeTree m_Type)\n        {\n            int numberOfNodes = reader.ReadInt32();\n            int stringBufferSize = reader.ReadInt32();\n            for (int i = 0; i < numberOfNodes; i++)\n            {\n                var typeTreeNode = new TypeTreeNode();\n                m_Type.m_Nodes.Add(typeTreeNode);\n                typeTreeNode.m_Version = reader.ReadUInt16();\n                typeTreeNode.m_Level = reader.ReadByte();\n                typeTreeNode.m_TypeFlags = reader.ReadByte();\n                typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();\n                typeTreeNode.m_NameStrOffset = reader.ReadUInt32();\n                typeTreeNode.m_ByteSize = reader.ReadInt32();\n                typeTreeNode.m_Index = reader.ReadInt32();\n                typeTreeNode.m_MetaFlag = reader.ReadInt32();\n                if (header.m_Version >= SerializedFileFormatVersion.TypeTreeNodeWithTypeFlags)\n                {\n                    typeTreeNode.m_RefTypeHash = reader.ReadUInt64();\n                }\n            }\n            m_Type.m_StringBuffer = reader.ReadBytes(stringBufferSize);\n\n            using (var stringBufferReader = new BinaryReader(new MemoryStream(m_Type.m_StringBuffer)))\n            {\n                for (int i = 0; i < numberOfNodes; i++)\n                {\n                    var m_Node = m_Type.m_Nodes[i];\n                    m_Node.m_Type = ReadString(stringBufferReader, m_Node.m_TypeStrOffset);\n                    m_Node.m_Name = ReadString(stringBufferReader, m_Node.m_NameStrOffset);\n                }\n            }\n\n            string ReadString(BinaryReader stringBufferReader, uint value)\n            {\n                var isOffset = (value & 0x80000000) == 0;\n                if (isOffset)\n                {\n                    stringBufferReader.BaseStream.Position = value;\n                    return stringBufferReader.ReadStringToNull();\n                }\n                var offset = value & 0x7FFFFFFF;\n                if (CommonString.StringBuffer.TryGetValue(offset, out var str))\n                {\n                    return str;\n                }\n                return offset.ToString();\n            }\n        }\n\n        public void AddObject(Object obj)\n        {\n            Objects.Add(obj);\n            ObjectsDic.Add(obj.m_PathID, obj);\n        }\n\n        public bool IsVersionStripped => unityVersion == strippedVersion;\n\n        private const string strippedVersion = \"0.0.0\";\n    }\n}\n"
  },
  {
    "path": "AssetStudio/SerializedFileFormatVersion.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace AssetStudio\n{\n    public enum SerializedFileFormatVersion\n    {\n        Unsupported = 1,\n        Unknown_2 = 2,\n        Unknown_3 = 3,\n        /// <summary>\n        /// 1.2.0 to 2.0.0\n        /// </summary>\n        Unknown_5 = 5,\n        /// <summary>\n        /// 2.1.0 to 2.6.1\n        /// </summary>\n        Unknown_6 = 6,\n        /// <summary>\n        /// 3.0.0b\n        /// </summary>\n        Unknown_7 = 7,\n        /// <summary>\n        /// 3.0.0 to 3.4.2\n        /// </summary>\n        Unknown_8 = 8,\n        /// <summary>\n        /// 3.5.0 to 4.7.2\n        /// </summary>\n        Unknown_9 = 9,\n        /// <summary>\n        /// 5.0.0aunk1\n        /// </summary>\n        Unknown_10 = 10,\n        /// <summary>\n        /// 5.0.0aunk2\n        /// </summary>\n        HasScriptTypeIndex = 11,\n        /// <summary>\n        /// 5.0.0aunk3\n        /// </summary>\n        Unknown_12 = 12,\n        /// <summary>\n        /// 5.0.0aunk4\n        /// </summary>\n        HasTypeTreeHashes = 13,\n        /// <summary>\n        /// 5.0.0unk\n        /// </summary>\n        Unknown_14 = 14,\n        /// <summary>\n        /// 5.0.1 to 5.4.0\n        /// </summary>\n        SupportsStrippedObject = 15,\n        /// <summary>\n        /// 5.5.0a\n        /// </summary>\n        RefactoredClassId = 16,\n        /// <summary>\n        /// 5.5.0unk to 2018.4\n        /// </summary>\n        RefactorTypeData = 17,\n        /// <summary>\n        /// 2019.1a\n        /// </summary>\n        RefactorShareableTypeTreeData = 18,\n        /// <summary>\n        /// 2019.1unk\n        /// </summary>\n        TypeTreeNodeWithTypeFlags = 19,\n        /// <summary>\n        /// 2019.2\n        /// </summary>\n        SupportsRefObject = 20,\n        /// <summary>\n        /// 2019.3 to 2019.4\n        /// </summary>\n        StoresTypeDependencies = 21,\n        /// <summary>\n        /// 2020.1 to x\n        /// </summary>\n        LargeFilesSupport = 22\n    }\n}\n"
  },
  {
    "path": "AssetStudio/SerializedFileHeader.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class SerializedFileHeader\n    {\n        public uint m_MetadataSize;\n        public long m_FileSize;\n        public SerializedFileFormatVersion m_Version;\n        public long m_DataOffset;\n        public byte m_Endianess;\n        public byte[] m_Reserved;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/SerializedType.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class SerializedType\n    {\n        public int classID;\n        public bool m_IsStrippedType;\n        public short m_ScriptTypeIndex = -1;\n        public TypeTree m_Type;\n        public byte[] m_ScriptID; //Hash128\n        public byte[] m_OldTypeHash; //Hash128\n        public int[] m_TypeDependencies;\n        public string m_KlassName;\n        public string m_NameSpace;\n        public string m_AsmName;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/SevenZipHelper.cs",
    "content": "using System;\nusing System.IO;\nusing SevenZip.Compression.LZMA;\n\n\nnamespace AssetStudio\n{\n    public static class SevenZipHelper\n    {\n        public static MemoryStream StreamDecompress(MemoryStream inStream)\n        {\n            var decoder = new Decoder();\n\n            inStream.Seek(0, SeekOrigin.Begin);\n            var newOutStream = new MemoryStream();\n\n            var properties = new byte[5];\n            if (inStream.Read(properties, 0, 5) != 5)\n                throw new Exception(\"input .lzma is too short\");\n            long outSize = 0;\n            for (var i = 0; i < 8; i++)\n            {\n                var v = inStream.ReadByte();\n                if (v < 0)\n                    throw new Exception(\"Can't Read 1\");\n                outSize |= ((long)(byte)v) << (8 * i);\n            }\n            decoder.SetDecoderProperties(properties);\n\n            var compressedSize = inStream.Length - inStream.Position;\n            decoder.Code(inStream, newOutStream, compressedSize, outSize, null);\n\n            newOutStream.Position = 0;\n            return newOutStream;\n        }\n\n        public static void StreamDecompress(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize)\n        {\n            var basePosition = compressedStream.Position;\n            var decoder = new Decoder();\n            var properties = new byte[5];\n            if (compressedStream.Read(properties, 0, 5) != 5)\n                throw new Exception(\"input .lzma is too short\");\n            decoder.SetDecoderProperties(properties);\n            decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null);\n            compressedStream.Position = basePosition + compressedSize;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/StreamFile.cs",
    "content": "﻿using System.IO;\n\nnamespace AssetStudio\n{\n    public class StreamFile\n    {\n        public string path;\n        public string fileName;\n        public Stream stream;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/TypeTree.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace AssetStudio\n{\n    public class TypeTree\n    {\n        public List<TypeTreeNode> m_Nodes;\n        public byte[] m_StringBuffer;\n    }\n}\n"
  },
  {
    "path": "AssetStudio/TypeTreeHelper.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Collections.Specialized;\nusing System.IO;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public static class TypeTreeHelper\n    {\n        public static string ReadTypeString(TypeTree m_Type, ObjectReader reader)\n        {\n            reader.Reset();\n            var sb = new StringBuilder();\n            var m_Nodes = m_Type.m_Nodes;\n            for (int i = 0; i < m_Nodes.Count; i++)\n            {\n                ReadStringValue(sb, m_Nodes, reader, ref i);\n            }\n            var readed = reader.Position - reader.byteStart;\n            if (readed != reader.byteSize)\n            {\n                Logger.Info($\"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes\");\n            }\n            return sb.ToString();\n        }\n\n        private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> m_Nodes, BinaryReader reader, ref int i)\n        {\n            var m_Node = m_Nodes[i];\n            var level = m_Node.m_Level;\n            var varTypeStr = m_Node.m_Type;\n            var varNameStr = m_Node.m_Name;\n            object value = null;\n            var append = true;\n            var align = (m_Node.m_MetaFlag & 0x4000) != 0;\n            switch (varTypeStr)\n            {\n                case \"SInt8\":\n                    value = reader.ReadSByte();\n                    break;\n                case \"UInt8\":\n                    value = reader.ReadByte();\n                    break;\n                case \"char\":\n                    value = BitConverter.ToChar(reader.ReadBytes(2), 0);\n                    break;\n                case \"short\":\n                case \"SInt16\":\n                    value = reader.ReadInt16();\n                    break;\n                case \"UInt16\":\n                case \"unsigned short\":\n                    value = reader.ReadUInt16();\n                    break;\n                case \"int\":\n                case \"SInt32\":\n                    value = reader.ReadInt32();\n                    break;\n                case \"UInt32\":\n                case \"unsigned int\":\n                case \"Type*\":\n                    value = reader.ReadUInt32();\n                    break;\n                case \"long long\":\n                case \"SInt64\":\n                    value = reader.ReadInt64();\n                    break;\n                case \"UInt64\":\n                case \"unsigned long long\":\n                case \"FileSize\":\n                    value = reader.ReadUInt64();\n                    break;\n                case \"float\":\n                    value = reader.ReadSingle();\n                    break;\n                case \"double\":\n                    value = reader.ReadDouble();\n                    break;\n                case \"bool\":\n                    value = reader.ReadBoolean();\n                    break;\n                case \"string\":\n                    append = false;\n                    var str = reader.ReadAlignedString();\n                    sb.AppendFormat(\"{0}{1} {2} = \\\"{3}\\\"\\r\\n\", (new string('\\t', level)), varTypeStr, varNameStr, str);\n                    var toSkip = GetNodes(m_Nodes, i);\n                    i += toSkip.Count - 1;\n                    break;\n                case \"map\":\n                    {\n                        if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)\n                            align = true;\n                        append = false;\n                        sb.AppendFormat(\"{0}{1} {2}\\r\\n\", (new string('\\t', level)), varTypeStr, varNameStr);\n                        sb.AppendFormat(\"{0}{1} {2}\\r\\n\", (new string('\\t', level + 1)), \"Array\", \"Array\");\n                        var size = reader.ReadInt32();\n                        sb.AppendFormat(\"{0}{1} {2} = {3}\\r\\n\", (new string('\\t', level + 1)), \"int\", \"size\", size);\n                        var map = GetNodes(m_Nodes, i);\n                        i += map.Count - 1;\n                        var first = GetNodes(map, 4);\n                        var next = 4 + first.Count;\n                        var second = GetNodes(map, next);\n                        for (int j = 0; j < size; j++)\n                        {\n                            sb.AppendFormat(\"{0}[{1}]\\r\\n\", (new string('\\t', level + 2)), j);\n                            sb.AppendFormat(\"{0}{1} {2}\\r\\n\", (new string('\\t', level + 2)), \"pair\", \"data\");\n                            int tmp1 = 0;\n                            int tmp2 = 0;\n                            ReadStringValue(sb, first, reader, ref tmp1);\n                            ReadStringValue(sb, second, reader, ref tmp2);\n                        }\n                        break;\n                    }\n                case \"TypelessData\":\n                    {\n                        append = false;\n                        var size = reader.ReadInt32();\n                        reader.ReadBytes(size);\n                        i += 2;\n                        sb.AppendFormat(\"{0}{1} {2}\\r\\n\", (new string('\\t', level)), varTypeStr, varNameStr);\n                        sb.AppendFormat(\"{0}{1} {2} = {3}\\r\\n\", (new string('\\t', level)), \"int\", \"size\", size);\n                        break;\n                    }\n                default:\n                    {\n                        if (i < m_Nodes.Count - 1 && m_Nodes[i + 1].m_Type == \"Array\") //Array\n                        {\n                            if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)\n                                align = true;\n                            append = false;\n                            sb.AppendFormat(\"{0}{1} {2}\\r\\n\", (new string('\\t', level)), varTypeStr, varNameStr);\n                            sb.AppendFormat(\"{0}{1} {2}\\r\\n\", (new string('\\t', level + 1)), \"Array\", \"Array\");\n                            var size = reader.ReadInt32();\n                            sb.AppendFormat(\"{0}{1} {2} = {3}\\r\\n\", (new string('\\t', level + 1)), \"int\", \"size\", size);\n                            var vector = GetNodes(m_Nodes, i);\n                            i += vector.Count - 1;\n                            for (int j = 0; j < size; j++)\n                            {\n                                sb.AppendFormat(\"{0}[{1}]\\r\\n\", (new string('\\t', level + 2)), j);\n                                int tmp = 3;\n                                ReadStringValue(sb, vector, reader, ref tmp);\n                            }\n                            break;\n                        }\n                        else //Class\n                        {\n                            append = false;\n                            sb.AppendFormat(\"{0}{1} {2}\\r\\n\", (new string('\\t', level)), varTypeStr, varNameStr);\n                            var @class = GetNodes(m_Nodes, i);\n                            i += @class.Count - 1;\n                            for (int j = 1; j < @class.Count; j++)\n                            {\n                                ReadStringValue(sb, @class, reader, ref j);\n                            }\n                            break;\n                        }\n                    }\n            }\n            if (append)\n                sb.AppendFormat(\"{0}{1} {2} = {3}\\r\\n\", (new string('\\t', level)), varTypeStr, varNameStr, value);\n            if (align)\n                reader.AlignStream();\n        }\n\n        public static OrderedDictionary ReadType(TypeTree m_Types, ObjectReader reader)\n        {\n            reader.Reset();\n            var obj = new OrderedDictionary();\n            var m_Nodes = m_Types.m_Nodes;\n            for (int i = 1; i < m_Nodes.Count; i++)\n            {\n                var m_Node = m_Nodes[i];\n                var varNameStr = m_Node.m_Name;\n                obj[varNameStr] = ReadValue(m_Nodes, reader, ref i);\n            }\n            var readed = reader.Position - reader.byteStart;\n            if (readed != reader.byteSize)\n            {\n                Logger.Info($\"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes\");\n            }\n            return obj;\n        }\n\n        private static object ReadValue(List<TypeTreeNode> m_Nodes, BinaryReader reader, ref int i)\n        {\n            var m_Node = m_Nodes[i];\n            var varTypeStr = m_Node.m_Type;\n            object value;\n            var align = (m_Node.m_MetaFlag & 0x4000) != 0;\n            switch (varTypeStr)\n            {\n                case \"SInt8\":\n                    value = reader.ReadSByte();\n                    break;\n                case \"UInt8\":\n                    value = reader.ReadByte();\n                    break;\n                case \"char\":\n                    value = BitConverter.ToChar(reader.ReadBytes(2), 0);\n                    break;\n                case \"short\":\n                case \"SInt16\":\n                    value = reader.ReadInt16();\n                    break;\n                case \"UInt16\":\n                case \"unsigned short\":\n                    value = reader.ReadUInt16();\n                    break;\n                case \"int\":\n                case \"SInt32\":\n                    value = reader.ReadInt32();\n                    break;\n                case \"UInt32\":\n                case \"unsigned int\":\n                case \"Type*\":\n                    value = reader.ReadUInt32();\n                    break;\n                case \"long long\":\n                case \"SInt64\":\n                    value = reader.ReadInt64();\n                    break;\n                case \"UInt64\":\n                case \"unsigned long long\":\n                case \"FileSize\":\n                    value = reader.ReadUInt64();\n                    break;\n                case \"float\":\n                    value = reader.ReadSingle();\n                    break;\n                case \"double\":\n                    value = reader.ReadDouble();\n                    break;\n                case \"bool\":\n                    value = reader.ReadBoolean();\n                    break;\n                case \"string\":\n                    value = reader.ReadAlignedString();\n                    var toSkip = GetNodes(m_Nodes, i);\n                    i += toSkip.Count - 1;\n                    break;\n                case \"map\":\n                    {\n                        if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)\n                            align = true;\n                        var map = GetNodes(m_Nodes, i);\n                        i += map.Count - 1;\n                        var first = GetNodes(map, 4);\n                        var next = 4 + first.Count;\n                        var second = GetNodes(map, next);\n                        var size = reader.ReadInt32();\n                        var dic = new List<KeyValuePair<object, object>>(size);\n                        for (int j = 0; j < size; j++)\n                        {\n                            int tmp1 = 0;\n                            int tmp2 = 0;\n                            dic.Add(new KeyValuePair<object, object>(ReadValue(first, reader, ref tmp1), ReadValue(second, reader, ref tmp2)));\n                        }\n                        value = dic;\n                        break;\n                    }\n                case \"TypelessData\":\n                    {\n                        var size = reader.ReadInt32();\n                        value = reader.ReadBytes(size);\n                        i += 2;\n                        break;\n                    }\n                default:\n                    {\n                        if (i < m_Nodes.Count - 1 && m_Nodes[i + 1].m_Type == \"Array\") //Array\n                        {\n                            if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)\n                                align = true;\n                            var vector = GetNodes(m_Nodes, i);\n                            i += vector.Count - 1;\n                            var size = reader.ReadInt32();\n                            var list = new List<object>(size);\n                            for (int j = 0; j < size; j++)\n                            {\n                                int tmp = 3;\n                                list.Add(ReadValue(vector, reader, ref tmp));\n                            }\n                            value = list;\n                            break;\n                        }\n                        else //Class\n                        {\n                            var @class = GetNodes(m_Nodes, i);\n                            i += @class.Count - 1;\n                            var obj = new OrderedDictionary();\n                            for (int j = 1; j < @class.Count; j++)\n                            {\n                                var classmember = @class[j];\n                                var name = classmember.m_Name;\n                                obj[name] = ReadValue(@class, reader, ref j);\n                            }\n                            value = obj;\n                            break;\n                        }\n                    }\n            }\n            if (align)\n                reader.AlignStream();\n            return value;\n        }\n\n        private static List<TypeTreeNode> GetNodes(List<TypeTreeNode> m_Nodes, int index)\n        {\n            var nodes = new List<TypeTreeNode>();\n            nodes.Add(m_Nodes[index]);\n            var level = m_Nodes[index].m_Level;\n            for (int i = index + 1; i < m_Nodes.Count; i++)\n            {\n                var member = m_Nodes[i];\n                var level2 = member.m_Level;\n                if (level2 <= level)\n                {\n                    return nodes;\n                }\n                nodes.Add(member);\n            }\n            return nodes;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/TypeTreeNode.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class TypeTreeNode\n    {\n        public string m_Type;\n        public string m_Name;\n        public int m_ByteSize;\n        public int m_Index;\n        public int m_TypeFlags; //m_IsArray\n        public int m_Version;\n        public int m_MetaFlag;\n        public int m_Level;\n        public uint m_TypeStrOffset;\n        public uint m_NameStrOffset;\n        public ulong m_RefTypeHash;\n\n        public TypeTreeNode() { }\n\n        public TypeTreeNode(string type, string name, int level, bool align)\n        {\n            m_Type = type;\n            m_Name = name;\n            m_Level = level;\n            m_MetaFlag = align ? 0x4000 : 0;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio/WebFile.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.IO;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class WebFile\n    {\n        public StreamFile[] fileList;\n\n        private class WebData\n        {\n            public int dataOffset;\n            public int dataLength;\n            public string path;\n        }\n\n        public WebFile(EndianBinaryReader reader)\n        {\n            reader.Endian = EndianType.LittleEndian;\n            var signature = reader.ReadStringToNull();\n            var headLength = reader.ReadInt32();\n            var dataList = new List<WebData>();\n            while (reader.BaseStream.Position < headLength)\n            {\n                var data = new WebData();\n                data.dataOffset = reader.ReadInt32();\n                data.dataLength = reader.ReadInt32();\n                var pathLength = reader.ReadInt32();\n                data.path = Encoding.UTF8.GetString(reader.ReadBytes(pathLength));\n                dataList.Add(data);\n            }\n            fileList = new StreamFile[dataList.Count];\n            for (int i = 0; i < dataList.Count; i++)\n            {\n                var data = dataList[i];\n                var file = new StreamFile();\n                file.path = data.path;\n                file.fileName = Path.GetFileName(data.path);\n                reader.BaseStream.Position = data.dataOffset;\n                file.stream = new MemoryStream(reader.ReadBytes(data.dataLength));\n                fileList[i] = file;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudio.PInvoke/AssetStudio.PInvoke.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <Version>0.16.0.0</Version>\n    <AssemblyVersion>0.16.0.0</AssemblyVersion>\n    <FileVersion>0.16.0.0</FileVersion>\n    <Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>\n    <DebugType>embedded</DebugType>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "AssetStudio.PInvoke/DllLoader.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio.PInvoke\n{\n    public static class DllLoader\n    {\n\n        public static void PreloadDll(string dllName)\n        {\n            var dllDir = GetDirectedDllDirectory();\n\n            // Not using OperatingSystem.Platform.\n            // See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform\n            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))\n            {\n                Win32.LoadDll(dllDir, dllName);\n            }\n            else\n            {\n                Posix.LoadDll(dllDir, dllName);\n            }\n        }\n\n        private static string GetDirectedDllDirectory()\n        {\n            var localPath = Process.GetCurrentProcess().MainModule.FileName;\n            var localDir = Path.GetDirectoryName(localPath);\n\n            var subDir = Environment.Is64BitProcess ? \"x64\" : \"x86\";\n\n            var directedDllDir = Path.Combine(localDir, subDir);\n\n            return directedDllDir;\n        }\n\n        private static class Win32\n        {\n\n            internal static void LoadDll(string dllDir, string dllName)\n            {\n                var dllFileName = $\"{dllName}.dll\";\n                var directedDllPath = Path.Combine(dllDir, dllFileName);\n\n                // Specify SEARCH_DLL_LOAD_DIR to load dependent libraries located in the same platform-specific directory.\n                var hLibrary = LoadLibraryEx(directedDllPath, IntPtr.Zero, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);\n\n                if (hLibrary == IntPtr.Zero)\n                {\n                    var errorCode = Marshal.GetLastWin32Error();\n                    var exception = new Win32Exception(errorCode);\n\n                    throw new DllNotFoundException(exception.Message, exception);\n                }\n            }\n\n            // HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);\n            // HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);\n            [DllImport(\"kernel32.dll\", SetLastError = true)]\n            private static extern IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags);\n\n            private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000;\n            private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100;\n\n        }\n\n        private static class Posix\n        {\n\n            internal static void LoadDll(string dllDir, string dllName)\n            {\n                string dllExtension;\n\n                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))\n                {\n                    dllExtension = \".so\";\n                }\n                else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))\n                {\n                    dllExtension = \".dylib\";\n                }\n                else\n                {\n                    throw new NotSupportedException();\n                }\n\n                var dllFileName = $\"lib{dllName}{dllExtension}\";\n                var directedDllPath = Path.Combine(dllDir, dllFileName);\n\n                const int ldFlags = RTLD_NOW | RTLD_GLOBAL;\n                var hLibrary = DlOpen(directedDllPath, ldFlags);\n\n                if (hLibrary == IntPtr.Zero)\n                {\n                    var pErrStr = DlError();\n                    // `PtrToStringAnsi` always uses the specific constructor of `String` (see dotnet/core#2325),\n                    // which in turn interprets the byte sequence with system default codepage. On OSX and Linux\n                    // the codepage is UTF-8 so the error message should be handled correctly.\n                    var errorMessage = Marshal.PtrToStringAnsi(pErrStr);\n\n                    throw new DllNotFoundException(errorMessage);\n                }\n            }\n\n            // OSX and most Linux OS use LP64 so `int` is still 32-bit even on 64-bit platforms.\n            // void *dlopen(const char *filename, int flag);\n            [DllImport(\"libdl\", EntryPoint = \"dlopen\")]\n            private static extern IntPtr DlOpen([MarshalAs(UnmanagedType.LPStr)] string fileName, int flags);\n\n            // char *dlerror(void);\n            [DllImport(\"libdl\", EntryPoint = \"dlerror\")]\n            private static extern IntPtr DlError();\n\n            private const int RTLD_LAZY = 0x1;\n            private const int RTLD_NOW = 0x2;\n            private const int RTLD_GLOBAL = 0x100;\n\n        }\n\n    }\n}\n"
  },
  {
    "path": "AssetStudio.PInvoke/Utf8StringHandle.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing Microsoft.Win32.SafeHandles;\n\nnamespace AssetStudio.PInvoke\n{\n    // Generally the technique from Steamworks.NET\n    public class Utf8StringHandle : SafeHandleZeroOrMinusOneIsInvalid\n    {\n\n        static Utf8StringHandle()\n        {\n            Utf8 = new UTF8Encoding(false);\n        }\n\n        public Utf8StringHandle(string str)\n            : base(true)\n        {\n            IntPtr buffer;\n\n            if (str == null)\n            {\n                buffer = IntPtr.Zero;\n            }\n            else\n            {\n                if (str.Length == 0)\n                {\n                    buffer = Marshal.AllocHGlobal(1);\n\n                    unsafe\n                    {\n                        *(byte*)buffer = 0;\n                    }\n                }\n                else\n                {\n                    var strlen = Utf8.GetByteCount(str);\n                    var strBuffer = new byte[strlen + 1];\n\n                    Utf8.GetBytes(str, 0, str.Length, strBuffer, 0);\n\n                    buffer = Marshal.AllocHGlobal(strBuffer.Length);\n\n                    Marshal.Copy(strBuffer, 0, buffer, strBuffer.Length);\n                }\n            }\n\n            SetHandle(buffer);\n        }\n\n        public static string ReadUtf8StringFromPointer(IntPtr lpstr)\n        {\n            if (lpstr == IntPtr.Zero || lpstr == new IntPtr(-1))\n            {\n                return null;\n            }\n\n            var byteCount = 0;\n\n            unsafe\n            {\n                var p = (byte*)lpstr.ToPointer();\n\n                while (*p != 0)\n                {\n                    byteCount += 1;\n                    p += 1;\n                }\n            }\n\n            if (byteCount == 0)\n            {\n                return string.Empty;\n            }\n\n            var strBuffer = new byte[byteCount];\n\n            Marshal.Copy(lpstr, strBuffer, 0, byteCount);\n\n            var str = Utf8.GetString(strBuffer);\n\n            return str;\n        }\n\n        protected override bool ReleaseHandle()\n        {\n            if (!IsInvalid)\n            {\n                Marshal.FreeHGlobal(handle);\n            }\n\n            return true;\n        }\n\n        private static readonly UTF8Encoding Utf8;\n\n    }\n}\n"
  },
  {
    "path": "AssetStudio.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.31410.357\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AssetStudio\", \"AssetStudio\\AssetStudio.csproj\", \"{422FEC21-EF60-4F29-AA56-95DFDA23C913}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AssetStudio.PInvoke\", \"AssetStudio.PInvoke\\AssetStudio.PInvoke.csproj\", \"{0B2BE613-3049-4021-85D1-21C325F729F4}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AssetStudioFBXWrapper\", \"AssetStudioFBXWrapper\\AssetStudioFBXWrapper.csproj\", \"{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027} = {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AssetStudioGUI\", \"AssetStudioGUI\\AssetStudioGUI.csproj\", \"{29EAD018-1C67-497A-AB8E-727D595AD756}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AssetStudioUtility\", \"AssetStudioUtility\\AssetStudioUtility.csproj\", \"{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Texture2DDecoderWrapper\", \"Texture2DDecoderWrapper\\Texture2DDecoderWrapper.csproj\", \"{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD}\n\tEndProjectSection\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"AssetStudioFBXNative\", \"AssetStudioFBXNative\\AssetStudioFBXNative.vcxproj\", \"{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Texture2DDecoderNative\", \"Texture2DDecoderNative\\Texture2DDecoderNative.vcxproj\", \"{29356642-C46E-4144-83D8-22DC09D0D7FD}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.Build.0 = Release|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.Build.0 = Release|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.Build.0 = Release|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.Build.0 = Release|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.Build.0 = Release|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.Build.0 = Release|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.Build.0 = Release|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.Build.0 = Release|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.Build.0 = Release|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.Build.0 = Release|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.Build.0 = Release|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.Build.0 = Release|Any CPU\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = Debug|Win32\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.Build.0 = Debug|x64\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.Build.0 = Debug|Win32\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.ActiveCfg = Release|Win32\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.Build.0 = Release|Win32\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.ActiveCfg = Release|x64\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = Release|x64\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.ActiveCfg = Release|Win32\n\t\t{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.ActiveCfg = Debug|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.Build.0 = Debug|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.Build.0 = Debug|x64\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.Build.0 = Debug|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.ActiveCfg = Release|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.Build.0 = Release|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.ActiveCfg = Release|x64\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32\n\t\t{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {3C074481-9CDD-4780-B9F6-57BBC5092EA2}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "AssetStudioFBXNative/AssetStudioFBXNative.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"winres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// Language neutral resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)\nLANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL\n#pragma code_page(65001)\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE \nBEGIN\n    \"#include \"\"winres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION 1,0,0,1\n PRODUCTVERSION 1,0,0,1\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x2L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"000004b0\"\n        BEGIN\n            VALUE \"FileDescription\", \"AssetStudioFBXNative\"\n            VALUE \"FileVersion\", \"1.0.0.1\"\n            VALUE \"InternalName\", \"AssetStudioFBXNative.dll\"\n            VALUE \"LegalCopyright\", \"Copyright (C) Perfare 2018-2020; Copyright (C) hozuki 2020\"\n            VALUE \"OriginalFilename\", \"AssetStudioFBXNative.dll\"\n            VALUE \"ProductName\", \"AssetStudioFBXNative\"\n            VALUE \"ProductVersion\", \"1.0.0.1\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x0, 1200\n    END\nEND\n\n#endif    // Language neutral resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "AssetStudioFBXNative/AssetStudioFBXNative.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>16.0</VCProjectVersion>\n    <Keyword>Win32Proj</Keyword>\n    <ProjectGuid>{11ea25a3-ed68-40ee-a9d0-7fde3b583027}</ProjectGuid>\n    <RootNamespace>AssetStudioFBXNative</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <TargetExt>.dll</TargetExt>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <TargetExt>.dll</TargetExt>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <TargetExt>.dll</TargetExt>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n    <TargetExt>.dll</TargetExt>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\lib\\vs2019\\x86\\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n      <IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\lib\\vs2019\\x86\\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\lib\\vs2019\\x64\\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n      <IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalLibraryDirectories>C:\\Program Files\\Autodesk\\FBX\\FBX SDK\\2020.2.1\\lib\\vs2019\\x64\\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"asfbx_anim_context.cpp\" />\n    <ClCompile Include=\"asfbx_context.cpp\" />\n    <ClCompile Include=\"api.cpp\" />\n    <ClCompile Include=\"asfbx_morph_context.cpp\" />\n    <ClCompile Include=\"asfbx_skin_context.cpp\" />\n    <ClCompile Include=\"utils.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"api.h\" />\n    <ClInclude Include=\"asfbx_anim_context.h\" />\n    <ClInclude Include=\"asfbx_context.h\" />\n    <ClInclude Include=\"asfbx_morph_context.h\" />\n    <ClInclude Include=\"asfbx_skin_context.h\" />\n    <ClInclude Include=\"bool32_t.h\" />\n    <ClInclude Include=\"dllexport.h\" />\n    <ClInclude Include=\"resource.h\" />\n    <ClInclude Include=\"utils.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"cpp.hint\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"AssetStudioFBXNative.rc\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n  <Target Name=\"AfterBuild\">\n    <MSBuild Condition=\" '$(Platform)' == 'Win32' \" Projects=\"$(MSBuildProjectFile)\" Properties=\"Platform=x64;PlatFormTarget=x64\" RunEachTargetSeparately=\"true\" />\n  </Target>\n</Project>"
  },
  {
    "path": "AssetStudioFBXNative/AssetStudioFBXNative.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"源文件\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"头文件\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"资源文件\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"utils.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"api.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"asfbx_context.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"asfbx_skin_context.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"asfbx_anim_context.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"asfbx_morph_context.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"dllexport.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"api.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"bool32_t.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"asfbx_context.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"asfbx_skin_context.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"asfbx_anim_context.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"asfbx_morph_context.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"resource.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"cpp.hint\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"AssetStudioFBXNative.rc\">\n      <Filter>资源文件</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "AssetStudioFBXNative/api.cpp",
    "content": "#include <fbxsdk.h>\n\n#include \"dllexport.h\"\n#include \"bool32_t.h\"\n#include \"asfbx_context.h\"\n#include \"asfbx_skin_context.h\"\n#include \"asfbx_anim_context.h\"\n#include \"asfbx_morph_context.h\"\n#include \"utils.h\"\n\nusing namespace fbxsdk;\n\nAS_API(void) AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, float* vx, float* vy, float* vz)\n{\n\tQuaternion q(qx, qy, qz, qw);\n\n\tauto v = QuaternionToEuler(q);\n\n\tif (vx)\n\t{\n\t\t*vx = v.X;\n\t}\n\n\tif (vy)\n\t{\n\t\t*vy = v.Y;\n\t}\n\n\tif (vz)\n\t{\n\t\t*vz = v.Z;\n\t}\n}\n\nAS_API(void) AsUtilEulerToQuaternion(float vx, float vy, float vz, float* qx, float* qy, float* qz, float* qw)\n{\n\tVector3 v(vx, vy, vz);\n\n\tauto q = EulerToQuaternion(v);\n\n\tif (qx)\n\t{\n\t\t*qx = q.X;\n\t}\n\n\tif (qy)\n\t{\n\t\t*qy = q.Y;\n\t}\n\n\tif (qz)\n\t{\n\t\t*qz = q.Z;\n\t}\n\n\tif (qw)\n\t{\n\t\t*qw = q.W;\n\t}\n}\n\n#define MGR_IOS_REF (*(pSdkManager->GetIOSettings()))\n\nstatic const char* FBXVersion[] =\n{\n\tFBX_2010_00_COMPATIBLE,\n\tFBX_2011_00_COMPATIBLE,\n\tFBX_2012_00_COMPATIBLE,\n\tFBX_2013_00_COMPATIBLE,\n\tFBX_2014_00_COMPATIBLE,\n\tFBX_2016_00_COMPATIBLE\n};\n\nAS_API(AsFbxContext*) AsFbxCreateContext()\n{\n\treturn new AsFbxContext();\n}\n\nAS_API(bool32_t) AsFbxInitializeContext(AsFbxContext* pContext, const char* pFileName, float scaleFactor, int32_t versionIndex, bool32_t isAscii, bool32_t is60Fps, const char** pErrMsg) {\n\tif (pContext == nullptr)\n\t{\n\t\tif (pErrMsg != nullptr)\n\t\t{\n\t\t\t*pErrMsg = \"null pointer for pContext\";\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tauto pSdkManager = FbxManager::Create();\n\tpContext->pSdkManager = pSdkManager;\n\n\tFbxIOSettings* ios = FbxIOSettings::Create(pSdkManager, IOSROOT);\n\tpSdkManager->SetIOSettings(ios);\n\n\tauto pScene = FbxScene::Create(pSdkManager, \"\");\n\tpContext->pScene = pScene;\n\n\tMGR_IOS_REF.SetBoolProp(EXP_FBX_MATERIAL, true);\n\tMGR_IOS_REF.SetBoolProp(EXP_FBX_TEXTURE, true);\n\tMGR_IOS_REF.SetBoolProp(EXP_FBX_EMBEDDED, false);\n\tMGR_IOS_REF.SetBoolProp(EXP_FBX_SHAPE, true);\n\tMGR_IOS_REF.SetBoolProp(EXP_FBX_GOBO, true);\n\tMGR_IOS_REF.SetBoolProp(EXP_FBX_ANIMATION, true);\n\tMGR_IOS_REF.SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true);\n\n\tFbxGlobalSettings& globalSettings = pScene->GetGlobalSettings();\n\tglobalSettings.SetSystemUnit(FbxSystemUnit(scaleFactor));\n\n\tif (is60Fps)\n\t{\n\t\tglobalSettings.SetTimeMode(FbxTime::eFrames60);\n\t}\n\n\tauto pExporter = FbxExporter::Create(pScene, \"\");\n\tpContext->pExporter = pExporter;\n\n\tint pFileFormat = 0;\n\n\tif (versionIndex == 0)\n\t{\n\t\tpFileFormat = 3;\n\n\t\tif (isAscii)\n\t\t{\n\t\t\tpFileFormat = 4;\n\t\t}\n\t}\n\telse\n\t{\n\t\tpExporter->SetFileExportVersion(FBXVersion[versionIndex]);\n\n\t\tif (isAscii)\n\t\t{\n\t\t\tpFileFormat = 1;\n\t\t}\n\t}\n\n\tif (!pExporter->Initialize(pFileName, pFileFormat, pSdkManager->GetIOSettings()))\n\t{\n\t\tif (pErrMsg != nullptr)\n\t\t{\n\t\t\tauto errStr = pExporter->GetStatus().GetErrorString();\n\t\t\t*pErrMsg = errStr;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tauto pBindPose = FbxPose::Create(pScene, \"BindPose\");\n\tpContext->pBindPose = pBindPose;\n\n\tpScene->AddPose(pBindPose);\n\n\treturn true;\n}\n\nAS_API(void) AsFbxDisposeContext(AsFbxContext** ppContext)\n{\n\tif (ppContext == nullptr) {\n\t\treturn;\n\t}\n\n\tdelete (*ppContext);\n\t*ppContext = nullptr;\n}\n\nAS_API(void) AsFbxSetFramePaths(AsFbxContext* pContext, const char* ppPaths[], int32_t count)\n{\n\tif (pContext == nullptr) {\n\t\treturn;\n\t}\n\n\tauto& framePaths = pContext->framePaths;\n\n\tfor (auto i = 0; i < count; i += 1)\n\t{\n\t\tconst char* path = ppPaths[i];\n\t\tframePaths.insert(std::string(path));\n\t}\n}\n\nAS_API(void) AsFbxExportScene(AsFbxContext* pContext)\n{\n\tif (pContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pScene = pContext->pScene;\n\tauto pExporter = pContext->pExporter;\n\n\tif (pExporter != nullptr && pScene != nullptr)\n\t{\n\t\tpExporter->Export(pScene);\n\t}\n}\n\nAS_API(FbxNode*) AsFbxGetSceneRootNode(AsFbxContext* pContext)\n{\n\tif (pContext == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tif (pContext->pScene == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\treturn pContext->pScene->GetRootNode();\n}\n\nAS_API(FbxNode*) AsFbxExportSingleFrame(AsFbxContext* pContext, FbxNode* pParentNode, const char* pFramePath, const char* pFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tconst auto& framePaths = pContext->framePaths;\n\n\tif (!(framePaths.empty() || framePaths.find(pFramePath) != framePaths.end()))\n\t{\n\t\treturn nullptr;\n\t}\n\n\tauto pFrameNode = FbxNode::Create(pContext->pScene, pFrameName);\n\n\tpFrameNode->LclScaling.Set(FbxDouble3(localScaleX, localScaleY, localScaleZ));\n\tpFrameNode->LclRotation.Set(FbxDouble3(localRotationX, localRotationY, localRotationZ));\n\tpFrameNode->LclTranslation.Set(FbxDouble3(localPositionX, localPositionY, localPositionZ));\n\tpFrameNode->SetPreferedAngle(pFrameNode->LclRotation.Get());\n\n\tpParentNode->AddChild(pFrameNode);\n\n\tif (pContext->pBindPose != nullptr)\n\t{\n\t\tpContext->pBindPose->Add(pFrameNode, pFrameNode->EvaluateGlobalTransform());\n\t}\n\n\treturn pFrameNode;\n}\n\nAS_API(void) AsFbxSetJointsNode_CastToBone(AsFbxContext* pContext, FbxNode* pNode, float boneSize)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pNode == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxSkeleton* pJoint = FbxSkeleton::Create(pContext->pScene, \"\");\n\tpJoint->Size.Set(FbxDouble(boneSize));\n\tpJoint->SetSkeletonType(FbxSkeleton::eLimbNode);\n\tpNode->SetNodeAttribute(pJoint);\n}\n\nAS_API(void) AsFbxSetJointsNode_BoneInPath(AsFbxContext* pContext, FbxNode* pNode, float boneSize)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pNode == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxSkeleton* pJoint = FbxSkeleton::Create(pContext->pScene, \"\");\n\tpJoint->Size.Set(FbxDouble(boneSize));\n\tpJoint->SetSkeletonType(FbxSkeleton::eLimbNode);\n\tpNode->SetNodeAttribute(pJoint);\n\n\tpJoint = FbxSkeleton::Create(pContext->pScene, \"\");\n\tpJoint->Size.Set(FbxDouble(boneSize));\n\tpJoint->SetSkeletonType(FbxSkeleton::eLimbNode);\n\tpNode->GetParent()->SetNodeAttribute(pJoint);\n}\n\nAS_API(void) AsFbxSetJointsNode_Generic(AsFbxContext* pContext, FbxNode* pNode)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pNode == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxNull* pNull = FbxNull::Create(pContext->pScene, \"\");\n\n\tif (pNode->GetChildCount() > 0)\n\t{\n\t\tpNull->Look.Set(FbxNull::eNone);\n\t}\n\n\tpNode->SetNodeAttribute(pNull);\n}\n\nAS_API(void) AsFbxPrepareMaterials(AsFbxContext* pContext, int32_t materialCount, int32_t textureCount)\n{\n\tif (pContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpContext->pMaterials = new FbxArray<FbxSurfacePhong*>();\n\tpContext->pTextures = new FbxArray<FbxFileTexture*>();\n\n\tpContext->pMaterials->Reserve(materialCount);\n\tpContext->pTextures->Reserve(textureCount);\n}\n\nAS_API(FbxFileTexture*) AsFbxCreateTexture(AsFbxContext* pContext, const char* pMatTexName)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tauto pTex = FbxFileTexture::Create(pContext->pScene, pMatTexName);\n\tpTex->SetFileName(pMatTexName);\n\tpTex->SetTextureUse(FbxTexture::eStandard);\n\tpTex->SetMappingType(FbxTexture::eUV);\n\tpTex->SetMaterialUse(FbxFileTexture::eModelMaterial);\n\tpTex->SetSwapUV(false);\n\tpTex->SetTranslation(0.0, 0.0);\n\tpTex->SetScale(1.0, 1.0);\n\tpTex->SetRotation(0.0, 0.0);\n\n\tif (pContext->pTextures != nullptr)\n\t{\n\t\tpContext->pTextures->Add(pTex);\n\t}\n\n\treturn pTex;\n}\n\nAS_API(void) AsFbxLinkTexture(int32_t dest, FbxFileTexture* pTexture, FbxSurfacePhong* pMaterial, float offsetX, float offsetY, float scaleX, float scaleY)\n{\n\tif (pTexture == nullptr || pMaterial == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpTexture->SetTranslation(offsetX, offsetY);\n\tpTexture->SetScale(scaleX, scaleY);\n\n\tFbxProperty* pProp;\n\n\tswitch (dest)\n\t{\n\tcase 0:\n\t\tpProp = &pMaterial->Diffuse;\n\t\tbreak;\n\tcase 1:\n\t\tpProp = &pMaterial->NormalMap;\n\t\tbreak;\n\tcase 2:\n\t\tpProp = &pMaterial->Specular;\n\t\tbreak;\n\tcase 3:\n\t\tpProp = &pMaterial->Bump;\n\t\tbreak;\n\tdefault:\n\t\tpProp = nullptr;\n\t\tbreak;\n\t}\n\n\tif (pProp != nullptr) {\n\t\tpProp->ConnectSrcObject(pTexture);\n\t}\n}\n\nAS_API(FbxArray<FbxCluster*>*) AsFbxMeshCreateClusterArray(int32_t boneCount)\n{\n\treturn new FbxArray<FbxCluster*>(boneCount);\n}\n\nAS_API(void) AsFbxMeshDisposeClusterArray(FbxArray<FbxCluster*>** ppArray)\n{\n\tif (ppArray == nullptr) {\n\t\treturn;\n\t}\n\n\tdelete (*ppArray);\n\t*ppArray = nullptr;\n}\n\nAS_API(FbxCluster*) AsFbxMeshCreateCluster(AsFbxContext* pContext, FbxNode* pBoneNode)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr) {\n\t\treturn nullptr;\n\t}\n\n\tif (pBoneNode == nullptr) {\n\t\treturn nullptr;\n\t}\n\n\tFbxString lClusterName = pBoneNode->GetNameOnly() + FbxString(\"Cluster\");\n\tFbxCluster* pCluster = FbxCluster::Create(pContext->pScene, lClusterName.Buffer());\n\tpCluster->SetLink(pBoneNode);\n\tpCluster->SetLinkMode(FbxCluster::eTotalOne);\n\n\treturn pCluster;\n}\n\nAS_API(void) AsFbxMeshAddCluster(FbxArray<FbxCluster*>* pArray, FbxCluster* pCluster)\n{\n\tif (pArray == nullptr) {\n\t\treturn;\n\t}\n\n\tpArray->Add(pCluster);\n}\n\nAS_API(FbxMesh*) AsFbxMeshCreateMesh(AsFbxContext* pContext, FbxNode* pFrameNode)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tif (pFrameNode == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tFbxMesh* pMesh = FbxMesh::Create(pContext->pScene, pFrameNode->GetName());\n\tpFrameNode->SetNodeAttribute(pMesh);\n\n\treturn pMesh;\n}\n\nAS_API(void) AsFbxMeshInitControlPoints(FbxMesh* pMesh, int32_t vertexCount)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpMesh->InitControlPoints(vertexCount);\n}\n\nAS_API(void) AsFbxMeshCreateElementNormal(FbxMesh* pMesh)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pNormal = pMesh->CreateElementNormal();\n\tpNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);\n\tpNormal->SetReferenceMode(FbxGeometryElement::eDirect);\n}\n\nAS_API(void) AsFbxMeshCreateDiffuseUV(FbxMesh* pMesh, int32_t uv)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pUV = pMesh->CreateElementUV(FbxString(\"UV\") + FbxString(uv), FbxLayerElement::eTextureDiffuse);\n\tpUV->SetMappingMode(FbxGeometryElement::eByControlPoint);\n\tpUV->SetReferenceMode(FbxGeometryElement::eDirect);\n}\n\nAS_API(void) AsFbxMeshCreateNormalMapUV(FbxMesh* pMesh, int32_t uv)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pUV = pMesh->CreateElementUV(FbxString(\"UV\") + FbxString(uv), FbxLayerElement::eTextureNormalMap);\n\tpUV->SetMappingMode(FbxGeometryElement::eByControlPoint);\n\tpUV->SetReferenceMode(FbxGeometryElement::eDirect);\n}\n\nAS_API(void) AsFbxMeshCreateElementTangent(FbxMesh* pMesh)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pTangent = pMesh->CreateElementTangent();\n\tpTangent->SetMappingMode(FbxGeometryElement::eByControlPoint);\n\tpTangent->SetReferenceMode(FbxGeometryElement::eDirect);\n}\n\nAS_API(void) AsFbxMeshCreateElementVertexColor(FbxMesh* pMesh)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pVertexColor = pMesh->CreateElementVertexColor();\n\tpVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);\n\tpVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);\n}\n\nAS_API(void) AsFbxMeshCreateElementMaterial(FbxMesh* pMesh)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pMaterial = pMesh->CreateElementMaterial();\n\tpMaterial->SetMappingMode(FbxGeometryElement::eByPolygon);\n\tpMaterial->SetReferenceMode(FbxGeometryElement::eIndexToDirect);\n}\n\nAS_API(FbxSurfacePhong*) AsFbxCreateMaterial(AsFbxContext* pContext, const char* pMatName,\n\tfloat diffuseR, float diffuseG, float diffuseB,\n\tfloat ambientR, float ambientG, float ambientB,\n\tfloat emissiveR, float emissiveG, float emissiveB,\n\tfloat specularR, float specularG, float specularB,\n\tfloat reflectR, float reflectG, float reflectB,\n\tfloat shininess, float transparency)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tif (pMatName == nullptr)\n\t{\n\t\treturn nullptr;\n\t}\n\n\tauto pMat = FbxSurfacePhong::Create(pContext->pScene, pMatName);\n\n\tpMat->Diffuse.Set(FbxDouble3(diffuseR, diffuseG, diffuseB));\n\tpMat->Ambient.Set(FbxDouble3(ambientR, ambientG, ambientB));\n\tpMat->Emissive.Set(FbxDouble3(emissiveR, emissiveG, emissiveB));\n\tpMat->Specular.Set(FbxDouble3(specularR, specularG, specularB));\n\tpMat->Reflection.Set(FbxDouble3(reflectR, reflectG, reflectB));\n\tpMat->Shininess.Set(FbxDouble(shininess));\n\tpMat->TransparencyFactor.Set(FbxDouble(transparency));\n\tpMat->ShadingModel.Set(\"Phong\");\n\n\tif (pContext->pMaterials)\n\t{\n\t\tpContext->pMaterials->Add(pMat);\n\t}\n\n\treturn pMat;\n}\n\nAS_API(int32_t) AsFbxAddMaterialToFrame(FbxNode* pFrameNode, FbxSurfacePhong* pMaterial)\n{\n\tif (pFrameNode == nullptr || pMaterial == nullptr)\n\t{\n\t\treturn 0;\n\t}\n\n\treturn pFrameNode->AddMaterial(pMaterial);\n}\n\nAS_API(void) AsFbxSetFrameShadingModeToTextureShading(FbxNode* pFrameNode)\n{\n\tif (pFrameNode == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpFrameNode->SetShadingMode(FbxNode::eTextureShading);\n}\n\nAS_API(void) AsFbxMeshSetControlPoint(FbxMesh* pMesh, int32_t index, float x, float y, float z)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pControlPoints = pMesh->GetControlPoints();\n\n\tpControlPoints[index] = FbxVector4(x, y, z, 0);\n}\n\nAS_API(void) AsFbxMeshAddPolygon(FbxMesh* pMesh, int32_t materialIndex, int32_t index0, int32_t index1, int32_t index2)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpMesh->BeginPolygon(materialIndex);\n\tpMesh->AddPolygon(index0);\n\tpMesh->AddPolygon(index1);\n\tpMesh->AddPolygon(index2);\n\tpMesh->EndPolygon();\n}\n\nAS_API(void) AsFbxMeshElementNormalAdd(FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pElem = pMesh->GetElementNormal(elementIndex);\n\tauto& array = pElem->GetDirectArray();\n\n\tarray.Add(FbxVector4(x, y, z, 0));\n}\n\nAS_API(void) AsFbxMeshElementUVAdd(FbxMesh* pMesh, int32_t elementIndex, float u, float v)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pElem = pMesh->GetElementUV(FbxString(\"UV\") + FbxString(elementIndex));\n\tauto& array = pElem->GetDirectArray();\n\n\tarray.Add(FbxVector2(u, v));\n}\n\nAS_API(void) AsFbxMeshElementTangentAdd(FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z, float w)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pElem = pMesh->GetElementTangent(elementIndex);\n\tauto& array = pElem->GetDirectArray();\n\n\tarray.Add(FbxVector4(x, y, z, w));\n}\n\nAS_API(void) AsFbxMeshElementVertexColorAdd(FbxMesh* pMesh, int32_t elementIndex, float r, float g, float b, float a)\n{\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pElem = pMesh->GetElementVertexColor(elementIndex);\n\tauto& array = pElem->GetDirectArray();\n\n\tarray.Add(FbxVector4(r, g, b, a));\n}\n\nAS_API(void) AsFbxMeshSetBoneWeight(FbxArray<FbxCluster*>* pClusterArray, int32_t boneIndex, int32_t vertexIndex, float weight)\n{\n\tif (pClusterArray == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pCluster = pClusterArray->GetAt(boneIndex);\n\n\tif (pCluster != nullptr)\n\t{\n\t\tpCluster->AddControlPointIndex(vertexIndex, weight);\n\t}\n}\n\nAS_API(AsFbxSkinContext*) AsFbxMeshCreateSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode)\n{\n\treturn new AsFbxSkinContext(pContext, pFrameNode);\n}\n\nAS_API(void) AsFbxMeshDisposeSkinContext(AsFbxSkinContext** ppSkinContext)\n{\n\tif (ppSkinContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tdelete (*ppSkinContext);\n\t*ppSkinContext = nullptr;\n}\n\nAS_API(bool32_t) FbxClusterArray_HasItemAt(FbxArray<FbxCluster*>* pClusterArray, int32_t index)\n{\n\tif (pClusterArray == nullptr)\n\t{\n\t\treturn false;\n\t}\n\n\tauto pCluster = pClusterArray->GetAt(index);\n\n\treturn pCluster != nullptr;\n}\n\nstatic inline int32_t IndexFrom4x4(int32_t m, int32_t n)\n{\n\treturn m * 4 + n;\n}\n\nAS_API(void) AsFbxMeshSkinAddCluster(AsFbxSkinContext* pSkinContext, FbxArray<FbxCluster*>* pClusterArray, int32_t index, float pBoneMatrix[16])\n{\n\tif (pSkinContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pClusterArray == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pBoneMatrix == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pCluster = pClusterArray->GetAt(index);\n\n\tif (pCluster == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxAMatrix boneMatrix;\n\n\tfor (int m = 0; m < 4; m += 1)\n\t{\n\t\tfor (int n = 0; n < 4; n += 1)\n\t\t{\n\t\t\tauto index = IndexFrom4x4(m, n);\n\t\t\tboneMatrix.mData[m][n] = pBoneMatrix[index];\n\t\t}\n\t}\n\n\tpCluster->SetTransformMatrix(pSkinContext->lMeshMatrix);\n\tpCluster->SetTransformLinkMatrix(pSkinContext->lMeshMatrix * boneMatrix.Inverse());\n\n\tif (pSkinContext->pSkin)\n\t{\n\t\tpSkinContext->pSkin->AddCluster(pCluster);\n\t}\n}\n\nAS_API(void) AsFbxMeshAddDeformer(AsFbxSkinContext* pSkinContext, FbxMesh* pMesh)\n{\n\tif (pSkinContext == nullptr || pSkinContext->pSkin == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pMesh == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pSkinContext->pSkin->GetClusterCount() > 0)\n\t{\n\t\tpMesh->AddDeformer(pSkinContext->pSkin);\n\t}\n}\n\nAS_API(AsFbxAnimContext*) AsFbxAnimCreateContext(bool32_t eulerFilter)\n{\n\treturn new AsFbxAnimContext(eulerFilter);\n}\n\nAS_API(void) AsFbxAnimDisposeContext(AsFbxAnimContext** ppAnimContext)\n{\n\tif (ppAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tdelete (*ppAnimContext);\n\t*ppAnimContext = nullptr;\n}\n\nAS_API(void) AsFbxAnimPrepareStackAndLayer(AsFbxContext* pContext, AsFbxAnimContext* pAnimContext, const char* pTakeName)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pTakeName == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpAnimContext->lAnimStack = FbxAnimStack::Create(pContext->pScene, pTakeName);\n\tpAnimContext->lAnimLayer = FbxAnimLayer::Create(pContext->pScene, \"Base Layer\");\n\n\tpAnimContext->lAnimStack->AddMember(pAnimContext->lAnimLayer);\n}\n\nAS_API(void) AsFbxAnimLoadCurves(FbxNode* pNode, AsFbxAnimContext* pAnimContext)\n{\n\tif (pNode == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpAnimContext->lCurveSX = pNode->LclScaling.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);\n\tpAnimContext->lCurveSY = pNode->LclScaling.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);\n\tpAnimContext->lCurveSZ = pNode->LclScaling.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);\n\tpAnimContext->lCurveRX = pNode->LclRotation.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);\n\tpAnimContext->lCurveRY = pNode->LclRotation.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);\n\tpAnimContext->lCurveRZ = pNode->LclRotation.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);\n\tpAnimContext->lCurveTX = pNode->LclTranslation.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);\n\tpAnimContext->lCurveTY = pNode->LclTranslation.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);\n\tpAnimContext->lCurveTZ = pNode->LclTranslation.GetCurve(pAnimContext->lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);\n}\n\nAS_API(void) AsFbxAnimBeginKeyModify(AsFbxAnimContext* pAnimContext)\n{\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpAnimContext->lCurveSX->KeyModifyBegin();\n\tpAnimContext->lCurveSY->KeyModifyBegin();\n\tpAnimContext->lCurveSZ->KeyModifyBegin();\n\tpAnimContext->lCurveRX->KeyModifyBegin();\n\tpAnimContext->lCurveRY->KeyModifyBegin();\n\tpAnimContext->lCurveRZ->KeyModifyBegin();\n\tpAnimContext->lCurveTX->KeyModifyBegin();\n\tpAnimContext->lCurveTY->KeyModifyBegin();\n\tpAnimContext->lCurveTZ->KeyModifyBegin();\n}\n\nAS_API(void) AsFbxAnimEndKeyModify(AsFbxAnimContext* pAnimContext)\n{\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpAnimContext->lCurveSX->KeyModifyEnd();\n\tpAnimContext->lCurveSY->KeyModifyEnd();\n\tpAnimContext->lCurveSZ->KeyModifyEnd();\n\tpAnimContext->lCurveRX->KeyModifyEnd();\n\tpAnimContext->lCurveRY->KeyModifyEnd();\n\tpAnimContext->lCurveRZ->KeyModifyEnd();\n\tpAnimContext->lCurveTX->KeyModifyEnd();\n\tpAnimContext->lCurveTY->KeyModifyEnd();\n\tpAnimContext->lCurveTZ->KeyModifyEnd();\n}\n\nAS_API(void) AsFbxAnimAddScalingKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z)\n{\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxTime lTime;\n\tlTime.SetSecondDouble(time);\n\n\tpAnimContext->lCurveSX->KeySet(pAnimContext->lCurveSX->KeyAdd(lTime), lTime, x);\n\tpAnimContext->lCurveSY->KeySet(pAnimContext->lCurveSY->KeyAdd(lTime), lTime, y);\n\tpAnimContext->lCurveSZ->KeySet(pAnimContext->lCurveSZ->KeyAdd(lTime), lTime, z);\n}\n\nAS_API(void) AsFbxAnimAddRotationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z)\n{\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxTime lTime;\n\tlTime.SetSecondDouble(time);\n\n\tpAnimContext->lCurveRX->KeySet(pAnimContext->lCurveRX->KeyAdd(lTime), lTime, x);\n\tpAnimContext->lCurveRY->KeySet(pAnimContext->lCurveRY->KeyAdd(lTime), lTime, y);\n\tpAnimContext->lCurveRZ->KeySet(pAnimContext->lCurveRZ->KeyAdd(lTime), lTime, z);\n}\n\nAS_API(void) AsFbxAnimAddTranslationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z)\n{\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxTime lTime;\n\tlTime.SetSecondDouble(time);\n\n\tpAnimContext->lCurveTX->KeySet(pAnimContext->lCurveTX->KeyAdd(lTime), lTime, x);\n\tpAnimContext->lCurveTY->KeySet(pAnimContext->lCurveTY->KeyAdd(lTime), lTime, y);\n\tpAnimContext->lCurveTZ->KeySet(pAnimContext->lCurveTZ->KeyAdd(lTime), lTime, z);\n}\n\nAS_API(void) AsFbxAnimApplyEulerFilter(AsFbxAnimContext* pAnimContext, float filterPrecision)\n{\n\tif (pAnimContext == nullptr || pAnimContext->lFilter == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxAnimCurve* lCurve[3];\n\tlCurve[0] = pAnimContext->lCurveRX;\n\tlCurve[1] = pAnimContext->lCurveRY;\n\tlCurve[2] = pAnimContext->lCurveRZ;\n\n\tauto eulerFilter = pAnimContext->lFilter;\n\n\teulerFilter->Reset();\n\teulerFilter->SetQualityTolerance(filterPrecision);\n\teulerFilter->Apply(lCurve, 3);\n}\n\nAS_API(int32_t) AsFbxAnimGetCurrentBlendShapeChannelCount(AsFbxAnimContext* pAnimContext, fbxsdk::FbxNode* pNode)\n{\n\tif (pAnimContext == nullptr)\n\t{\n\t\treturn 0;\n\t}\n\n\tif (pNode == nullptr)\n\t{\n\t\treturn 0;\n\t}\n\n\tauto pMesh = pNode->GetMesh();\n\tpAnimContext->pMesh = pMesh;\n\n\tif (pMesh == nullptr)\n\t{\n\t\treturn 0;\n\t}\n\n\tauto blendShapeDeformerCount = pMesh->GetDeformerCount(FbxDeformer::eBlendShape);\n\n\tif (blendShapeDeformerCount <= 0)\n\t{\n\t\treturn 0;\n\t}\n\n\tauto lBlendShape = (FbxBlendShape*)pMesh->GetDeformer(0, FbxDeformer::eBlendShape);\n\tpAnimContext->lBlendShape = lBlendShape;\n\n\tif (lBlendShape == nullptr)\n\t{\n\t\treturn 0;\n\t}\n\n\tauto lBlendShapeChannelCount = lBlendShape->GetBlendShapeChannelCount();\n\n\treturn lBlendShapeChannelCount;\n}\n\nAS_API(bool32_t) AsFbxAnimIsBlendShapeChannelMatch(AsFbxAnimContext* pAnimContext, int32_t channelIndex, const char* channelName)\n{\n\tif (pAnimContext == nullptr || pAnimContext->lBlendShape == nullptr)\n\t{\n\t\treturn false;\n\t}\n\n\tif (channelName == nullptr)\n\t{\n\t\treturn false;\n\t}\n\n\tFbxBlendShapeChannel* lChannel = pAnimContext->lBlendShape->GetBlendShapeChannel(channelIndex);\n\tauto lChannelName = lChannel->GetNameOnly();\n\n\tFbxString chanName(channelName);\n\n\treturn lChannelName == chanName;\n}\n\nAS_API(void) AsFbxAnimBeginBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext, int32_t channelIndex)\n{\n\tif (pAnimContext == nullptr || pAnimContext->pMesh == nullptr || pAnimContext->lAnimLayer == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpAnimContext->lAnimCurve = pAnimContext->pMesh->GetShapeChannel(0, channelIndex, pAnimContext->lAnimLayer, true);\n\tpAnimContext->lAnimCurve->KeyModifyBegin();\n}\n\nAS_API(void) AsFbxAnimEndBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext)\n{\n\tif (pAnimContext == nullptr || pAnimContext->lAnimCurve == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpAnimContext->lAnimCurve->KeyModifyEnd();\n}\n\nAS_API(void) AsFbxAnimAddBlendShapeKeyframe(AsFbxAnimContext* pAnimContext, float time, float value)\n{\n\tif (pAnimContext == nullptr || pAnimContext->lAnimCurve == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tFbxTime lTime;\n\tlTime.SetSecondDouble(time);\n\n\tauto keyIndex = pAnimContext->lAnimCurve->KeyAdd(lTime);\n\tpAnimContext->lAnimCurve->KeySetValue(keyIndex, value);\n\tpAnimContext->lAnimCurve->KeySetInterpolation(keyIndex, FbxAnimCurveDef::eInterpolationCubic);\n}\n\nAS_API(AsFbxMorphContext*) AsFbxMorphCreateContext()\n{\n\treturn new AsFbxMorphContext();\n}\n\nAS_API(void) AsFbxMorphInitializeContext(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, fbxsdk::FbxNode* pNode)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pMorphContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pNode == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto pMesh = pNode->GetMesh();\n\tpMorphContext->pMesh = pMesh;\n\n\tauto lBlendShape = FbxBlendShape::Create(pContext->pScene, pMesh->GetNameOnly() + FbxString(\"BlendShape\"));\n\tpMorphContext->lBlendShape = lBlendShape;\n\n\tpMesh->AddDeformer(lBlendShape);\n}\n\nAS_API(void) AsFbxMorphDisposeContext(AsFbxMorphContext** ppMorphContext)\n{\n\tif (ppMorphContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tdelete (*ppMorphContext);\n\t*ppMorphContext = nullptr;\n}\n\nAS_API(void) AsFbxMorphAddBlendShapeChannel(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, const char* channelName)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pMorphContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (channelName == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto lBlendShapeChannel = FbxBlendShapeChannel::Create(pContext->pScene, channelName);\n\tpMorphContext->lBlendShapeChannel = lBlendShapeChannel;\n\n\tif (pMorphContext->lBlendShape != nullptr)\n\t{\n\t\tpMorphContext->lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);\n\t}\n}\n\nAS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight, const char* shapeName)\n{\n\tif (pContext == nullptr || pContext->pScene == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tif (pMorphContext == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto lShape = FbxShape::Create(pContext->pScene, shapeName);\n\tpMorphContext->lShape = lShape;\n\n\tif (pMorphContext->lBlendShapeChannel != nullptr) {\n\t\tpMorphContext->lBlendShapeChannel->AddTargetShape(lShape, weight);\n\t}\n}\n\nAS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphContext)\n{\n\tif (pMorphContext == nullptr || pMorphContext->pMesh == nullptr || pMorphContext->lShape == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto vectorCount = pMorphContext->pMesh->GetControlPointsCount();\n\n\tauto srcControlPoints = pMorphContext->pMesh->GetControlPoints();\n\n\tpMorphContext->lShape->InitControlPoints(vectorCount);\n\n\tfor (int j = 0; j < vectorCount; j++)\n\t{\n\t\tpMorphContext->lShape->SetControlPointAt(FbxVector4(srcControlPoints[j]), j);;\n\t}\n}\n\nAS_API(void) AsFbxMorphSetBlendShapeVertex(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z)\n{\n\tif (pMorphContext == nullptr || pMorphContext->lShape == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpMorphContext->lShape->SetControlPointAt(FbxVector4(x, y, z, 0), index);\n}\n\nAS_API(void) AsFbxMorphCopyBlendShapeControlPointsNormal(AsFbxMorphContext* pMorphContext)\n{\n\tif (pMorphContext == nullptr || pMorphContext->pMesh == nullptr || pMorphContext->lShape == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpMorphContext->lShape->InitNormals(pMorphContext->pMesh);\n}\n\nAS_API(void) AsFbxMorphSetBlendShapeVertexNormal(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z)\n{\n\tif (pMorphContext == nullptr || pMorphContext->lShape == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tpMorphContext->lShape->SetControlPointNormalAt(FbxVector4(x, y, z, 0), index);\n}\n"
  },
  {
    "path": "AssetStudioFBXNative/api.h",
    "content": "#pragma once\n\n#include \"dllexport.h\"\n#include \"bool32_t.h\"\n\nnamespace fbxsdk\n{\n\tclass FbxNode;\n\tclass FbxFileTexture;\n\ttemplate<typename T, const int Alignment = 16>\n\tclass FbxArray;\n\tclass FbxCluster;\n\tclass FbxMesh;\n\tclass FbxSurfacePhong;\n}\n\nstruct AsFbxContext;\nstruct AsFbxSkinContext;\nstruct AsFbxAnimContext;\nstruct AsFbxMorphContext;\n\nAS_API(void) AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, float* vx, float* vy, float* vz);\n\nAS_API(void) AsUtilEulerToQuaternion(float vx, float vy, float vz, float* qx, float* qy, float* qz, float* qw);\n\n// All strings ([const] char *) in this header are UTF-8 strings.\n\nAS_API(AsFbxContext*) AsFbxCreateContext();\n\n// Do not free pErrMsg\nAS_API(bool32_t) AsFbxInitializeContext(AsFbxContext* pContext, const char* pFileName, float scaleFactor, int32_t versionIndex, bool32_t isAscii, bool32_t is60Fps, const char** pErrMsg);\n\nAS_API(void) AsFbxDisposeContext(AsFbxContext** ppContext);\n\nAS_API(void) AsFbxSetFramePaths(AsFbxContext* pContext, const char* ppPaths[], int32_t count);\n\nAS_API(void) AsFbxExportScene(AsFbxContext* pContext);\n\nAS_API(fbxsdk::FbxNode*) AsFbxGetSceneRootNode(AsFbxContext* pContext);\n\nAS_API(fbxsdk::FbxNode*) AsFbxExportSingleFrame(AsFbxContext* pContext, fbxsdk::FbxNode* pParentNode, const char* pFramePath, const char* pFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);\n\nAS_API(void) AsFbxSetJointsNode_CastToBone(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);\n\nAS_API(void) AsFbxSetJointsNode_BoneInPath(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);\n\nAS_API(void) AsFbxSetJointsNode_Generic(AsFbxContext* pContext, fbxsdk::FbxNode* pNode);\n\nAS_API(void) AsFbxPrepareMaterials(AsFbxContext* pContext, int32_t materialCount, int32_t textureCount);\n\nAS_API(fbxsdk::FbxFileTexture*) AsFbxCreateTexture(AsFbxContext* pContext, const char* pMatTexName);\n\nAS_API(void) AsFbxLinkTexture(int32_t dest, fbxsdk::FbxFileTexture* pTexture, fbxsdk::FbxSurfacePhong* pMaterial, float offsetX, float offsetY, float scaleX, float scaleY);\n\nAS_API(fbxsdk::FbxArray<fbxsdk::FbxCluster*>*) AsFbxMeshCreateClusterArray(int32_t boneCount);\n\nAS_API(void) AsFbxMeshDisposeClusterArray(fbxsdk::FbxArray<fbxsdk::FbxCluster*>** ppArray);\n\nAS_API(fbxsdk::FbxCluster*) AsFbxMeshCreateCluster(AsFbxContext* pContext, fbxsdk::FbxNode* pBoneNode);\n\nAS_API(void) AsFbxMeshAddCluster(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pArray, /* CanBeNull */ fbxsdk::FbxCluster* pCluster);\n\nAS_API(fbxsdk::FbxMesh*) AsFbxMeshCreateMesh(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);\n\nAS_API(void) AsFbxMeshInitControlPoints(fbxsdk::FbxMesh* pMesh, int32_t vertexCount);\n\nAS_API(void) AsFbxMeshCreateElementNormal(fbxsdk::FbxMesh* pMesh);\n\nAS_API(void) AsFbxMeshCreateDiffuseUV(fbxsdk::FbxMesh* pMesh, int32_t uv);\n\nAS_API(void) AsFbxMeshCreateNormalMapUV(fbxsdk::FbxMesh* pMesh, int32_t uv);\n\nAS_API(void) AsFbxMeshCreateElementTangent(fbxsdk::FbxMesh* pMesh);\n\nAS_API(void) AsFbxMeshCreateElementVertexColor(fbxsdk::FbxMesh* pMesh);\n\nAS_API(void) AsFbxMeshCreateElementMaterial(fbxsdk::FbxMesh* pMesh);\n\nAS_API(fbxsdk::FbxSurfacePhong*) AsFbxCreateMaterial(AsFbxContext* pContext, const char* pMatName,\n\tfloat diffuseR, float diffuseG, float diffuseB,\n\tfloat ambientR, float ambientG, float ambientB,\n\tfloat emissiveR, float emissiveG, float emissiveB,\n\tfloat specularR, float specularG, float specularB,\n\tfloat reflectR, float reflectG, float reflectB,\n\tfloat shininess, float transparency);\n\nAS_API(int32_t) AsFbxAddMaterialToFrame(fbxsdk::FbxNode* pFrameNode, fbxsdk::FbxSurfacePhong* pMaterial);\n\nAS_API(void) AsFbxSetFrameShadingModeToTextureShading(fbxsdk::FbxNode* pFrameNode);\n\nAS_API(void) AsFbxMeshSetControlPoint(fbxsdk::FbxMesh* pMesh, int32_t index, float x, float y, float z);\n\nAS_API(void) AsFbxMeshAddPolygon(fbxsdk::FbxMesh* pMesh, int32_t materialIndex, int32_t index0, int32_t index1, int32_t index2);\n\nAS_API(void) AsFbxMeshElementNormalAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z);\n\nAS_API(void) AsFbxMeshElementUVAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float u, float v);\n\nAS_API(void) AsFbxMeshElementTangentAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z, float w);\n\nAS_API(void) AsFbxMeshElementVertexColorAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float r, float g, float b, float a);\n\nAS_API(void) AsFbxMeshSetBoneWeight(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t boneIndex, int32_t vertexIndex, float weight);\n\nAS_API(AsFbxSkinContext*) AsFbxMeshCreateSkinContext(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);\n\nAS_API(void) AsFbxMeshDisposeSkinContext(AsFbxSkinContext** ppSkinContext);\n\nAS_API(bool32_t) FbxClusterArray_HasItemAt(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index);\n\nAS_API(void) AsFbxMeshSkinAddCluster(AsFbxSkinContext* pSkinContext, fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index, float pBoneMatrix[16]);\n\nAS_API(void) AsFbxMeshAddDeformer(AsFbxSkinContext* pSkinContext, fbxsdk::FbxMesh* pMesh);\n\nAS_API(AsFbxAnimContext*) AsFbxAnimCreateContext(bool32_t eulerFilter);\n\nAS_API(void) AsFbxAnimDisposeContext(AsFbxAnimContext** ppAnimContext);\n\nAS_API(void) AsFbxAnimPrepareStackAndLayer(AsFbxContext* pContext, AsFbxAnimContext* pAnimContext, const char* pTakeName);\n\nAS_API(void) AsFbxAnimLoadCurves(fbxsdk::FbxNode* pNode, AsFbxAnimContext* pAnimContext);\n\nAS_API(void) AsFbxAnimBeginKeyModify(AsFbxAnimContext* pAnimContext);\n\nAS_API(void) AsFbxAnimEndKeyModify(AsFbxAnimContext* pAnimContext);\n\nAS_API(void) AsFbxAnimAddScalingKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);\n\nAS_API(void) AsFbxAnimAddRotationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);\n\nAS_API(void) AsFbxAnimAddTranslationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);\n\nAS_API(void) AsFbxAnimApplyEulerFilter(AsFbxAnimContext* pAnimContext, float filterPrecision);\n\nAS_API(int32_t) AsFbxAnimGetCurrentBlendShapeChannelCount(AsFbxAnimContext* pAnimContext, fbxsdk::FbxNode* pNode);\n\nAS_API(bool32_t) AsFbxAnimIsBlendShapeChannelMatch(AsFbxAnimContext* pAnimContext, int32_t channelIndex, const char* channelName);\n\nAS_API(void) AsFbxAnimBeginBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext, int32_t channelIndex);\n\nAS_API(void) AsFbxAnimEndBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext);\n\nAS_API(void) AsFbxAnimAddBlendShapeKeyframe(AsFbxAnimContext* pAnimContext, float time, float value);\n\nAS_API(AsFbxMorphContext*) AsFbxMorphCreateContext();\n\nAS_API(void) AsFbxMorphInitializeContext(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, fbxsdk::FbxNode* pNode);\n\nAS_API(void) AsFbxMorphDisposeContext(AsFbxMorphContext** ppMorphContext);\n\nAS_API(void) AsFbxMorphAddBlendShapeChannel(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, const char* channelName);\n\nAS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight, const char* shapeName);\n\nAS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphContext);\n\nAS_API(void) AsFbxMorphSetBlendShapeVertex(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z);\n\nAS_API(void) AsFbxMorphCopyBlendShapeControlPointsNormal(AsFbxMorphContext* pMorphContext);\n\nAS_API(void) AsFbxMorphSetBlendShapeVertexNormal(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z);\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_anim_context.cpp",
    "content": "#include \"asfbx_anim_context.h\"\n\nAsFbxAnimContext::AsFbxAnimContext(bool32_t eulerFilter)\n\t: lFilter(nullptr)\n{\n\tif (eulerFilter)\n\t{\n\t\tlFilter = new FbxAnimCurveFilterUnroll();\n\t}\n\n\tlAnimStack = nullptr;\n\tlAnimLayer = nullptr;\n\n\tlCurveSX = nullptr;\n\tlCurveSY = nullptr;\n\tlCurveSZ = nullptr;\n\tlCurveRX = nullptr;\n\tlCurveRY = nullptr;\n\tlCurveRZ = nullptr;\n\tlCurveTX = nullptr;\n\tlCurveTY = nullptr;\n\tlCurveTZ = nullptr;\n\n\tpMesh = nullptr;\n\tlBlendShape = nullptr;\n\tlAnimCurve = nullptr;\n}\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_anim_context.h",
    "content": "#pragma once\n\n#include <fbxsdk.h>\n\n#include \"bool32_t.h\"\n\nstruct AsFbxAnimContext\n{\n\n\tFbxAnimCurveFilterUnroll* lFilter;\n\n\tFbxAnimStack* lAnimStack;\n\tFbxAnimLayer* lAnimLayer;\n\n\tFbxAnimCurve* lCurveSX;\n\tFbxAnimCurve* lCurveSY;\n\tFbxAnimCurve* lCurveSZ;\n\tFbxAnimCurve* lCurveRX;\n\tFbxAnimCurve* lCurveRY;\n\tFbxAnimCurve* lCurveRZ;\n\tFbxAnimCurve* lCurveTX;\n\tFbxAnimCurve* lCurveTY;\n\tFbxAnimCurve* lCurveTZ;\n\n\tFbxMesh* pMesh;\n\tFbxBlendShape* lBlendShape;\n\tFbxAnimCurve* lAnimCurve;\n\n\tAsFbxAnimContext(bool32_t eulerFilter);\n\t~AsFbxAnimContext() = default;\n\n};\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_context.cpp",
    "content": "#include <fbxsdk.h>\n\n#include \"asfbx_context.h\"\n\nAsFbxContext::AsFbxContext()\n{\n\tpSdkManager = nullptr;\n\tpScene = nullptr;\n\tpTextures = nullptr;\n\tpMaterials = nullptr;\n\tpExporter = nullptr;\n\tpBindPose = nullptr;\n}\n\nAsFbxContext::~AsFbxContext()\n{\n\tframePaths.clear();\n\n\tdelete pMaterials;\n\tdelete pTextures;\n\n\tif (pExporter != nullptr) {\n\t\tpExporter->Destroy();\n\t}\n\n\tif (pScene != nullptr) {\n\t\tpScene->Destroy();\n\t}\n\n\tif (pSdkManager != nullptr) {\n\t\tpSdkManager->Destroy();\n\t}\n}\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_context.h",
    "content": "#pragma once\n\n#include <cstdint>\n#include <string>\n#include <unordered_set>\n\nstruct AsFbxContext\n{\n\n\tfbxsdk::FbxManager* pSdkManager;\n\tfbxsdk::FbxScene* pScene;\n\tfbxsdk::FbxArray<fbxsdk::FbxFileTexture*>* pTextures;\n\tfbxsdk::FbxArray<fbxsdk::FbxSurfacePhong*>* pMaterials;\n\tfbxsdk::FbxExporter* pExporter;\n\tfbxsdk::FbxPose* pBindPose;\n\n\tstd::unordered_set<std::string> framePaths;\n\n\tAsFbxContext();\n\t~AsFbxContext();\n};\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_morph_context.cpp",
    "content": "#include \"asfbx_morph_context.h\"\n\nAsFbxMorphContext::AsFbxMorphContext()\n{\n\tpMesh = nullptr;\n\tlBlendShape = nullptr;\n\tlBlendShapeChannel = nullptr;\n\tlShape = nullptr;\n}\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_morph_context.h",
    "content": "#pragma once\n\n#include <fbxsdk.h>\n\nstruct AsFbxMorphContext\n{\n\n\tFbxMesh* pMesh;\n\tFbxBlendShape* lBlendShape;\n\tFbxBlendShapeChannel* lBlendShapeChannel;\n\tFbxShape* lShape;\n\n\tAsFbxMorphContext();\n\t~AsFbxMorphContext() = default;\n\n};\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_skin_context.cpp",
    "content": "#include \"asfbx_skin_context.h\"\n#include \"asfbx_context.h\"\n\nAsFbxSkinContext::AsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode)\n\t: pSkin(nullptr)\n{\n\tif (pContext != nullptr && pContext->pScene != nullptr)\n\t{\n\t\tpSkin = FbxSkin::Create(pContext->pScene, \"\");\n\t}\n\n\tif (pFrameNode != nullptr) \n\t{\n\t\tlMeshMatrix = pFrameNode->EvaluateGlobalTransform();\n\t}\n}\n"
  },
  {
    "path": "AssetStudioFBXNative/asfbx_skin_context.h",
    "content": "#pragma once\n\n#include <fbxsdk.h>\n\nstruct AsFbxContext;\n\nstruct AsFbxSkinContext\n{\n\t\n\tFbxSkin* pSkin;\n\tFbxAMatrix lMeshMatrix;\n\n\tAsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode);\n\t~AsFbxSkinContext() = default;\n\n};\n"
  },
  {
    "path": "AssetStudioFBXNative/bool32_t.h",
    "content": "#pragma once\n\n#include <cstdint>\n\ntypedef uint32_t bool32_t;\n"
  },
  {
    "path": "AssetStudioFBXNative/cpp.hint",
    "content": "#define AS_API(ret_type)\n"
  },
  {
    "path": "AssetStudioFBXNative/dllexport.h",
    "content": "#pragma once\n\n#if defined(_MSC_VER)\n#if _MSC_VER < 1910 // MSVC 2017-\n#error MSVC 2017 or later is required.\n#endif\n#endif\n\n#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__)\n#ifdef _AS_DLL\n#ifdef __GNUC__\n#define _AS_EXPORT __attribute__ ((dllexport))\n#else\n#define _AS_EXPORT __declspec(dllexport)\n#endif\n#else\n#ifdef __GNUC__\n#define _AS_EXPORT __attribute__ ((dllimport))\n#else\n#define _AS_EXPORT __declspec(dllimport)\n#endif\n#endif\n#define _AS_LOCAL\n#else\n#if __GNUC__ >= 4\n#define _AS_EXPORT __attribute__ ((visibility (\"default\")))\n#define _AS_LOCAL  __attribute__ ((visibility (\"hidden\")))\n#else\n#define _AS_EXPORT\n#define _AS_LOCAL\n#endif\n#endif\n\n#ifdef __cplusplus\n#ifndef _EXTERN_C_STMT\n#define _EXTERN_C_STMT extern \"C\"\n#endif\n#else\n#ifndef _EXTERN_C_STMT\n#define _EXTERN_C_STMT\n#endif\n#endif\n\n#ifndef _AS_CALL\n#if defined(WIN32) || defined(_WIN32)\n#define _AS_CALL __stdcall\n#else\n#define _AS_CALL /* __cdecl */\n#endif\n#endif\n\n#if defined(_MSC_VER)\n#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT ret_type _AS_CALL\n#else\n#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT _AS_CALL ret_type\n#endif\n"
  },
  {
    "path": "AssetStudioFBXNative/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by AssetStudioFBXNative.rc\n\n// ¶һĬֵ\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        101\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1001\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "AssetStudioFBXNative/utils.cpp",
    "content": "#include <fbxsdk.h>\n#include <cassert>\n\n#include \"utils.h\"\n\nVector3::Vector3()\n\t: X(0), Y(0), Z(0)\n{\n}\n\nVector3::Vector3(float x, float y, float z)\n\t: X(x), Y(y), Z(z)\n{\n}\n\nQuaternion::Quaternion()\n\t: X(0), Y(0), Z(0), W(1)\n{\n}\n\nQuaternion::Quaternion(float x, float y, float z)\n\t: X(x), Y(y), Z(z), W(1)\n{\n}\n\nQuaternion::Quaternion(float x, float y, float z, float w)\n\t: X(x), Y(y), Z(z), W(w)\n{\n}\n\nVector3 QuaternionToEuler(Quaternion q) {\n\tFbxAMatrix lMatrixRot;\n\tlMatrixRot.SetQ(FbxQuaternion(q.X, q.Y, q.Z, q.W));\n\tFbxVector4 lEuler = lMatrixRot.GetR();\n\treturn Vector3((float)lEuler[0], (float)lEuler[1], (float)lEuler[2]);\n}\n\nQuaternion EulerToQuaternion(Vector3 v) {\n\tFbxAMatrix lMatrixRot;\n\tlMatrixRot.SetR(FbxVector4(v.X, v.Y, v.Z));\n\tFbxQuaternion lQuaternion = lMatrixRot.GetQ();\n\treturn Quaternion((float)lQuaternion[0], (float)lQuaternion[1], (float)lQuaternion[2], (float)lQuaternion[3]);\n}\n"
  },
  {
    "path": "AssetStudioFBXNative/utils.h",
    "content": "#pragma once\n\nstruct Vector3 {\n\n\tfloat X;\n\tfloat Y;\n\tfloat Z;\n\n\tVector3();\n\tVector3(float x, float y, float z);\n\n};\n\nstruct Quaternion {\n\n\tfloat X;\n\tfloat Y;\n\tfloat Z;\n\tfloat W;\n\n\tQuaternion();\n\tQuaternion(float x, float y, float z);\n\tQuaternion(float x, float y, float z, float w);\n\n};\n\nVector3 QuaternionToEuler(Quaternion q);\n\nQuaternion EulerToQuaternion(Vector3 v);\n"
  },
  {
    "path": "AssetStudioFBXWrapper/AssetStudioFBXWrapper.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <Version>0.16.0.0</Version>\n    <AssemblyVersion>0.16.0.0</AssemblyVersion>\n    <FileVersion>0.16.0.0</FileVersion>\n    <Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>\n    <DebugType>embedded</DebugType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\AssetStudio.PInvoke\\AssetStudio.PInvoke.csproj\" />\n    <ProjectReference Include=\"..\\AssetStudio\\AssetStudio.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "AssetStudioFBXWrapper/Fbx.PInvoke.cs",
    "content": "﻿using System.Runtime.InteropServices;\nusing AssetStudio.FbxInterop;\n\nnamespace AssetStudio\n{\n    partial class Fbx\n    {\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, out float vx, out float vy, out float vz);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsUtilEulerToQuaternion(float vx, float vy, float vz, out float qx, out float qy, out float qz, out float qw);\n\n    }\n}\n"
  },
  {
    "path": "AssetStudioFBXWrapper/Fbx.cs",
    "content": "﻿using AssetStudio.FbxInterop;\nusing AssetStudio.PInvoke;\nusing System.IO;\n\nnamespace AssetStudio\n{\n    public static partial class Fbx\n    {\n\n        static Fbx()\n        {\n            DllLoader.PreloadDll(FbxDll.DllName);\n        }\n\n        public static Vector3 QuaternionToEuler(Quaternion q)\n        {\n            AsUtilQuaternionToEuler(q.X, q.Y, q.Z, q.W, out var x, out var y, out var z);\n            return new Vector3(x, y, z);\n        }\n\n        public static Quaternion EulerToQuaternion(Vector3 v)\n        {\n            AsUtilEulerToQuaternion(v.X, v.Y, v.Z, out var x, out var y, out var z, out var w);\n            return new Quaternion(x, y, z, w);\n        }\n\n        public static class Exporter\n        {\n\n            public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision,\n                bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii)\n            {\n                var file = new FileInfo(path);\n                var dir = file.Directory;\n\n                if (!dir.Exists)\n                {\n                    dir.Create();\n                }\n\n                var currentDir = Directory.GetCurrentDirectory();\n                Directory.SetCurrentDirectory(dir.FullName);\n\n                var name = Path.GetFileName(path);\n\n                using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, versionIndex, isAscii))\n                {\n                    exporter.Initialize();\n                    exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision);\n                }\n\n                Directory.SetCurrentDirectory(currentDir);\n            }\n\n        }\n\n    }\n}\n"
  },
  {
    "path": "AssetStudioFBXWrapper/FbxDll.cs",
    "content": "﻿namespace AssetStudio.FbxInterop\n{\n    internal static class FbxDll\n    {\n\n        internal const string DllName = \"AssetStudioFBXNative\";\n        internal const string FbxsdkDllName = \"libfbxsdk\";\n\n    }\n}\n"
  },
  {
    "path": "AssetStudioFBXWrapper/FbxExporter.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\n\nnamespace AssetStudio.FbxInterop\n{\n    internal sealed class FbxExporter : IDisposable\n    {\n\n        private FbxExporterContext _context;\n\n        private readonly string _fileName;\n        private readonly IImported _imported;\n        private readonly bool _allNodes;\n        private readonly bool _exportSkins;\n        private readonly bool _castToBone;\n        private readonly float _boneSize;\n        private readonly bool _exportAllUvsAsDiffuseMaps;\n        private readonly float _scaleFactor;\n        private readonly int _versionIndex;\n        private readonly bool _isAscii;\n\n        internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii)\n        {\n            _context = new FbxExporterContext();\n\n            _fileName = fileName;\n            _imported = imported;\n            _allNodes = allNodes;\n            _exportSkins = exportSkins;\n            _castToBone = castToBone;\n            _boneSize = boneSize;\n            _exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps;\n            _scaleFactor = scaleFactor;\n            _versionIndex = versionIndex;\n            _isAscii = isAscii;\n        }\n\n        ~FbxExporter()\n        {\n            Dispose(false);\n        }\n\n        public void Dispose()\n        {\n            if (IsDisposed)\n            {\n                return;\n            }\n\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        public bool IsDisposed { get; private set; }\n\n        private void Dispose(bool disposing)\n        {\n            if (disposing)\n            {\n                _context.Dispose();\n            }\n\n            IsDisposed = true;\n        }\n\n        internal void Initialize()\n        {\n            var is60Fps = _imported.AnimationList.Count > 0 && _imported.AnimationList[0].SampleRate.Equals(60.0f);\n\n            _context.Initialize(_fileName, _scaleFactor, _versionIndex, _isAscii, is60Fps);\n\n            if (!_allNodes)\n            {\n                var framePaths = SearchHierarchy();\n\n                _context.SetFramePaths(framePaths);\n            }\n        }\n\n        internal void ExportAll(bool blendShape, bool animation, bool eulerFilter, float filterPrecision)\n        {\n            var meshFrames = new List<ImportedFrame>();\n\n            ExportRootFrame(meshFrames);\n\n            if (_imported.MeshList != null)\n            {\n                SetJointsFromImportedMeshes();\n\n                PrepareMaterials();\n\n                ExportMeshFrames(_imported.RootFrame, meshFrames);\n            }\n            else\n            {\n                SetJointsNode(_imported.RootFrame, null, true);\n            }\n\n\n\n            if (blendShape)\n            {\n                ExportMorphs();\n            }\n\n            if (animation)\n            {\n                ExportAnimations(eulerFilter, filterPrecision);\n            }\n\n            ExportScene();\n        }\n\n        private void ExportMorphs()\n        {\n            _context.ExportMorphs(_imported.RootFrame, _imported.MorphList);\n        }\n\n        private void ExportAnimations(bool eulerFilter, float filterPrecision)\n        {\n            _context.ExportAnimations(_imported.RootFrame, _imported.AnimationList, eulerFilter, filterPrecision);\n        }\n\n        private void ExportRootFrame(List<ImportedFrame> meshFrames)\n        {\n            _context.ExportFrame(_imported.MeshList, meshFrames, _imported.RootFrame);\n        }\n\n        private void ExportScene()\n        {\n            _context.ExportScene();\n        }\n\n        private void SetJointsFromImportedMeshes()\n        {\n            if (!_exportSkins)\n            {\n                return;\n            }\n\n            Debug.Assert(_imported.MeshList != null);\n\n            var bonePaths = new HashSet<string>();\n\n            foreach (var mesh in _imported.MeshList)\n            {\n                var boneList = mesh.BoneList;\n\n                if (boneList != null)\n                {\n                    foreach (var bone in boneList)\n                    {\n                        bonePaths.Add(bone.Path);\n                    }\n                }\n            }\n\n            SetJointsNode(_imported.RootFrame, bonePaths, _castToBone);\n        }\n\n        private void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone)\n        {\n            _context.SetJointsNode(rootFrame, bonePaths, castToBone, _boneSize);\n        }\n\n        private void PrepareMaterials()\n        {\n            _context.PrepareMaterials(_imported.MaterialList.Count, _imported.TextureList.Count);\n        }\n\n        private void ExportMeshFrames(ImportedFrame rootFrame, List<ImportedFrame> meshFrames)\n        {\n            foreach (var meshFrame in meshFrames)\n            {\n                _context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins, _exportAllUvsAsDiffuseMaps);\n            }\n        }\n\n        private HashSet<string> SearchHierarchy()\n        {\n            if (_imported.MeshList == null || _imported.MeshList.Count == 0)\n            {\n                return null;\n            }\n\n            var exportFrames = new HashSet<string>();\n\n            SearchHierarchy(_imported.RootFrame, _imported.MeshList, exportFrames);\n\n            return exportFrames;\n        }\n\n        private static void SearchHierarchy(ImportedFrame rootFrame, List<ImportedMesh> meshList, HashSet<string> exportFrames)\n        {\n            var frameStack = new Stack<ImportedFrame>();\n\n            frameStack.Push(rootFrame);\n\n            while (frameStack.Count > 0)\n            {\n                var frame = frameStack.Pop();\n\n                var meshListSome = ImportedHelpers.FindMesh(frame.Path, meshList);\n\n                if (meshListSome != null)\n                {\n                    var parent = frame;\n\n                    while (parent != null)\n                    {\n                        exportFrames.Add(parent.Path);\n                        parent = parent.Parent;\n                    }\n\n                    var boneList = meshListSome.BoneList;\n\n                    if (boneList != null)\n                    {\n                        foreach (var bone in boneList)\n                        {\n                            if (!exportFrames.Contains(bone.Path))\n                            {\n                                var boneParent = rootFrame.FindFrameByPath(bone.Path);\n\n                                while (boneParent != null)\n                                {\n                                    exportFrames.Add(boneParent.Path);\n                                    boneParent = boneParent.Parent;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                for (var i = frame.Count - 1; i >= 0; i -= 1)\n                {\n                    frameStack.Push(frame[i]);\n                }\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "AssetStudioFBXWrapper/FbxExporterContext.PInvoke.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\nusing AssetStudio.PInvoke;\n\nnamespace AssetStudio.FbxInterop\n{\n    partial class FbxExporterContext\n    {\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxCreateContext();\n\n        private static bool AsFbxInitializeContext(IntPtr context, string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps, out string errorMessage)\n        {\n            bool b;\n            IntPtr pErrMsg;\n\n            using (var fileNameUtf8 = new Utf8StringHandle(fileName))\n            {\n                b = AsFbxInitializeContext(context, fileNameUtf8.DangerousGetHandle(), scaleFactor, versionIndex, isAscii, is60Fps, out pErrMsg);\n            }\n\n            errorMessage = Utf8StringHandle.ReadUtf8StringFromPointer(pErrMsg);\n\n            return b;\n        }\n\n        // Do not free the pointer strErrorMessage\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool AsFbxInitializeContext(IntPtr context, IntPtr strFileName, float scaleFactor, int versionIndex, [MarshalAs(UnmanagedType.Bool)] bool isAscii, [MarshalAs(UnmanagedType.Bool)] bool is60Fps, out IntPtr strErrorMessage);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxDisposeContext(ref IntPtr ppContext);\n\n        private static void AsFbxSetFramePaths(IntPtr context, string[] framePaths)\n        {\n            var framePathCount = framePaths.Length;\n\n            if (framePathCount == 0)\n            {\n                AsFbxSetFramePaths(context, Array.Empty<IntPtr>(), 0);\n            }\n            else\n            {\n                var utf8Paths = new Utf8StringHandle[framePathCount];\n\n                try\n                {\n                    for (var i = 0; i < framePathCount; i += 1)\n                    {\n                        utf8Paths[i] = new Utf8StringHandle(framePaths[i]);\n                    }\n\n                    var pathPointers = new IntPtr[framePathCount];\n\n                    for (var i = 0; i < framePathCount; i += 1)\n                    {\n                        pathPointers[i] = utf8Paths[i].DangerousGetHandle();\n                    }\n\n                    AsFbxSetFramePaths(context, pathPointers, framePathCount);\n                }\n                finally\n                {\n                    foreach (var path in utf8Paths)\n                    {\n                        path?.Dispose();\n                    }\n                }\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxSetFramePaths(IntPtr context, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] strFramePaths, int count);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxExportScene(IntPtr context);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxGetSceneRootNode(IntPtr context);\n\n        private static IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, string framePath, string frameName, in Vector3 localPosition, in Vector3 localRotation, in Vector3 localScale)\n        {\n            using (var framePathUtf8 = new Utf8StringHandle(framePath))\n            {\n                using (var frameNameUtf8 = new Utf8StringHandle(frameName))\n                {\n                    return AsFbxExportSingleFrame(context, parentNode, framePathUtf8.DangerousGetHandle(), frameNameUtf8.DangerousGetHandle(), localPosition.X, localPosition.Y, localPosition.Z, localRotation.X, localRotation.Y, localRotation.Z, localScale.X, localScale.Y, localScale.Z);\n                }\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, IntPtr strFramePath, IntPtr strFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxSetJointsNode_CastToBone(IntPtr context, IntPtr node, float boneSize);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxSetJointsNode_BoneInPath(IntPtr context, IntPtr node, float boneSize);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxSetJointsNode_Generic(IntPtr context, IntPtr node);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxPrepareMaterials(IntPtr context, int materialCount, int textureCount);\n\n        private static IntPtr AsFbxCreateTexture(IntPtr context, string matTexName)\n        {\n            using (var matTexNameUtf8 = new Utf8StringHandle(matTexName))\n            {\n                return AsFbxCreateTexture(context, matTexNameUtf8.DangerousGetHandle());\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxCreateTexture(IntPtr context, IntPtr strMatTexName);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxLinkTexture(int dest, IntPtr texture, IntPtr material, float offsetX, float offsetY, float scaleX, float scaleY);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxMeshCreateClusterArray(int boneCount);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshDisposeClusterArray(ref IntPtr ppArray);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxMeshCreateCluster(IntPtr context, IntPtr boneNode);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshAddCluster(IntPtr array, IntPtr cluster);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxMeshCreateMesh(IntPtr context, IntPtr frameNode);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshInitControlPoints(IntPtr mesh, int vertexCount);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshCreateElementNormal(IntPtr mesh);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshCreateDiffuseUV(IntPtr mesh, int uv);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshCreateNormalMapUV(IntPtr mesh, int uv);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshCreateElementTangent(IntPtr mesh);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshCreateElementVertexColor(IntPtr mesh);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshCreateElementMaterial(IntPtr mesh);\n\n        private static IntPtr AsFbxCreateMaterial(IntPtr pContext, string matName, in Color diffuse, in Color ambient, in Color emissive, in Color specular, in Color reflection, float shininess, float transparency)\n        {\n            using (var matNameUtf8 = new Utf8StringHandle(matName))\n            {\n                return AsFbxCreateMaterial(pContext, matNameUtf8.DangerousGetHandle(), diffuse.R, diffuse.G, diffuse.B, ambient.R, ambient.G, ambient.B, emissive.R, emissive.G, emissive.B, specular.R, specular.G, specular.B, reflection.R, reflection.G, reflection.B, shininess, transparency);\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxCreateMaterial(IntPtr pContext, IntPtr pMatName,\n            float diffuseR, float diffuseG, float diffuseB,\n            float ambientR, float ambientG, float ambientB,\n            float emissiveR, float emissiveG, float emissiveB,\n            float specularR, float specularG, float specularB,\n            float reflectR, float reflectG, float reflectB,\n            float shininess, float transparency);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern int AsFbxAddMaterialToFrame(IntPtr frameNode, IntPtr material);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxSetFrameShadingModeToTextureShading(IntPtr frameNode);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshSetControlPoint(IntPtr mesh, int index, float x, float y, float z);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshAddPolygon(IntPtr mesh, int materialIndex, int index0, int index1, int index2);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshElementNormalAdd(IntPtr mesh, int elementIndex, float x, float y, float z);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshElementUVAdd(IntPtr mesh, int elementIndex, float u, float v);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshElementTangentAdd(IntPtr mesh, int elementIndex, float x, float y, float z, float w);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshElementVertexColorAdd(IntPtr mesh, int elementIndex, float r, float g, float b, float a);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshSetBoneWeight(IntPtr pClusterArray, int boneIndex, int vertexIndex, float weight);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxMeshCreateSkinContext(IntPtr context, IntPtr frameNode);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshDisposeSkinContext(ref IntPtr ppSkinContext);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool FbxClusterArray_HasItemAt(IntPtr pClusterArray, int index);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private unsafe static extern void AsFbxMeshSkinAddCluster(IntPtr pSkinContext, IntPtr pClusterArray, int index, float* pBoneMatrix);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMeshAddDeformer(IntPtr pSkinContext, IntPtr pMesh);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxAnimCreateContext([MarshalAs(UnmanagedType.Bool)] bool eulerFilter);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimDisposeContext(ref IntPtr ppAnimContext);\n\n        private static void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, string takeName)\n        {\n            using (var takeNameUtf8 = new Utf8StringHandle(takeName))\n            {\n                AsFbxAnimPrepareStackAndLayer(pContext, pAnimContext, takeNameUtf8.DangerousGetHandle());\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, IntPtr strTakeName);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimLoadCurves(IntPtr pNode, IntPtr pAnimContext);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimBeginKeyModify(IntPtr pAnimContext);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimEndKeyModify(IntPtr pAnimContext);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimAddScalingKey(IntPtr pAnimContext, float time, float x, float y, float z);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimAddRotationKey(IntPtr pAnimContext, float time, float x, float y, float z);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimAddTranslationKey(IntPtr pAnimContext, float time, float x, float y, float z);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimApplyEulerFilter(IntPtr pAnimContext, float filterPrecision);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern int AsFbxAnimGetCurrentBlendShapeChannelCount(IntPtr pAnimContext, IntPtr pNode);\n\n        private static bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, string channelName)\n        {\n            using (var channelNameUtf8 = new Utf8StringHandle(channelName))\n            {\n                return AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, channelNameUtf8.DangerousGetHandle());\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, IntPtr strChannelName);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimBeginBlendShapeAnimCurve(IntPtr pAnimContext, int channelIndex);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimEndBlendShapeAnimCurve(IntPtr pAnimContext);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxAnimAddBlendShapeKeyframe(IntPtr pAnimContext, float time, float value);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern IntPtr AsFbxMorphCreateContext();\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphInitializeContext(IntPtr pContext, IntPtr pMorphContext, IntPtr pNode);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphDisposeContext(ref IntPtr ppMorphContext);\n\n        private static void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, string channelName)\n        {\n            using (var channelNameUtf8 = new Utf8StringHandle(channelName))\n            {\n                AsFbxMorphAddBlendShapeChannel(pContext, pMorphContext, channelNameUtf8.DangerousGetHandle());\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, IntPtr strChannelName);\n\n        private static void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, string shapeName)\n        {\n            using (var shapeNameUtf8 = new Utf8StringHandle(shapeName))\n            {\n                AsFbxMorphAddBlendShapeChannelShape(pContext, pMorphContext, weight, shapeNameUtf8.DangerousGetHandle());\n            }\n        }\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, IntPtr strShapeName);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphCopyBlendShapeControlPoints(IntPtr pMorphContext);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphSetBlendShapeVertex(IntPtr pMorphContext, uint index, float x, float y, float z);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphCopyBlendShapeControlPointsNormal(IntPtr pMorphContext);\n\n        [DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void AsFbxMorphSetBlendShapeVertexNormal(IntPtr pMorphContext, uint index, float x, float y, float z);\n\n    }\n}\n"
  },
  {
    "path": "AssetStudioFBXWrapper/FbxExporterContext.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Runtime.CompilerServices;\n\nnamespace AssetStudio.FbxInterop\n{\n    internal sealed partial class FbxExporterContext : IDisposable\n    {\n\n        private IntPtr _pContext;\n        private readonly Dictionary<ImportedFrame, IntPtr> _frameToNode;\n        private readonly List<KeyValuePair<string, IntPtr>> _createdMaterials;\n        private readonly Dictionary<string, IntPtr> _createdTextures;\n\n        public FbxExporterContext()\n        {\n            _pContext = AsFbxCreateContext();\n            _frameToNode = new Dictionary<ImportedFrame, IntPtr>();\n            _createdMaterials = new List<KeyValuePair<string, IntPtr>>();\n            _createdTextures = new Dictionary<string, IntPtr>();\n        }\n\n        ~FbxExporterContext()\n        {\n            Dispose(false);\n        }\n\n        public void Dispose()\n        {\n            if (IsDisposed)\n            {\n                return;\n            }\n\n            Dispose(true);\n            GC.SuppressFinalize(this);\n        }\n\n        public bool IsDisposed { get; private set; }\n\n        private void Dispose(bool disposing)\n        {\n            IsDisposed = true;\n\n            _frameToNode.Clear();\n            _createdMaterials.Clear();\n            _createdTextures.Clear();\n\n            AsFbxDisposeContext(ref _pContext);\n        }\n\n        private void EnsureNotDisposed()\n        {\n            if (IsDisposed)\n            {\n                throw new ObjectDisposedException(nameof(FbxExporterContext));\n            }\n        }\n\n        internal void Initialize(string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps)\n        {\n            EnsureNotDisposed();\n\n            var b = AsFbxInitializeContext(_pContext, fileName, scaleFactor, versionIndex, isAscii, is60Fps, out var errorMessage);\n\n            if (!b)\n            {\n                var fullMessage = $\"Failed to initialize FbxExporter: {errorMessage}\";\n                throw new ApplicationException(fullMessage);\n            }\n        }\n\n        internal void SetFramePaths(HashSet<string> framePaths)\n        {\n            EnsureNotDisposed();\n\n            if (framePaths == null || framePaths.Count == 0)\n            {\n                return;\n            }\n\n            var framePathList = new List<string>(framePaths);\n            var framePathArray = framePathList.ToArray();\n\n            AsFbxSetFramePaths(_pContext, framePathArray);\n        }\n\n        internal void ExportScene()\n        {\n            EnsureNotDisposed();\n\n            AsFbxExportScene(_pContext);\n        }\n\n        internal void ExportFrame(List<ImportedMesh> meshList, List<ImportedFrame> meshFrames, ImportedFrame rootFrame)\n        {\n            var rootNode = AsFbxGetSceneRootNode(_pContext);\n\n            Debug.Assert(rootNode != IntPtr.Zero);\n\n            var nodeStack = new Stack<IntPtr>();\n            var frameStack = new Stack<ImportedFrame>();\n\n            nodeStack.Push(rootNode);\n            frameStack.Push(rootFrame);\n\n            while (nodeStack.Count > 0)\n            {\n                var parentNode = nodeStack.Pop();\n                var frame = frameStack.Pop();\n\n                var childNode = AsFbxExportSingleFrame(_pContext, parentNode, frame.Path, frame.Name, frame.LocalPosition, frame.LocalRotation, frame.LocalScale);\n\n                if (meshList != null && ImportedHelpers.FindMesh(frame.Path, meshList) != null)\n                {\n                    meshFrames.Add(frame);\n                }\n\n                _frameToNode.Add(frame, childNode);\n\n                for (var i = frame.Count - 1; i >= 0; i -= 1)\n                {\n                    nodeStack.Push(childNode);\n                    frameStack.Push(frame[i]);\n                }\n            }\n        }\n\n        internal void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone, float boneSize)\n        {\n            var frameStack = new Stack<ImportedFrame>();\n\n            frameStack.Push(rootFrame);\n\n            while (frameStack.Count > 0)\n            {\n                var frame = frameStack.Pop();\n\n                if (_frameToNode.TryGetValue(frame, out var node))\n                {\n                    Debug.Assert(node != IntPtr.Zero);\n\n                    if (castToBone)\n                    {\n                        AsFbxSetJointsNode_CastToBone(_pContext, node, boneSize);\n                    }\n                    else\n                    {\n                        Debug.Assert(bonePaths != null);\n\n                        if (bonePaths.Contains(frame.Path))\n                        {\n                            AsFbxSetJointsNode_BoneInPath(_pContext, node, boneSize);\n                        }\n                        else\n                        {\n                            AsFbxSetJointsNode_Generic(_pContext, node);\n                        }\n                    }\n                }\n\n                for (var i = frame.Count - 1; i >= 0; i -= 1)\n                {\n                    frameStack.Push(frame[i]);\n                }\n            }\n        }\n\n        internal void PrepareMaterials(int materialCount, int textureCount)\n        {\n            AsFbxPrepareMaterials(_pContext, materialCount, textureCount);\n        }\n\n        internal void ExportMeshFromFrame(ImportedFrame rootFrame, ImportedFrame meshFrame, List<ImportedMesh> meshList, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, bool exportSkins, bool exportAllUvsAsDiffuseMaps)\n        {\n            var meshNode = _frameToNode[meshFrame];\n            var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList);\n\n            ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins, exportAllUvsAsDiffuseMaps);\n        }\n\n        private IntPtr ExportTexture(ImportedTexture texture)\n        {\n            if (texture == null)\n            {\n                return IntPtr.Zero;\n            }\n\n            if (_createdTextures.ContainsKey(texture.Name))\n            {\n                return _createdTextures[texture.Name];\n            }\n\n            var pTex = AsFbxCreateTexture(_pContext, texture.Name);\n\n            _createdTextures.Add(texture.Name, pTex);\n\n            var file = new FileInfo(texture.Name);\n\n            using (var writer = new BinaryWriter(file.Create()))\n            {\n                writer.Write(texture.Data);\n            }\n\n            return pTex;\n        }\n\n        private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins, bool exportAllUvsAsDiffuseMaps)\n        {\n            var boneList = importedMesh.BoneList;\n            var totalBoneCount = 0;\n            var hasBones = false;\n            if (exportSkins && boneList?.Count > 0)\n            {\n                totalBoneCount = boneList.Count;\n                hasBones = true;\n            }\n\n            var pClusterArray = IntPtr.Zero;\n\n            try\n            {\n                if (hasBones)\n                {\n                    pClusterArray = AsFbxMeshCreateClusterArray(totalBoneCount);\n\n                    foreach (var bone in boneList)\n                    {\n                        if (bone.Path != null)\n                        {\n                            var frame = rootFrame.FindFrameByPath(bone.Path);\n                            var boneNode = _frameToNode[frame];\n\n                            var cluster = AsFbxMeshCreateCluster(_pContext, boneNode);\n\n                            AsFbxMeshAddCluster(pClusterArray, cluster);\n                        }\n                        else\n                        {\n                            AsFbxMeshAddCluster(pClusterArray, IntPtr.Zero);\n                        }\n                    }\n                }\n\n                var mesh = AsFbxMeshCreateMesh(_pContext, frameNode);\n\n                AsFbxMeshInitControlPoints(mesh, importedMesh.VertexList.Count);\n\n                if (importedMesh.hasNormal)\n                {\n                    AsFbxMeshCreateElementNormal(mesh);\n                }\n\n                for (int i = 0; i < importedMesh.hasUV.Length; i++)\n                {\n                    if (!importedMesh.hasUV[i]) { continue; }\n\n                    if (i == 1 && !exportAllUvsAsDiffuseMaps)\n                    {\n                        AsFbxMeshCreateNormalMapUV(mesh, 1);\n                    }\n                    else\n                    {\n                        AsFbxMeshCreateDiffuseUV(mesh, i);\n                    }\n                }\n\n                if (importedMesh.hasTangent)\n                {\n                    AsFbxMeshCreateElementTangent(mesh);\n                }\n\n                if (importedMesh.hasColor)\n                {\n                    AsFbxMeshCreateElementVertexColor(mesh);\n                }\n\n                AsFbxMeshCreateElementMaterial(mesh);\n\n                foreach (var meshObj in importedMesh.SubmeshList)\n                {\n                    var materialIndex = 0;\n                    var mat = ImportedHelpers.FindMaterial(meshObj.Material, materialList);\n\n                    if (mat != null)\n                    {\n                        var foundMat = _createdMaterials.FindIndex(kv => kv.Key == mat.Name);\n                        IntPtr pMat;\n\n                        if (foundMat >= 0)\n                        {\n                            pMat = _createdMaterials[foundMat].Value;\n                        }\n                        else\n                        {\n                            var diffuse = mat.Diffuse;\n                            var ambient = mat.Ambient;\n                            var emissive = mat.Emissive;\n                            var specular = mat.Specular;\n                            var reflection = mat.Reflection;\n\n                            pMat = AsFbxCreateMaterial(_pContext, mat.Name, in diffuse, in ambient, in emissive, in specular, in reflection, mat.Shininess, mat.Transparency);\n\n                            _createdMaterials.Add(new KeyValuePair<string, IntPtr>(mat.Name, pMat));\n                        }\n\n                        materialIndex = AsFbxAddMaterialToFrame(frameNode, pMat);\n\n                        var hasTexture = false;\n\n                        foreach (var texture in mat.Textures)\n                        {\n                            var tex = ImportedHelpers.FindTexture(texture.Name, textureList);\n                            var pTexture = ExportTexture(tex);\n\n                            if (pTexture != IntPtr.Zero)\n                            {\n                                switch (texture.Dest)\n                                {\n                                    case 0:\n                                    case 1:\n                                    case 2:\n                                    case 3:\n                                        {\n                                            AsFbxLinkTexture(texture.Dest, pTexture, pMat, texture.Offset.X, texture.Offset.Y, texture.Scale.X, texture.Scale.Y);\n                                            hasTexture = true;\n                                            break;\n                                        }\n                                    default:\n                                        break;\n                                }\n                            }\n                        }\n\n                        if (hasTexture)\n                        {\n                            AsFbxSetFrameShadingModeToTextureShading(frameNode);\n                        }\n                    }\n\n                    foreach (var face in meshObj.FaceList)\n                    {\n                        var index0 = face.VertexIndices[0] + meshObj.BaseVertex;\n                        var index1 = face.VertexIndices[1] + meshObj.BaseVertex;\n                        var index2 = face.VertexIndices[2] + meshObj.BaseVertex;\n\n                        AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2);\n                    }\n                }\n\n                var vertexList = importedMesh.VertexList;\n\n                var vertexCount = vertexList.Count;\n\n                for (var j = 0; j < vertexCount; j += 1)\n                {\n                    var importedVertex = vertexList[j];\n\n                    var vertex = importedVertex.Vertex;\n                    AsFbxMeshSetControlPoint(mesh, j, vertex.X, vertex.Y, vertex.Z);\n\n                    if (importedMesh.hasNormal)\n                    {\n                        var normal = importedVertex.Normal;\n                        AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z);\n                    }\n\n                    for (var uvIndex = 0; uvIndex < importedMesh.hasUV.Length; uvIndex += 1)\n                    {\n                        if (importedMesh.hasUV[uvIndex])\n                        {\n                            var uv = importedVertex.UV[uvIndex];\n                            AsFbxMeshElementUVAdd(mesh, uvIndex, uv[0], uv[1]);\n                        }\n                    }\n\n                    if (importedMesh.hasTangent)\n                    {\n                        var tangent = importedVertex.Tangent;\n                        AsFbxMeshElementTangentAdd(mesh, 0, tangent.X, tangent.Y, tangent.Z, tangent.W);\n                    }\n\n                    if (importedMesh.hasColor)\n                    {\n                        var color = importedVertex.Color;\n                        AsFbxMeshElementVertexColorAdd(mesh, 0, color.R, color.G, color.B, color.A);\n                    }\n\n                    if (hasBones && importedVertex.BoneIndices != null)\n                    {\n                        var boneIndices = importedVertex.BoneIndices;\n                        var boneWeights = importedVertex.Weights;\n\n                        for (var k = 0; k < 4; k += 1)\n                        {\n                            if (boneIndices[k] < totalBoneCount && boneWeights[k] > 0)\n                            {\n                                AsFbxMeshSetBoneWeight(pClusterArray, boneIndices[k], j, boneWeights[k]);\n                            }\n                        }\n                    }\n                }\n\n\n                if (hasBones)\n                {\n                    IntPtr pSkinContext = IntPtr.Zero;\n\n                    try\n                    {\n                        pSkinContext = AsFbxMeshCreateSkinContext(_pContext, frameNode);\n\n                        unsafe\n                        {\n                            var boneMatrix = stackalloc float[16];\n\n                            for (var j = 0; j < totalBoneCount; j += 1)\n                            {\n                                if (!FbxClusterArray_HasItemAt(pClusterArray, j))\n                                {\n                                    continue;\n                                }\n\n                                var m = boneList[j].Matrix;\n\n                                CopyMatrix4x4(in m, boneMatrix);\n\n                                AsFbxMeshSkinAddCluster(pSkinContext, pClusterArray, j, boneMatrix);\n                            }\n                        }\n\n                        AsFbxMeshAddDeformer(pSkinContext, mesh);\n                    }\n                    finally\n                    {\n                        AsFbxMeshDisposeSkinContext(ref pSkinContext);\n                    }\n                }\n            }\n            finally\n            {\n                AsFbxMeshDisposeClusterArray(ref pClusterArray);\n            }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static unsafe void CopyMatrix4x4(in Matrix4x4 matrix, float* buffer)\n        {\n            for (var m = 0; m < 4; m += 1)\n            {\n                for (var n = 0; n < 4; n += 1)\n                {\n                    var index = IndexFrom4x4(m, n);\n                    buffer[index] = matrix[m, n];\n                }\n            }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static int IndexFrom4x4(int m, int n)\n        {\n            return 4 * m + n;\n        }\n\n        internal void ExportAnimations(ImportedFrame rootFrame, List<ImportedKeyframedAnimation> animationList, bool eulerFilter, float filterPrecision)\n        {\n            if (animationList == null || animationList.Count == 0)\n            {\n                return;\n            }\n\n            var pAnimContext = IntPtr.Zero;\n\n            try\n            {\n                pAnimContext = AsFbxAnimCreateContext(eulerFilter);\n\n                for (int i = 0; i < animationList.Count; i++)\n                {\n                    var importedAnimation = animationList[i];\n                    string takeName;\n\n                    if (importedAnimation.Name != null)\n                    {\n                        takeName = importedAnimation.Name;\n                    }\n                    else\n                    {\n                        takeName = $\"Take{i.ToString()}\";\n                    }\n\n                    AsFbxAnimPrepareStackAndLayer(_pContext, pAnimContext, takeName);\n\n                    ExportKeyframedAnimation(rootFrame, importedAnimation, pAnimContext, filterPrecision);\n                }\n            }\n            finally\n            {\n                AsFbxAnimDisposeContext(ref pAnimContext);\n            }\n        }\n\n        private void ExportKeyframedAnimation(ImportedFrame rootFrame, ImportedKeyframedAnimation parser, IntPtr pAnimContext, float filterPrecision)\n        {\n            foreach (var track in parser.TrackList)\n            {\n                if (track.Path == null)\n                {\n                    continue;\n                }\n\n                var frame = rootFrame.FindFrameByPath(track.Path);\n\n                if (frame == null)\n                {\n                    continue;\n                }\n\n                var pNode = _frameToNode[frame];\n\n                AsFbxAnimLoadCurves(pNode, pAnimContext);\n\n                AsFbxAnimBeginKeyModify(pAnimContext);\n\n                foreach (var scaling in track.Scalings)\n                {\n                    var value = scaling.value;\n                    AsFbxAnimAddScalingKey(pAnimContext, scaling.time, value.X, value.Y, value.Z);\n                }\n\n                foreach (var rotation in track.Rotations)\n                {\n                    var value = rotation.value;\n                    AsFbxAnimAddRotationKey(pAnimContext, rotation.time, value.X, value.Y, value.Z);\n                }\n\n                foreach (var translation in track.Translations)\n                {\n                    var value = translation.value;\n                    AsFbxAnimAddTranslationKey(pAnimContext, translation.time, value.X, value.Y, value.Z);\n                }\n\n                AsFbxAnimEndKeyModify(pAnimContext);\n\n                AsFbxAnimApplyEulerFilter(pAnimContext, filterPrecision);\n\n                var blendShape = track.BlendShape;\n\n                if (blendShape != null)\n                {\n                    var channelCount = AsFbxAnimGetCurrentBlendShapeChannelCount(pAnimContext, pNode);\n\n                    if (channelCount > 0)\n                    {\n                        for (var channelIndex = 0; channelIndex < channelCount; channelIndex += 1)\n                        {\n                            if (!AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, blendShape.ChannelName))\n                            {\n                                continue;\n                            }\n\n                            AsFbxAnimBeginBlendShapeAnimCurve(pAnimContext, channelIndex);\n\n                            foreach (var keyframe in blendShape.Keyframes)\n                            {\n                                AsFbxAnimAddBlendShapeKeyframe(pAnimContext, keyframe.time, keyframe.value);\n                            }\n\n                            AsFbxAnimEndBlendShapeAnimCurve(pAnimContext);\n                        }\n                    }\n                }\n            }\n        }\n\n        internal void ExportMorphs(ImportedFrame rootFrame, List<ImportedMorph> morphList)\n        {\n            if (morphList == null || morphList.Count == 0)\n            {\n                return;\n            }\n\n            foreach (var morph in morphList)\n            {\n                var frame = rootFrame.FindFrameByPath(morph.Path);\n\n                if (frame == null)\n                {\n                    continue;\n                }\n\n                var pNode = _frameToNode[frame];\n\n                var pMorphContext = IntPtr.Zero;\n\n                try\n                {\n                    pMorphContext = AsFbxMorphCreateContext();\n\n                    AsFbxMorphInitializeContext(_pContext, pMorphContext, pNode);\n\n                    foreach (var channel in morph.Channels)\n                    {\n                        AsFbxMorphAddBlendShapeChannel(_pContext, pMorphContext, channel.Name);\n\n                        for (var i = 0; i < channel.KeyframeList.Count; i++)\n                        {\n                            var keyframe = channel.KeyframeList[i];\n\n                            AsFbxMorphAddBlendShapeChannelShape(_pContext, pMorphContext, keyframe.Weight, i == 0 ? channel.Name : $\"{channel.Name}_{i + 1}\");\n\n                            AsFbxMorphCopyBlendShapeControlPoints(pMorphContext);\n\n                            foreach (var vertex in keyframe.VertexList)\n                            {\n                                var v = vertex.Vertex.Vertex;\n                                AsFbxMorphSetBlendShapeVertex(pMorphContext, vertex.Index, v.X, v.Y, v.Z);\n                            }\n\n                            if (keyframe.hasNormals)\n                            {\n                                AsFbxMorphCopyBlendShapeControlPointsNormal(pMorphContext);\n\n                                foreach (var vertex in keyframe.VertexList)\n                                {\n                                    var v = vertex.Vertex.Normal;\n                                    AsFbxMorphSetBlendShapeVertexNormal(pMorphContext, vertex.Index, v.X, v.Y, v.Z);\n                                }\n                            }\n                        }\n                    }\n                }\n                finally\n                {\n                    AsFbxMorphDisposeContext(ref pMorphContext);\n                }\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/AssetStudioGUI.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>WinExe</OutputType>\n\t\t<TargetFrameworks>net472;net5.0-windows;net6.0-windows</TargetFrameworks>\n\t\t<UseWindowsForms>true</UseWindowsForms>\n\t\t<ApplicationIcon>Resources\\as.ico</ApplicationIcon>\n\t\t<Version>0.16.0.0</Version>\n\t\t<AssemblyVersion>0.16.0.0</AssemblyVersion>\n\t\t<FileVersion>0.16.0.0</FileVersion>\n\t\t<Copyright>Copyright © Perfare 2018-2022</Copyright>\n\t\t<DebugType>embedded</DebugType>\n\t</PropertyGroup>\n\n\t<ItemGroup>\n\t\t<ProjectReference Include=\"..\\AssetStudioUtility\\AssetStudioUtility.csproj\" />\n\t\t<ProjectReference Include=\"..\\AssetStudio\\AssetStudio.csproj\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<None Include=\"Properties\\Settings.settings\">\n\t\t\t<Generator>SettingsSingleFileGenerator</Generator>\n\t\t\t<LastGenOutput>Settings.Designer.cs</LastGenOutput>\n\t\t</None>\n\t\t<Compile Update=\"Properties\\Settings.Designer.cs\">\n\t\t\t<AutoGen>True</AutoGen>\n\t\t\t<DependentUpon>Settings.settings</DependentUpon>\n\t\t\t<DesignTimeSharedInput>True</DesignTimeSharedInput>\n\t\t</Compile>\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<EmbeddedResource Update=\"Properties\\Resources.resx\">\n\t\t\t<Generator>ResXFileCodeGenerator</Generator>\n\t\t\t<LastGenOutput>Resources.Designer.cs</LastGenOutput>\n\t\t</EmbeddedResource>\n\t\t<Compile Update=\"Properties\\Resources.Designer.cs\">\n\t\t\t<AutoGen>True</AutoGen>\n\t\t\t<DependentUpon>Resources.resx</DependentUpon>\n\t\t\t<DesignTime>True</DesignTime>\n\t\t</Compile>\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<ContentWithTargetPath Include=\"Libraries\\x86\\fmod.dll\">\n\t\t\t<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n\t\t\t<TargetPath>x86\\fmod.dll</TargetPath>\n\t\t</ContentWithTargetPath>\n\t\t<ContentWithTargetPath Include=\"Libraries\\x64\\fmod.dll\">\n\t\t\t<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n\t\t\t<TargetPath>x64\\fmod.dll</TargetPath>\n\t\t</ContentWithTargetPath>\n\t</ItemGroup>\n\n\t<ItemGroup Condition=\" '$(TargetFramework)' != 'net472' \">\n\t\t<PackageReference Include=\"OpenTK\" Version=\"4.6.7\" />\n\t\t<Reference Include=\"OpenTK.WinForms\">\n\t\t\t<HintPath>Libraries\\OpenTK.WinForms.dll</HintPath>\n\t\t</Reference>\n\t</ItemGroup>\n\n\t<ItemGroup Condition=\" '$(TargetFramework)' == 'net472' \">\n\t\t<PackageReference Include=\"OpenTK\" Version=\"3.1.0\" />\n\t\t<PackageReference Include=\"OpenTK.GLControl\" Version=\"3.1.0\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<PackageReference Include=\"Newtonsoft.Json\" Version=\"13.0.1\" />\n\t</ItemGroup>\n\n\t<Target Name=\"CopyExtraFiles\" AfterTargets=\"AfterBuild\">\n\t\t<Copy SourceFiles=\"$(SolutionDir)AssetStudioFBXNative\\bin\\Win32\\$(Configuration)\\AssetStudioFBXNative.dll\" DestinationFolder=\"$(TargetDir)x86\" ContinueOnError=\"true\" />\n\t\t<Copy SourceFiles=\"$(SolutionDir)AssetStudioFBXNative\\bin\\x64\\$(Configuration)\\AssetStudioFBXNative.dll\" DestinationFolder=\"$(TargetDir)x64\" ContinueOnError=\"true\" />\n\t\t<Copy SourceFiles=\"$(SolutionDir)Texture2DDecoderNative\\bin\\Win32\\$(Configuration)\\Texture2DDecoderNative.dll\" DestinationFolder=\"$(TargetDir)x86\" ContinueOnError=\"true\" />\n\t\t<Copy SourceFiles=\"$(SolutionDir)Texture2DDecoderNative\\bin\\x64\\$(Configuration)\\Texture2DDecoderNative.dll\" DestinationFolder=\"$(TargetDir)x64\" ContinueOnError=\"true\" />\n\t</Target>\n\n\t<Target Name=\"PublishExtraFiles\" AfterTargets=\"Publish\">\n\t\t<Copy SourceFiles=\"$(TargetDir)x86\\AssetStudioFBXNative.dll\" DestinationFolder=\"$(PublishDir)x86\" ContinueOnError=\"true\" />\n\t\t<Copy SourceFiles=\"$(TargetDir)x64\\AssetStudioFBXNative.dll\" DestinationFolder=\"$(PublishDir)x64\" ContinueOnError=\"true\" />\n\t\t<Copy SourceFiles=\"$(TargetDir)x86\\Texture2DDecoderNative.dll\" DestinationFolder=\"$(PublishDir)x86\" ContinueOnError=\"true\" />\n\t\t<Copy SourceFiles=\"$(TargetDir)x64\\Texture2DDecoderNative.dll\" DestinationFolder=\"$(PublishDir)x64\" ContinueOnError=\"true\" />\n\t</Target>\n</Project>"
  },
  {
    "path": "AssetStudioGUI/AssetStudioGUIForm.Designer.cs",
    "content": "﻿namespace AssetStudioGUI\n{\n    partial class AssetStudioGUIForm\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.components = new System.ComponentModel.Container();\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AssetStudioGUIForm));\n            this.menuStrip1 = new System.Windows.Forms.MenuStrip();\n            this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.loadFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.loadFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();\n            this.extractFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.extractFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.displayAll = new System.Windows.Forms.ToolStripMenuItem();\n            this.enablePreview = new System.Windows.Forms.ToolStripMenuItem();\n            this.displayInfo = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem();\n            this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox();\n            this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem();\n            this.modelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportAllObjectssplitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportSelectedObjectsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportSelectedObjectsWithAnimationClipToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();\n            this.exportSelectedObjectsmergeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportAllAssetsMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportSelectedAssetsMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportFilteredAssetsMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();\n            this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();\n            this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();\n            this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem13 = new System.Windows.Forms.ToolStripMenuItem();\n            this.filterTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.allToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.splitContainer1 = new System.Windows.Forms.SplitContainer();\n            this.tabControl1 = new System.Windows.Forms.TabControl();\n            this.tabPage1 = new System.Windows.Forms.TabPage();\n            this.sceneTreeView = new AssetStudioGUI.GOHierarchy();\n            this.treeSearch = new System.Windows.Forms.TextBox();\n            this.tabPage2 = new System.Windows.Forms.TabPage();\n            this.assetListView = new System.Windows.Forms.ListView();\n            this.columnHeaderName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.columnHeaderContainer = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.columnHeaderPathID = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.columnHeaderSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.listSearch = new System.Windows.Forms.TextBox();\n            this.tabPage3 = new System.Windows.Forms.TabPage();\n            this.classesListView = new System.Windows.Forms.ListView();\n            this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\n            this.progressbarPanel = new System.Windows.Forms.Panel();\n            this.progressBar1 = new System.Windows.Forms.ProgressBar();\n            this.tabControl2 = new System.Windows.Forms.TabControl();\n            this.tabPage4 = new System.Windows.Forms.TabPage();\n            this.previewPanel = new System.Windows.Forms.Panel();\n            this.assetInfoLabel = new System.Windows.Forms.Label();\n            this.FMODpanel = new System.Windows.Forms.Panel();\n            this.FMODcopyright = new System.Windows.Forms.Label();\n            this.FMODinfoLabel = new System.Windows.Forms.Label();\n            this.FMODtimerLabel = new System.Windows.Forms.Label();\n            this.FMODstatusLabel = new System.Windows.Forms.Label();\n            this.FMODprogressBar = new System.Windows.Forms.TrackBar();\n            this.FMODvolumeBar = new System.Windows.Forms.TrackBar();\n            this.FMODloopButton = new System.Windows.Forms.CheckBox();\n            this.FMODstopButton = new System.Windows.Forms.Button();\n            this.FMODpauseButton = new System.Windows.Forms.Button();\n            this.FMODplayButton = new System.Windows.Forms.Button();\n            this.fontPreviewBox = new System.Windows.Forms.RichTextBox();\n            this.glControl1 = new OpenTK.GLControl();\n            this.textPreviewBox = new System.Windows.Forms.TextBox();\n            this.classTextBox = new System.Windows.Forms.TextBox();\n            this.tabPage5 = new System.Windows.Forms.TabPage();\n            this.dumpTextBox = new System.Windows.Forms.TextBox();\n            this.statusStrip1 = new System.Windows.Forms.StatusStrip();\n            this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();\n            this.timer = new System.Windows.Forms.Timer(this.components);\n            this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();\n            this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);\n            this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.exportAnimatorwithselectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            this.menuStrip1.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();\n            this.splitContainer1.Panel1.SuspendLayout();\n            this.splitContainer1.Panel2.SuspendLayout();\n            this.splitContainer1.SuspendLayout();\n            this.tabControl1.SuspendLayout();\n            this.tabPage1.SuspendLayout();\n            this.tabPage2.SuspendLayout();\n            this.tabPage3.SuspendLayout();\n            this.progressbarPanel.SuspendLayout();\n            this.tabControl2.SuspendLayout();\n            this.tabPage4.SuspendLayout();\n            this.previewPanel.SuspendLayout();\n            this.FMODpanel.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.FMODprogressBar)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.FMODvolumeBar)).BeginInit();\n            this.tabPage5.SuspendLayout();\n            this.statusStrip1.SuspendLayout();\n            this.contextMenuStrip1.SuspendLayout();\n            this.SuspendLayout();\n            // \n            // menuStrip1\n            // \n            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.fileToolStripMenuItem,\n            this.optionsToolStripMenuItem,\n            this.modelToolStripMenuItem,\n            this.exportToolStripMenuItem,\n            this.filterTypeToolStripMenuItem,\n            this.debugMenuItem});\n            this.menuStrip1.Location = new System.Drawing.Point(0, 0);\n            this.menuStrip1.Name = \"menuStrip1\";\n            this.menuStrip1.Size = new System.Drawing.Size(1264, 25);\n            this.menuStrip1.TabIndex = 0;\n            this.menuStrip1.Text = \"menuStrip1\";\n            // \n            // fileToolStripMenuItem\n            // \n            this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.loadFileToolStripMenuItem,\n            this.loadFolderToolStripMenuItem,\n            this.toolStripMenuItem1,\n            this.extractFileToolStripMenuItem,\n            this.extractFolderToolStripMenuItem});\n            this.fileToolStripMenuItem.Name = \"fileToolStripMenuItem\";\n            this.fileToolStripMenuItem.Size = new System.Drawing.Size(39, 21);\n            this.fileToolStripMenuItem.Text = \"File\";\n            // \n            // loadFileToolStripMenuItem\n            // \n            this.loadFileToolStripMenuItem.Name = \"loadFileToolStripMenuItem\";\n            this.loadFileToolStripMenuItem.Size = new System.Drawing.Size(154, 22);\n            this.loadFileToolStripMenuItem.Text = \"Load file\";\n            this.loadFileToolStripMenuItem.Click += new System.EventHandler(this.loadFile_Click);\n            // \n            // loadFolderToolStripMenuItem\n            // \n            this.loadFolderToolStripMenuItem.Name = \"loadFolderToolStripMenuItem\";\n            this.loadFolderToolStripMenuItem.Size = new System.Drawing.Size(154, 22);\n            this.loadFolderToolStripMenuItem.Text = \"Load folder\";\n            this.loadFolderToolStripMenuItem.Click += new System.EventHandler(this.loadFolder_Click);\n            // \n            // toolStripMenuItem1\n            // \n            this.toolStripMenuItem1.Name = \"toolStripMenuItem1\";\n            this.toolStripMenuItem1.Size = new System.Drawing.Size(151, 6);\n            // \n            // extractFileToolStripMenuItem\n            // \n            this.extractFileToolStripMenuItem.Name = \"extractFileToolStripMenuItem\";\n            this.extractFileToolStripMenuItem.Size = new System.Drawing.Size(154, 22);\n            this.extractFileToolStripMenuItem.Text = \"Extract file\";\n            this.extractFileToolStripMenuItem.Click += new System.EventHandler(this.extractFileToolStripMenuItem_Click);\n            // \n            // extractFolderToolStripMenuItem\n            // \n            this.extractFolderToolStripMenuItem.Name = \"extractFolderToolStripMenuItem\";\n            this.extractFolderToolStripMenuItem.Size = new System.Drawing.Size(154, 22);\n            this.extractFolderToolStripMenuItem.Text = \"Extract folder\";\n            this.extractFolderToolStripMenuItem.Click += new System.EventHandler(this.extractFolderToolStripMenuItem_Click);\n            // \n            // optionsToolStripMenuItem\n            // \n            this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.displayAll,\n            this.enablePreview,\n            this.displayInfo,\n            this.toolStripMenuItem14,\n            this.showExpOpt});\n            this.optionsToolStripMenuItem.Name = \"optionsToolStripMenuItem\";\n            this.optionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);\n            this.optionsToolStripMenuItem.Text = \"Options\";\n            // \n            // displayAll\n            // \n            this.displayAll.CheckOnClick = true;\n            this.displayAll.Name = \"displayAll\";\n            this.displayAll.Size = new System.Drawing.Size(223, 22);\n            this.displayAll.Text = \"Display all assets\";\n            this.displayAll.ToolTipText = \"Check this option will display all types assets. Not extractable assets can expor\" +\n    \"t the RAW file.\";\n            this.displayAll.CheckedChanged += new System.EventHandler(this.displayAll_CheckedChanged);\n            // \n            // enablePreview\n            // \n            this.enablePreview.Checked = true;\n            this.enablePreview.CheckOnClick = true;\n            this.enablePreview.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.enablePreview.Name = \"enablePreview\";\n            this.enablePreview.Size = new System.Drawing.Size(223, 22);\n            this.enablePreview.Text = \"Enable preview\";\n            this.enablePreview.ToolTipText = \"Toggle the loading and preview of readable assets, such as images, sounds, text, \" +\n    \"etc.\\r\\nDisable preview if you have performance or compatibility issues.\";\n            this.enablePreview.CheckedChanged += new System.EventHandler(this.enablePreview_Check);\n            // \n            // displayInfo\n            // \n            this.displayInfo.Checked = true;\n            this.displayInfo.CheckOnClick = true;\n            this.displayInfo.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.displayInfo.Name = \"displayInfo\";\n            this.displayInfo.Size = new System.Drawing.Size(223, 22);\n            this.displayInfo.Text = \"Display asset infromation\";\n            this.displayInfo.ToolTipText = \"Toggle the overlay that shows information about each asset, eg. image size, forma\" +\n    \"t, audio bitrate, etc.\";\n            this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check);\n            // \n            // toolStripMenuItem14\n            // \n            this.toolStripMenuItem14.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.specifyUnityVersion});\n            this.toolStripMenuItem14.Name = \"toolStripMenuItem14\";\n            this.toolStripMenuItem14.Size = new System.Drawing.Size(223, 22);\n            this.toolStripMenuItem14.Text = \"Specify Unity version\";\n            // \n            // specifyUnityVersion\n            // \n            this.specifyUnityVersion.Font = new System.Drawing.Font(\"Microsoft YaHei UI\", 9F);\n            this.specifyUnityVersion.Name = \"specifyUnityVersion\";\n            this.specifyUnityVersion.Size = new System.Drawing.Size(100, 23);\n            // \n            // showExpOpt\n            // \n            this.showExpOpt.Name = \"showExpOpt\";\n            this.showExpOpt.Size = new System.Drawing.Size(223, 22);\n            this.showExpOpt.Text = \"Export options\";\n            this.showExpOpt.Click += new System.EventHandler(this.showExpOpt_Click);\n            // \n            // modelToolStripMenuItem\n            // \n            this.modelToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.exportAllObjectssplitToolStripMenuItem1,\n            this.exportSelectedObjectsToolStripMenuItem,\n            this.exportSelectedObjectsWithAnimationClipToolStripMenuItem,\n            this.toolStripSeparator1,\n            this.exportSelectedObjectsmergeToolStripMenuItem,\n            this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem});\n            this.modelToolStripMenuItem.Name = \"modelToolStripMenuItem\";\n            this.modelToolStripMenuItem.Size = new System.Drawing.Size(58, 21);\n            this.modelToolStripMenuItem.Text = \"Model\";\n            // \n            // exportAllObjectssplitToolStripMenuItem1\n            // \n            this.exportAllObjectssplitToolStripMenuItem1.Name = \"exportAllObjectssplitToolStripMenuItem1\";\n            this.exportAllObjectssplitToolStripMenuItem1.Size = new System.Drawing.Size(417, 22);\n            this.exportAllObjectssplitToolStripMenuItem1.Text = \"Export all objects (split)\";\n            this.exportAllObjectssplitToolStripMenuItem1.Click += new System.EventHandler(this.exportAllObjectssplitToolStripMenuItem1_Click);\n            // \n            // exportSelectedObjectsToolStripMenuItem\n            // \n            this.exportSelectedObjectsToolStripMenuItem.Name = \"exportSelectedObjectsToolStripMenuItem\";\n            this.exportSelectedObjectsToolStripMenuItem.Size = new System.Drawing.Size(417, 22);\n            this.exportSelectedObjectsToolStripMenuItem.Text = \"Export selected objects (split)\";\n            this.exportSelectedObjectsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedObjectsToolStripMenuItem_Click);\n            // \n            // exportSelectedObjectsWithAnimationClipToolStripMenuItem\n            // \n            this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Name = \"exportSelectedObjectsWithAnimationClipToolStripMenuItem\";\n            this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(417, 22);\n            this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Text = \"Export selected objects (split) + selected AnimationClips\";\n            this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportObjectswithAnimationClipMenuItem_Click);\n            // \n            // toolStripSeparator1\n            // \n            this.toolStripSeparator1.Name = \"toolStripSeparator1\";\n            this.toolStripSeparator1.Size = new System.Drawing.Size(414, 6);\n            // \n            // exportSelectedObjectsmergeToolStripMenuItem\n            // \n            this.exportSelectedObjectsmergeToolStripMenuItem.Name = \"exportSelectedObjectsmergeToolStripMenuItem\";\n            this.exportSelectedObjectsmergeToolStripMenuItem.Size = new System.Drawing.Size(417, 22);\n            this.exportSelectedObjectsmergeToolStripMenuItem.Text = \"Export selected objects (merge)\";\n            this.exportSelectedObjectsmergeToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedObjectsmergeToolStripMenuItem_Click);\n            // \n            // exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem\n            // \n            this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Name = \"exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem\";\n            this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(417, 22);\n            this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Text = \"Export selected objects (merge) + selected AnimationClips\";\n            this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem_Click);\n            // \n            // exportToolStripMenuItem\n            // \n            this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.exportAllAssetsMenuItem,\n            this.exportSelectedAssetsMenuItem,\n            this.exportFilteredAssetsMenuItem,\n            this.toolStripSeparator3,\n            this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem,\n            this.toolStripSeparator4,\n            this.toolStripMenuItem2,\n            this.toolStripMenuItem3,\n            this.toolStripSeparator2,\n            this.toolStripMenuItem10});\n            this.exportToolStripMenuItem.Name = \"exportToolStripMenuItem\";\n            this.exportToolStripMenuItem.Size = new System.Drawing.Size(58, 21);\n            this.exportToolStripMenuItem.Text = \"Export\";\n            // \n            // exportAllAssetsMenuItem\n            // \n            this.exportAllAssetsMenuItem.Name = \"exportAllAssetsMenuItem\";\n            this.exportAllAssetsMenuItem.Size = new System.Drawing.Size(284, 22);\n            this.exportAllAssetsMenuItem.Text = \"All assets\";\n            this.exportAllAssetsMenuItem.Click += new System.EventHandler(this.exportAllAssetsMenuItem_Click);\n            // \n            // exportSelectedAssetsMenuItem\n            // \n            this.exportSelectedAssetsMenuItem.Name = \"exportSelectedAssetsMenuItem\";\n            this.exportSelectedAssetsMenuItem.Size = new System.Drawing.Size(284, 22);\n            this.exportSelectedAssetsMenuItem.Text = \"Selected assets\";\n            this.exportSelectedAssetsMenuItem.Click += new System.EventHandler(this.exportSelectedAssetsMenuItem_Click);\n            // \n            // exportFilteredAssetsMenuItem\n            // \n            this.exportFilteredAssetsMenuItem.Name = \"exportFilteredAssetsMenuItem\";\n            this.exportFilteredAssetsMenuItem.Size = new System.Drawing.Size(284, 22);\n            this.exportFilteredAssetsMenuItem.Text = \"Filtered assets\";\n            this.exportFilteredAssetsMenuItem.Click += new System.EventHandler(this.exportFilteredAssetsMenuItem_Click);\n            // \n            // toolStripSeparator3\n            // \n            this.toolStripSeparator3.Name = \"toolStripSeparator3\";\n            this.toolStripSeparator3.Size = new System.Drawing.Size(281, 6);\n            // \n            // exportAnimatorWithSelectedAnimationClipToolStripMenuItem\n            // \n            this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Name = \"exportAnimatorWithSelectedAnimationClipToolStripMenuItem\";\n            this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(284, 22);\n            this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Text = \"Animator + selected AnimationClips\";\n            this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportAnimatorwithAnimationClipMenuItem_Click);\n            // \n            // toolStripSeparator4\n            // \n            this.toolStripSeparator4.Name = \"toolStripSeparator4\";\n            this.toolStripSeparator4.Size = new System.Drawing.Size(281, 6);\n            // \n            // toolStripMenuItem2\n            // \n            this.toolStripMenuItem2.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.toolStripMenuItem4,\n            this.toolStripMenuItem5,\n            this.toolStripMenuItem6});\n            this.toolStripMenuItem2.Name = \"toolStripMenuItem2\";\n            this.toolStripMenuItem2.Size = new System.Drawing.Size(284, 22);\n            this.toolStripMenuItem2.Text = \"Raw\";\n            // \n            // toolStripMenuItem4\n            // \n            this.toolStripMenuItem4.Name = \"toolStripMenuItem4\";\n            this.toolStripMenuItem4.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem4.Text = \"All assets\";\n            this.toolStripMenuItem4.Click += new System.EventHandler(this.toolStripMenuItem4_Click);\n            // \n            // toolStripMenuItem5\n            // \n            this.toolStripMenuItem5.Name = \"toolStripMenuItem5\";\n            this.toolStripMenuItem5.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem5.Text = \"Selected assets\";\n            this.toolStripMenuItem5.Click += new System.EventHandler(this.toolStripMenuItem5_Click);\n            // \n            // toolStripMenuItem6\n            // \n            this.toolStripMenuItem6.Name = \"toolStripMenuItem6\";\n            this.toolStripMenuItem6.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem6.Text = \"Filtered assets\";\n            this.toolStripMenuItem6.Click += new System.EventHandler(this.toolStripMenuItem6_Click);\n            // \n            // toolStripMenuItem3\n            // \n            this.toolStripMenuItem3.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.toolStripMenuItem7,\n            this.toolStripMenuItem8,\n            this.toolStripMenuItem9});\n            this.toolStripMenuItem3.Name = \"toolStripMenuItem3\";\n            this.toolStripMenuItem3.Size = new System.Drawing.Size(284, 22);\n            this.toolStripMenuItem3.Text = \"Dump\";\n            // \n            // toolStripMenuItem7\n            // \n            this.toolStripMenuItem7.Name = \"toolStripMenuItem7\";\n            this.toolStripMenuItem7.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem7.Text = \"All assets\";\n            this.toolStripMenuItem7.Click += new System.EventHandler(this.toolStripMenuItem7_Click);\n            // \n            // toolStripMenuItem8\n            // \n            this.toolStripMenuItem8.Name = \"toolStripMenuItem8\";\n            this.toolStripMenuItem8.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem8.Text = \"Selected assets\";\n            this.toolStripMenuItem8.Click += new System.EventHandler(this.toolStripMenuItem8_Click);\n            // \n            // toolStripMenuItem9\n            // \n            this.toolStripMenuItem9.Name = \"toolStripMenuItem9\";\n            this.toolStripMenuItem9.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem9.Text = \"Filtered assets\";\n            this.toolStripMenuItem9.Click += new System.EventHandler(this.toolStripMenuItem9_Click);\n            // \n            // toolStripSeparator2\n            // \n            this.toolStripSeparator2.Name = \"toolStripSeparator2\";\n            this.toolStripSeparator2.Size = new System.Drawing.Size(281, 6);\n            // \n            // toolStripMenuItem10\n            // \n            this.toolStripMenuItem10.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.toolStripMenuItem11,\n            this.toolStripMenuItem12,\n            this.toolStripMenuItem13});\n            this.toolStripMenuItem10.Name = \"toolStripMenuItem10\";\n            this.toolStripMenuItem10.Size = new System.Drawing.Size(284, 22);\n            this.toolStripMenuItem10.Text = \"Asset list to XML\";\n            // \n            // toolStripMenuItem11\n            // \n            this.toolStripMenuItem11.Name = \"toolStripMenuItem11\";\n            this.toolStripMenuItem11.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem11.Text = \"All assets\";\n            this.toolStripMenuItem11.Click += new System.EventHandler(this.toolStripMenuItem11_Click);\n            // \n            // toolStripMenuItem12\n            // \n            this.toolStripMenuItem12.Name = \"toolStripMenuItem12\";\n            this.toolStripMenuItem12.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem12.Text = \"Selected assets\";\n            this.toolStripMenuItem12.Click += new System.EventHandler(this.toolStripMenuItem12_Click);\n            // \n            // toolStripMenuItem13\n            // \n            this.toolStripMenuItem13.Name = \"toolStripMenuItem13\";\n            this.toolStripMenuItem13.Size = new System.Drawing.Size(165, 22);\n            this.toolStripMenuItem13.Text = \"Filtered assets\";\n            this.toolStripMenuItem13.Click += new System.EventHandler(this.toolStripMenuItem13_Click);\n            // \n            // filterTypeToolStripMenuItem\n            // \n            this.filterTypeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.allToolStripMenuItem});\n            this.filterTypeToolStripMenuItem.Name = \"filterTypeToolStripMenuItem\";\n            this.filterTypeToolStripMenuItem.Size = new System.Drawing.Size(80, 21);\n            this.filterTypeToolStripMenuItem.Text = \"Filter Type\";\n            // \n            // allToolStripMenuItem\n            // \n            this.allToolStripMenuItem.Checked = true;\n            this.allToolStripMenuItem.CheckOnClick = true;\n            this.allToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.allToolStripMenuItem.Name = \"allToolStripMenuItem\";\n            this.allToolStripMenuItem.Size = new System.Drawing.Size(90, 22);\n            this.allToolStripMenuItem.Text = \"All\";\n            this.allToolStripMenuItem.Click += new System.EventHandler(this.typeToolStripMenuItem_Click);\n            // \n            // debugMenuItem\n            // \n            this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.toolStripMenuItem15,\n            this.exportClassStructuresMenuItem});\n            this.debugMenuItem.Name = \"debugMenuItem\";\n            this.debugMenuItem.Size = new System.Drawing.Size(59, 21);\n            this.debugMenuItem.Text = \"Debug\";\n            // \n            // toolStripMenuItem15\n            // \n            this.toolStripMenuItem15.Checked = true;\n            this.toolStripMenuItem15.CheckOnClick = true;\n            this.toolStripMenuItem15.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.toolStripMenuItem15.Name = \"toolStripMenuItem15\";\n            this.toolStripMenuItem15.Size = new System.Drawing.Size(207, 22);\n            this.toolStripMenuItem15.Text = \"Show error message\";\n            this.toolStripMenuItem15.Click += new System.EventHandler(this.toolStripMenuItem15_Click);\n            // \n            // exportClassStructuresMenuItem\n            // \n            this.exportClassStructuresMenuItem.Name = \"exportClassStructuresMenuItem\";\n            this.exportClassStructuresMenuItem.Size = new System.Drawing.Size(207, 22);\n            this.exportClassStructuresMenuItem.Text = \"Export class structures\";\n            this.exportClassStructuresMenuItem.Click += new System.EventHandler(this.exportClassStructuresMenuItem_Click);\n            // \n            // splitContainer1\n            // \n            this.splitContainer1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;\n            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.splitContainer1.Location = new System.Drawing.Point(0, 25);\n            this.splitContainer1.Name = \"splitContainer1\";\n            // \n            // splitContainer1.Panel1\n            // \n            this.splitContainer1.Panel1.Controls.Add(this.tabControl1);\n            this.splitContainer1.Panel1.Controls.Add(this.progressbarPanel);\n            this.splitContainer1.Panel1MinSize = 200;\n            // \n            // splitContainer1.Panel2\n            // \n            this.splitContainer1.Panel2.Controls.Add(this.tabControl2);\n            this.splitContainer1.Panel2.Controls.Add(this.statusStrip1);\n            this.splitContainer1.Panel2MinSize = 400;\n            this.splitContainer1.Size = new System.Drawing.Size(1264, 656);\n            this.splitContainer1.SplitterDistance = 482;\n            this.splitContainer1.TabIndex = 2;\n            this.splitContainer1.TabStop = false;\n            // \n            // tabControl1\n            // \n            this.tabControl1.Controls.Add(this.tabPage1);\n            this.tabControl1.Controls.Add(this.tabPage2);\n            this.tabControl1.Controls.Add(this.tabPage3);\n            this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tabControl1.Location = new System.Drawing.Point(0, 0);\n            this.tabControl1.Name = \"tabControl1\";\n            this.tabControl1.Padding = new System.Drawing.Point(17, 3);\n            this.tabControl1.SelectedIndex = 0;\n            this.tabControl1.Size = new System.Drawing.Size(480, 634);\n            this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;\n            this.tabControl1.TabIndex = 0;\n            this.tabControl1.Selected += new System.Windows.Forms.TabControlEventHandler(this.tabPageSelected);\n            // \n            // tabPage1\n            // \n            this.tabPage1.Controls.Add(this.sceneTreeView);\n            this.tabPage1.Controls.Add(this.treeSearch);\n            this.tabPage1.Location = new System.Drawing.Point(4, 22);\n            this.tabPage1.Name = \"tabPage1\";\n            this.tabPage1.Size = new System.Drawing.Size(472, 608);\n            this.tabPage1.TabIndex = 0;\n            this.tabPage1.Text = \"Scene Hierarchy\";\n            this.tabPage1.UseVisualStyleBackColor = true;\n            // \n            // sceneTreeView\n            // \n            this.sceneTreeView.CheckBoxes = true;\n            this.sceneTreeView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.sceneTreeView.HideSelection = false;\n            this.sceneTreeView.Location = new System.Drawing.Point(0, 21);\n            this.sceneTreeView.Name = \"sceneTreeView\";\n            this.sceneTreeView.Size = new System.Drawing.Size(472, 587);\n            this.sceneTreeView.TabIndex = 1;\n            this.sceneTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.sceneTreeView_AfterCheck);\n            // \n            // treeSearch\n            // \n            this.treeSearch.Dock = System.Windows.Forms.DockStyle.Top;\n            this.treeSearch.ForeColor = System.Drawing.SystemColors.GrayText;\n            this.treeSearch.Location = new System.Drawing.Point(0, 0);\n            this.treeSearch.Name = \"treeSearch\";\n            this.treeSearch.Size = new System.Drawing.Size(472, 21);\n            this.treeSearch.TabIndex = 0;\n            this.treeSearch.Text = \" Search \";\n            this.treeSearch.TextChanged += new System.EventHandler(this.treeSearch_TextChanged);\n            this.treeSearch.Enter += new System.EventHandler(this.treeSearch_Enter);\n            this.treeSearch.KeyDown += new System.Windows.Forms.KeyEventHandler(this.treeSearch_KeyDown);\n            this.treeSearch.Leave += new System.EventHandler(this.treeSearch_Leave);\n            // \n            // tabPage2\n            // \n            this.tabPage2.Controls.Add(this.assetListView);\n            this.tabPage2.Controls.Add(this.listSearch);\n            this.tabPage2.Location = new System.Drawing.Point(4, 22);\n            this.tabPage2.Name = \"tabPage2\";\n            this.tabPage2.Size = new System.Drawing.Size(472, 608);\n            this.tabPage2.TabIndex = 1;\n            this.tabPage2.Text = \"Asset List\";\n            this.tabPage2.UseVisualStyleBackColor = true;\n            // \n            // assetListView\n            // \n            this.assetListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {\n            this.columnHeaderName,\n            this.columnHeaderContainer,\n            this.columnHeaderType,\n            this.columnHeaderPathID,\n            this.columnHeaderSize});\n            this.assetListView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.assetListView.FullRowSelect = true;\n            this.assetListView.GridLines = true;\n            this.assetListView.HideSelection = false;\n            this.assetListView.Location = new System.Drawing.Point(0, 21);\n            this.assetListView.Name = \"assetListView\";\n            this.assetListView.Size = new System.Drawing.Size(472, 587);\n            this.assetListView.TabIndex = 1;\n            this.assetListView.UseCompatibleStateImageBehavior = false;\n            this.assetListView.View = System.Windows.Forms.View.Details;\n            this.assetListView.VirtualMode = true;\n            this.assetListView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.assetListView_ColumnClick);\n            this.assetListView.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.selectAsset);\n            this.assetListView.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.assetListView_RetrieveVirtualItem);\n            this.assetListView.MouseClick += new System.Windows.Forms.MouseEventHandler(this.assetListView_MouseClick);\n            // \n            // columnHeaderName\n            // \n            this.columnHeaderName.Text = \"Name\";\n            this.columnHeaderName.Width = 170;\n            // \n            // columnHeaderContainer\n            // \n            this.columnHeaderContainer.Text = \"Container\";\n            this.columnHeaderContainer.Width = 80;\n            // \n            // columnHeaderType\n            // \n            this.columnHeaderType.Text = \"Type\";\n            this.columnHeaderType.Width = 90;\n            // \n            // columnHeaderPathID\n            // \n            this.columnHeaderPathID.Text = \"PathID\";\n            // \n            // columnHeaderSize\n            // \n            this.columnHeaderSize.Text = \"Size\";\n            this.columnHeaderSize.Width = 50;\n            // \n            // listSearch\n            // \n            this.listSearch.Dock = System.Windows.Forms.DockStyle.Top;\n            this.listSearch.ForeColor = System.Drawing.SystemColors.GrayText;\n            this.listSearch.Location = new System.Drawing.Point(0, 0);\n            this.listSearch.Name = \"listSearch\";\n            this.listSearch.Size = new System.Drawing.Size(472, 21);\n            this.listSearch.TabIndex = 0;\n            this.listSearch.Text = \" Filter \";\n            this.listSearch.TextChanged += new System.EventHandler(this.ListSearchTextChanged);\n            this.listSearch.Enter += new System.EventHandler(this.listSearch_Enter);\n            this.listSearch.Leave += new System.EventHandler(this.listSearch_Leave);\n            // \n            // tabPage3\n            // \n            this.tabPage3.Controls.Add(this.classesListView);\n            this.tabPage3.Location = new System.Drawing.Point(4, 22);\n            this.tabPage3.Name = \"tabPage3\";\n            this.tabPage3.Size = new System.Drawing.Size(472, 608);\n            this.tabPage3.TabIndex = 2;\n            this.tabPage3.Text = \"Asset Classes\";\n            this.tabPage3.UseVisualStyleBackColor = true;\n            // \n            // classesListView\n            // \n            this.classesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {\n            this.columnHeader1,\n            this.columnHeader2});\n            this.classesListView.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.classesListView.FullRowSelect = true;\n            this.classesListView.HideSelection = false;\n            this.classesListView.Location = new System.Drawing.Point(0, 0);\n            this.classesListView.MultiSelect = false;\n            this.classesListView.Name = \"classesListView\";\n            this.classesListView.Size = new System.Drawing.Size(472, 608);\n            this.classesListView.TabIndex = 0;\n            this.classesListView.UseCompatibleStateImageBehavior = false;\n            this.classesListView.View = System.Windows.Forms.View.Details;\n            this.classesListView.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.classesListView_ItemSelectionChanged);\n            // \n            // columnHeader1\n            // \n            this.columnHeader1.DisplayIndex = 1;\n            this.columnHeader1.Text = \"Name\";\n            this.columnHeader1.Width = 300;\n            // \n            // columnHeader2\n            // \n            this.columnHeader2.DisplayIndex = 0;\n            this.columnHeader2.Text = \"ID\";\n            this.columnHeader2.Width = 70;\n            // \n            // progressbarPanel\n            // \n            this.progressbarPanel.Controls.Add(this.progressBar1);\n            this.progressbarPanel.Dock = System.Windows.Forms.DockStyle.Bottom;\n            this.progressbarPanel.Location = new System.Drawing.Point(0, 634);\n            this.progressbarPanel.Name = \"progressbarPanel\";\n            this.progressbarPanel.Padding = new System.Windows.Forms.Padding(1, 3, 1, 1);\n            this.progressbarPanel.Size = new System.Drawing.Size(480, 20);\n            this.progressbarPanel.TabIndex = 2;\n            // \n            // progressBar1\n            // \n            this.progressBar1.Dock = System.Windows.Forms.DockStyle.Bottom;\n            this.progressBar1.Location = new System.Drawing.Point(1, 2);\n            this.progressBar1.Name = \"progressBar1\";\n            this.progressBar1.Size = new System.Drawing.Size(478, 17);\n            this.progressBar1.Step = 1;\n            this.progressBar1.TabIndex = 1;\n            // \n            // tabControl2\n            // \n            this.tabControl2.Controls.Add(this.tabPage4);\n            this.tabControl2.Controls.Add(this.tabPage5);\n            this.tabControl2.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.tabControl2.Location = new System.Drawing.Point(0, 0);\n            this.tabControl2.Name = \"tabControl2\";\n            this.tabControl2.SelectedIndex = 0;\n            this.tabControl2.Size = new System.Drawing.Size(776, 632);\n            this.tabControl2.TabIndex = 4;\n            this.tabControl2.SelectedIndexChanged += new System.EventHandler(this.tabControl2_SelectedIndexChanged);\n            // \n            // tabPage4\n            // \n            this.tabPage4.Controls.Add(this.previewPanel);\n            this.tabPage4.Location = new System.Drawing.Point(4, 22);\n            this.tabPage4.Name = \"tabPage4\";\n            this.tabPage4.Size = new System.Drawing.Size(768, 606);\n            this.tabPage4.TabIndex = 0;\n            this.tabPage4.Text = \"Preview\";\n            this.tabPage4.UseVisualStyleBackColor = true;\n            // \n            // previewPanel\n            // \n            this.previewPanel.BackColor = System.Drawing.SystemColors.ControlDark;\n            this.previewPanel.BackgroundImage = global::AssetStudioGUI.Properties.Resources.preview;\n            this.previewPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;\n            this.previewPanel.Controls.Add(this.assetInfoLabel);\n            this.previewPanel.Controls.Add(this.FMODpanel);\n            this.previewPanel.Controls.Add(this.fontPreviewBox);\n            this.previewPanel.Controls.Add(this.glControl1);\n            this.previewPanel.Controls.Add(this.textPreviewBox);\n            this.previewPanel.Controls.Add(this.classTextBox);\n            this.previewPanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.previewPanel.Location = new System.Drawing.Point(0, 0);\n            this.previewPanel.Name = \"previewPanel\";\n            this.previewPanel.Size = new System.Drawing.Size(768, 606);\n            this.previewPanel.TabIndex = 1;\n            this.previewPanel.Resize += new System.EventHandler(this.preview_Resize);\n            // \n            // assetInfoLabel\n            // \n            this.assetInfoLabel.AutoSize = true;\n            this.assetInfoLabel.BackColor = System.Drawing.Color.Transparent;\n            this.assetInfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;\n            this.assetInfoLabel.Location = new System.Drawing.Point(4, 7);\n            this.assetInfoLabel.Name = \"assetInfoLabel\";\n            this.assetInfoLabel.Size = new System.Drawing.Size(0, 12);\n            this.assetInfoLabel.TabIndex = 0;\n            // \n            // FMODpanel\n            // \n            this.FMODpanel.BackColor = System.Drawing.SystemColors.ControlDark;\n            this.FMODpanel.Controls.Add(this.FMODcopyright);\n            this.FMODpanel.Controls.Add(this.FMODinfoLabel);\n            this.FMODpanel.Controls.Add(this.FMODtimerLabel);\n            this.FMODpanel.Controls.Add(this.FMODstatusLabel);\n            this.FMODpanel.Controls.Add(this.FMODprogressBar);\n            this.FMODpanel.Controls.Add(this.FMODvolumeBar);\n            this.FMODpanel.Controls.Add(this.FMODloopButton);\n            this.FMODpanel.Controls.Add(this.FMODstopButton);\n            this.FMODpanel.Controls.Add(this.FMODpauseButton);\n            this.FMODpanel.Controls.Add(this.FMODplayButton);\n            this.FMODpanel.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.FMODpanel.Location = new System.Drawing.Point(0, 0);\n            this.FMODpanel.Name = \"FMODpanel\";\n            this.FMODpanel.Size = new System.Drawing.Size(768, 606);\n            this.FMODpanel.TabIndex = 2;\n            this.FMODpanel.Visible = false;\n            // \n            // FMODcopyright\n            // \n            this.FMODcopyright.AutoSize = true;\n            this.FMODcopyright.ForeColor = System.Drawing.SystemColors.ControlLight;\n            this.FMODcopyright.Location = new System.Drawing.Point(214, 337);\n            this.FMODcopyright.Name = \"FMODcopyright\";\n            this.FMODcopyright.Size = new System.Drawing.Size(341, 12);\n            this.FMODcopyright.TabIndex = 9;\n            this.FMODcopyright.Text = \"Audio Engine supplied by FMOD by Firelight Technologies.\";\n            // \n            // FMODinfoLabel\n            // \n            this.FMODinfoLabel.AutoSize = true;\n            this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;\n            this.FMODinfoLabel.Location = new System.Drawing.Point(269, 235);\n            this.FMODinfoLabel.Name = \"FMODinfoLabel\";\n            this.FMODinfoLabel.Size = new System.Drawing.Size(0, 12);\n            this.FMODinfoLabel.TabIndex = 8;\n            // \n            // FMODtimerLabel\n            // \n            this.FMODtimerLabel.AutoSize = true;\n            this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;\n            this.FMODtimerLabel.Location = new System.Drawing.Point(460, 235);\n            this.FMODtimerLabel.Name = \"FMODtimerLabel\";\n            this.FMODtimerLabel.Size = new System.Drawing.Size(95, 12);\n            this.FMODtimerLabel.TabIndex = 7;\n            this.FMODtimerLabel.Text = \"0:00.0 / 0:00.0\";\n            // \n            // FMODstatusLabel\n            // \n            this.FMODstatusLabel.AutoSize = true;\n            this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;\n            this.FMODstatusLabel.Location = new System.Drawing.Point(213, 235);\n            this.FMODstatusLabel.Name = \"FMODstatusLabel\";\n            this.FMODstatusLabel.Size = new System.Drawing.Size(47, 12);\n            this.FMODstatusLabel.TabIndex = 6;\n            this.FMODstatusLabel.Text = \"Stopped\";\n            // \n            // FMODprogressBar\n            // \n            this.FMODprogressBar.AutoSize = false;\n            this.FMODprogressBar.Location = new System.Drawing.Point(213, 253);\n            this.FMODprogressBar.Maximum = 1000;\n            this.FMODprogressBar.Name = \"FMODprogressBar\";\n            this.FMODprogressBar.Size = new System.Drawing.Size(350, 22);\n            this.FMODprogressBar.TabIndex = 5;\n            this.FMODprogressBar.TickStyle = System.Windows.Forms.TickStyle.None;\n            this.FMODprogressBar.Scroll += new System.EventHandler(this.FMODprogressBar_Scroll);\n            this.FMODprogressBar.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FMODprogressBar_MouseDown);\n            this.FMODprogressBar.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FMODprogressBar_MouseUp);\n            // \n            // FMODvolumeBar\n            // \n            this.FMODvolumeBar.LargeChange = 2;\n            this.FMODvolumeBar.Location = new System.Drawing.Point(460, 280);\n            this.FMODvolumeBar.Name = \"FMODvolumeBar\";\n            this.FMODvolumeBar.Size = new System.Drawing.Size(104, 45);\n            this.FMODvolumeBar.TabIndex = 4;\n            this.FMODvolumeBar.TickStyle = System.Windows.Forms.TickStyle.Both;\n            this.FMODvolumeBar.Value = 8;\n            this.FMODvolumeBar.ValueChanged += new System.EventHandler(this.FMODvolumeBar_ValueChanged);\n            // \n            // FMODloopButton\n            // \n            this.FMODloopButton.Appearance = System.Windows.Forms.Appearance.Button;\n            this.FMODloopButton.Location = new System.Drawing.Point(399, 280);\n            this.FMODloopButton.Name = \"FMODloopButton\";\n            this.FMODloopButton.Size = new System.Drawing.Size(55, 42);\n            this.FMODloopButton.TabIndex = 3;\n            this.FMODloopButton.Text = \"Loop\";\n            this.FMODloopButton.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;\n            this.FMODloopButton.UseVisualStyleBackColor = true;\n            this.FMODloopButton.CheckedChanged += new System.EventHandler(this.FMODloopButton_CheckedChanged);\n            // \n            // FMODstopButton\n            // \n            this.FMODstopButton.Location = new System.Drawing.Point(338, 280);\n            this.FMODstopButton.Name = \"FMODstopButton\";\n            this.FMODstopButton.Size = new System.Drawing.Size(55, 42);\n            this.FMODstopButton.TabIndex = 2;\n            this.FMODstopButton.Text = \"Stop\";\n            this.FMODstopButton.UseVisualStyleBackColor = true;\n            this.FMODstopButton.Click += new System.EventHandler(this.FMODstopButton_Click);\n            // \n            // FMODpauseButton\n            // \n            this.FMODpauseButton.Location = new System.Drawing.Point(277, 280);\n            this.FMODpauseButton.Name = \"FMODpauseButton\";\n            this.FMODpauseButton.Size = new System.Drawing.Size(55, 42);\n            this.FMODpauseButton.TabIndex = 1;\n            this.FMODpauseButton.Text = \"Pause\";\n            this.FMODpauseButton.UseVisualStyleBackColor = true;\n            this.FMODpauseButton.Click += new System.EventHandler(this.FMODpauseButton_Click);\n            // \n            // FMODplayButton\n            // \n            this.FMODplayButton.Location = new System.Drawing.Point(216, 280);\n            this.FMODplayButton.Name = \"FMODplayButton\";\n            this.FMODplayButton.Size = new System.Drawing.Size(55, 42);\n            this.FMODplayButton.TabIndex = 0;\n            this.FMODplayButton.Text = \"Play\";\n            this.FMODplayButton.UseVisualStyleBackColor = true;\n            this.FMODplayButton.Click += new System.EventHandler(this.FMODplayButton_Click);\n            // \n            // fontPreviewBox\n            // \n            this.fontPreviewBox.BackColor = System.Drawing.SystemColors.ControlLightLight;\n            this.fontPreviewBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.fontPreviewBox.Location = new System.Drawing.Point(0, 0);\n            this.fontPreviewBox.Name = \"fontPreviewBox\";\n            this.fontPreviewBox.ReadOnly = true;\n            this.fontPreviewBox.Size = new System.Drawing.Size(768, 606);\n            this.fontPreviewBox.TabIndex = 0;\n            this.fontPreviewBox.Text = resources.GetString(\"fontPreviewBox.Text\");\n            this.fontPreviewBox.Visible = false;\n            this.fontPreviewBox.WordWrap = false;\n            // \n            // glControl1\n            // \n            this.glControl1.BackColor = System.Drawing.SystemColors.ControlDarkDark;\n            this.glControl1.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.glControl1.Location = new System.Drawing.Point(0, 0);\n            this.glControl1.Name = \"glControl1\";\n            this.glControl1.Size = new System.Drawing.Size(768, 606);\n            this.glControl1.TabIndex = 4;\n            this.glControl1.Visible = false;\n            this.glControl1.VSync = false;\n            this.glControl1.Load += new System.EventHandler(this.glControl1_Load);\n            this.glControl1.Paint += new System.Windows.Forms.PaintEventHandler(this.glControl1_Paint);\n            this.glControl1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseDown);\n            this.glControl1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseMove);\n            this.glControl1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseUp);\n            this.glControl1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseWheel);\n            // \n            // textPreviewBox\n            // \n            this.textPreviewBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.textPreviewBox.Font = new System.Drawing.Font(\"Consolas\", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));\n            this.textPreviewBox.Location = new System.Drawing.Point(0, 0);\n            this.textPreviewBox.Multiline = true;\n            this.textPreviewBox.Name = \"textPreviewBox\";\n            this.textPreviewBox.ReadOnly = true;\n            this.textPreviewBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;\n            this.textPreviewBox.Size = new System.Drawing.Size(768, 606);\n            this.textPreviewBox.TabIndex = 2;\n            this.textPreviewBox.Visible = false;\n            this.textPreviewBox.WordWrap = false;\n            // \n            // classTextBox\n            // \n            this.classTextBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.classTextBox.Location = new System.Drawing.Point(0, 0);\n            this.classTextBox.Multiline = true;\n            this.classTextBox.Name = \"classTextBox\";\n            this.classTextBox.ReadOnly = true;\n            this.classTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;\n            this.classTextBox.Size = new System.Drawing.Size(768, 606);\n            this.classTextBox.TabIndex = 3;\n            this.classTextBox.Visible = false;\n            this.classTextBox.WordWrap = false;\n            // \n            // tabPage5\n            // \n            this.tabPage5.Controls.Add(this.dumpTextBox);\n            this.tabPage5.Location = new System.Drawing.Point(4, 22);\n            this.tabPage5.Name = \"tabPage5\";\n            this.tabPage5.Size = new System.Drawing.Size(768, 606);\n            this.tabPage5.TabIndex = 1;\n            this.tabPage5.Text = \"Dump\";\n            this.tabPage5.UseVisualStyleBackColor = true;\n            // \n            // dumpTextBox\n            // \n            this.dumpTextBox.Dock = System.Windows.Forms.DockStyle.Fill;\n            this.dumpTextBox.Location = new System.Drawing.Point(0, 0);\n            this.dumpTextBox.Multiline = true;\n            this.dumpTextBox.Name = \"dumpTextBox\";\n            this.dumpTextBox.ReadOnly = true;\n            this.dumpTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;\n            this.dumpTextBox.Size = new System.Drawing.Size(768, 606);\n            this.dumpTextBox.TabIndex = 0;\n            this.dumpTextBox.WordWrap = false;\n            // \n            // statusStrip1\n            // \n            this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.toolStripStatusLabel1});\n            this.statusStrip1.Location = new System.Drawing.Point(0, 632);\n            this.statusStrip1.Name = \"statusStrip1\";\n            this.statusStrip1.Size = new System.Drawing.Size(776, 22);\n            this.statusStrip1.TabIndex = 2;\n            this.statusStrip1.Text = \"statusStrip1\";\n            // \n            // toolStripStatusLabel1\n            // \n            this.toolStripStatusLabel1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;\n            this.toolStripStatusLabel1.Name = \"toolStripStatusLabel1\";\n            this.toolStripStatusLabel1.Size = new System.Drawing.Size(761, 17);\n            this.toolStripStatusLabel1.Spring = true;\n            this.toolStripStatusLabel1.Text = \"Ready to go\";\n            this.toolStripStatusLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;\n            // \n            // timer\n            // \n            this.timer.Interval = 10;\n            this.timer.Tick += new System.EventHandler(this.timer_Tick);\n            // \n            // openFileDialog1\n            // \n            this.openFileDialog1.AddExtension = false;\n            this.openFileDialog1.Filter = \"All types|*.*\";\n            this.openFileDialog1.Multiselect = true;\n            this.openFileDialog1.RestoreDirectory = true;\n            // \n            // contextMenuStrip1\n            // \n            this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);\n            this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\n            this.copyToolStripMenuItem,\n            this.exportSelectedAssetsToolStripMenuItem,\n            this.exportAnimatorwithselectedAnimationClipMenuItem,\n            this.goToSceneHierarchyToolStripMenuItem,\n            this.showOriginalFileToolStripMenuItem});\n            this.contextMenuStrip1.Name = \"contextMenuStrip1\";\n            this.contextMenuStrip1.Size = new System.Drawing.Size(327, 114);\n            // \n            // copyToolStripMenuItem\n            // \n            this.copyToolStripMenuItem.Name = \"copyToolStripMenuItem\";\n            this.copyToolStripMenuItem.Size = new System.Drawing.Size(326, 22);\n            this.copyToolStripMenuItem.Text = \"Copy text\";\n            this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);\n            // \n            // exportSelectedAssetsToolStripMenuItem\n            // \n            this.exportSelectedAssetsToolStripMenuItem.Name = \"exportSelectedAssetsToolStripMenuItem\";\n            this.exportSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(326, 22);\n            this.exportSelectedAssetsToolStripMenuItem.Text = \"Export selected assets\";\n            this.exportSelectedAssetsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedAssetsToolStripMenuItem_Click);\n            // \n            // exportAnimatorwithselectedAnimationClipMenuItem\n            // \n            this.exportAnimatorwithselectedAnimationClipMenuItem.Name = \"exportAnimatorwithselectedAnimationClipMenuItem\";\n            this.exportAnimatorwithselectedAnimationClipMenuItem.Size = new System.Drawing.Size(326, 22);\n            this.exportAnimatorwithselectedAnimationClipMenuItem.Text = \"Export Animator + selected AnimationClips\";\n            this.exportAnimatorwithselectedAnimationClipMenuItem.Visible = false;\n            this.exportAnimatorwithselectedAnimationClipMenuItem.Click += new System.EventHandler(this.exportAnimatorwithAnimationClipMenuItem_Click);\n            // \n            // goToSceneHierarchyToolStripMenuItem\n            // \n            this.goToSceneHierarchyToolStripMenuItem.Name = \"goToSceneHierarchyToolStripMenuItem\";\n            this.goToSceneHierarchyToolStripMenuItem.Size = new System.Drawing.Size(326, 22);\n            this.goToSceneHierarchyToolStripMenuItem.Text = \"Go to scene hierarchy\";\n            this.goToSceneHierarchyToolStripMenuItem.Visible = false;\n            this.goToSceneHierarchyToolStripMenuItem.Click += new System.EventHandler(this.goToSceneHierarchyToolStripMenuItem_Click);\n            // \n            // showOriginalFileToolStripMenuItem\n            // \n            this.showOriginalFileToolStripMenuItem.Name = \"showOriginalFileToolStripMenuItem\";\n            this.showOriginalFileToolStripMenuItem.Size = new System.Drawing.Size(326, 22);\n            this.showOriginalFileToolStripMenuItem.Text = \"Show original file\";\n            this.showOriginalFileToolStripMenuItem.Visible = false;\n            this.showOriginalFileToolStripMenuItem.Click += new System.EventHandler(this.showOriginalFileToolStripMenuItem_Click);\n            // \n            // AssetStudioGUIForm\n            // \n            this.AllowDrop = true;\n            this.ClientSize = new System.Drawing.Size(1264, 681);\n            this.Controls.Add(this.splitContainer1);\n            this.Controls.Add(this.menuStrip1);\n            this.Icon = global::AssetStudioGUI.Properties.Resources._as;\n            this.KeyPreview = true;\n            this.MainMenuStrip = this.menuStrip1;\n            this.MinimumSize = new System.Drawing.Size(620, 372);\n            this.Name = \"AssetStudioGUIForm\";\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;\n            this.Text = \"AssetStudioGUI\";\n            this.DragDrop += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragDrop);\n            this.DragEnter += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragEnter);\n            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AssetStudioForm_KeyDown);\n            this.menuStrip1.ResumeLayout(false);\n            this.menuStrip1.PerformLayout();\n            this.splitContainer1.Panel1.ResumeLayout(false);\n            this.splitContainer1.Panel2.ResumeLayout(false);\n            this.splitContainer1.Panel2.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();\n            this.splitContainer1.ResumeLayout(false);\n            this.tabControl1.ResumeLayout(false);\n            this.tabPage1.ResumeLayout(false);\n            this.tabPage1.PerformLayout();\n            this.tabPage2.ResumeLayout(false);\n            this.tabPage2.PerformLayout();\n            this.tabPage3.ResumeLayout(false);\n            this.progressbarPanel.ResumeLayout(false);\n            this.tabControl2.ResumeLayout(false);\n            this.tabPage4.ResumeLayout(false);\n            this.previewPanel.ResumeLayout(false);\n            this.previewPanel.PerformLayout();\n            this.FMODpanel.ResumeLayout(false);\n            this.FMODpanel.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.FMODprogressBar)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.FMODvolumeBar)).EndInit();\n            this.tabPage5.ResumeLayout(false);\n            this.tabPage5.PerformLayout();\n            this.statusStrip1.ResumeLayout(false);\n            this.statusStrip1.PerformLayout();\n            this.contextMenuStrip1.ResumeLayout(false);\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n\n        private System.Windows.Forms.MenuStrip menuStrip1;\n        private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;\n        private System.Windows.Forms.SplitContainer splitContainer1;\n        private System.Windows.Forms.TabControl tabControl1;\n        private System.Windows.Forms.TabPage tabPage1;\n        private System.Windows.Forms.TabPage tabPage2;\n        private System.Windows.Forms.TextBox treeSearch;\n        private System.Windows.Forms.TextBox listSearch;\n        private System.Windows.Forms.ToolStripMenuItem loadFileToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem loadFolderToolStripMenuItem;\n        private System.Windows.Forms.ListView assetListView;\n        private System.Windows.Forms.ColumnHeader columnHeaderName;\n        private System.Windows.Forms.ColumnHeader columnHeaderSize;\n        private System.Windows.Forms.ColumnHeader columnHeaderType;\n        private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportAllAssetsMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportSelectedAssetsMenuItem;\n        private System.Windows.Forms.Panel previewPanel;\n        private System.Windows.Forms.ProgressBar progressBar1;\n        private System.Windows.Forms.StatusStrip statusStrip1;\n        private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;\n        private System.Windows.Forms.Panel progressbarPanel;\n        private System.Windows.Forms.ToolStripMenuItem exportFilteredAssetsMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem modelToolStripMenuItem;\n        private System.Windows.Forms.Label assetInfoLabel;\n        private System.Windows.Forms.TextBox textPreviewBox;\n        private System.Windows.Forms.RichTextBox fontPreviewBox;\n        private System.Windows.Forms.Panel FMODpanel;\n        private System.Windows.Forms.TrackBar FMODvolumeBar;\n        private System.Windows.Forms.CheckBox FMODloopButton;\n        private System.Windows.Forms.Button FMODstopButton;\n        private System.Windows.Forms.Button FMODpauseButton;\n        private System.Windows.Forms.Button FMODplayButton;\n        private System.Windows.Forms.TrackBar FMODprogressBar;\n        private System.Windows.Forms.Label FMODstatusLabel;\n        private System.Windows.Forms.Label FMODtimerLabel;\n        private System.Windows.Forms.Label FMODinfoLabel;\n        private System.Windows.Forms.Timer timer;\n        private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem displayAll;\n        private System.Windows.Forms.ToolStripMenuItem enablePreview;\n        private System.Windows.Forms.ToolStripMenuItem displayInfo;\n        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;\n        private System.Windows.Forms.ToolStripMenuItem extractFileToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem extractFolderToolStripMenuItem;\n        private System.Windows.Forms.OpenFileDialog openFileDialog1;\n        private System.Windows.Forms.ToolStripMenuItem showExpOpt;\n        private GOHierarchy sceneTreeView;\n        private System.Windows.Forms.ToolStripMenuItem debugMenuItem;\n        private System.Windows.Forms.TabPage tabPage3;\n        private System.Windows.Forms.ListView classesListView;\n        private System.Windows.Forms.ColumnHeader columnHeader2;\n        private System.Windows.Forms.ColumnHeader columnHeader1;\n        private System.Windows.Forms.TextBox classTextBox;\n        private System.Windows.Forms.ToolStripMenuItem exportClassStructuresMenuItem;\n        private System.Windows.Forms.Label FMODcopyright;\n        private OpenTK.GLControl glControl1;\n        private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;\n        private System.Windows.Forms.ToolStripMenuItem showOriginalFileToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportAnimatorwithselectedAnimationClipMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportSelectedAssetsToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem filterTypeToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem allToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportSelectedObjectsToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportSelectedObjectsWithAnimationClipToolStripMenuItem;\n        private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;\n        private System.Windows.Forms.ToolStripMenuItem exportAnimatorWithSelectedAnimationClipToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportAllObjectssplitToolStripMenuItem1;\n        private System.Windows.Forms.ToolStripMenuItem goToSceneHierarchyToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportSelectedObjectsmergeToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem;\n        private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;\n        private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem4;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem5;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem6;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem7;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem8;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem9;\n        private System.Windows.Forms.ColumnHeader columnHeaderContainer;\n        private System.Windows.Forms.ColumnHeader columnHeaderPathID;\n        private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem;\n        private System.Windows.Forms.TabControl tabControl2;\n        private System.Windows.Forms.TabPage tabPage4;\n        private System.Windows.Forms.TabPage tabPage5;\n        private System.Windows.Forms.TextBox dumpTextBox;\n        private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem10;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem12;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem13;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem14;\n        private System.Windows.Forms.ToolStripTextBox specifyUnityVersion;\n        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15;\n    }\n}\n\n"
  },
  {
    "path": "AssetStudioGUI/AssetStudioGUIForm.cs",
    "content": "﻿using AssetStudio;\nusing Newtonsoft.Json;\nusing OpenTK;\nusing OpenTK.Graphics.OpenGL;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Drawing.Text;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Timers;\nusing System.Windows.Forms;\nusing static AssetStudioGUI.Studio;\nusing Font = AssetStudio.Font;\n#if NET472\nusing Vector3 = OpenTK.Vector3;\nusing Vector4 = OpenTK.Vector4;\n#else\nusing Vector3 = OpenTK.Mathematics.Vector3;\nusing Vector4 = OpenTK.Mathematics.Vector4;\nusing Matrix4 = OpenTK.Mathematics.Matrix4;\n#endif\n\nnamespace AssetStudioGUI\n{\n    partial class AssetStudioGUIForm : Form\n    {\n        private AssetItem lastSelectedItem;\n        private DirectBitmap imageTexture;\n        private string tempClipboard;\n\n        private FMOD.System system;\n        private FMOD.Sound sound;\n        private FMOD.Channel channel;\n        private FMOD.SoundGroup masterSoundGroup;\n        private FMOD.MODE loopMode = FMOD.MODE.LOOP_OFF;\n        private uint FMODlenms;\n        private float FMODVolume = 0.8f;\n\n        #region TexControl\n        private static char[] textureChannelNames = new[] { 'B', 'G', 'R', 'A' };\n        private bool[] textureChannels = new[] { true, true, true, true };\n        #endregion\n\n        #region GLControl\n        private bool glControlLoaded;\n        private int mdx, mdy;\n        private bool lmdown, rmdown;\n        private int pgmID, pgmColorID, pgmBlackID;\n        private int attributeVertexPosition;\n        private int attributeNormalDirection;\n        private int attributeVertexColor;\n        private int uniformModelMatrix;\n        private int uniformViewMatrix;\n        private int uniformProjMatrix;\n        private int vao;\n        private Vector3[] vertexData;\n        private Vector3[] normalData;\n        private Vector3[] normal2Data;\n        private Vector4[] colorData;\n        private Matrix4 modelMatrixData;\n        private Matrix4 viewMatrixData;\n        private Matrix4 projMatrixData;\n        private int[] indiceData;\n        private int wireFrameMode;\n        private int shadeMode;\n        private int normalMode;\n        #endregion\n\n        //asset list sorting\n        private int sortColumn = -1;\n        private bool reverseSort;\n\n        //asset list filter\n        private System.Timers.Timer delayTimer;\n        private bool enableFiltering;\n\n        //tree search\n        private int nextGObject;\n        private List<TreeNode> treeSrcResults = new List<TreeNode>();\n\n        private string openDirectoryBackup = string.Empty;\n        private string saveDirectoryBackup = string.Empty;\n\n        private GUILogger logger;\n\n        [DllImport(\"gdi32.dll\")]\n        private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);\n\n        public AssetStudioGUIForm()\n        {\n            Thread.CurrentThread.CurrentCulture = new CultureInfo(\"en-US\");\n            InitializeComponent();\n            Text = $\"AssetStudioGUI v{Application.ProductVersion}\";\n            delayTimer = new System.Timers.Timer(800);\n            delayTimer.Elapsed += new ElapsedEventHandler(delayTimer_Elapsed);\n            displayAll.Checked = Properties.Settings.Default.displayAll;\n            displayInfo.Checked = Properties.Settings.Default.displayInfo;\n            enablePreview.Checked = Properties.Settings.Default.enablePreview;\n            FMODinit();\n\n            logger = new GUILogger(StatusStripUpdate);\n            Logger.Default = logger;\n            Progress.Default = new Progress<int>(SetProgressBarValue);\n            Studio.StatusStripUpdate = StatusStripUpdate;\n        }\n\n        private void AssetStudioGUIForm_DragEnter(object sender, DragEventArgs e)\n        {\n            if (e.Data.GetDataPresent(DataFormats.FileDrop))\n            {\n                e.Effect = DragDropEffects.Move;\n            }\n        }\n\n        private async void AssetStudioGUIForm_DragDrop(object sender, DragEventArgs e)\n        {\n            var paths = (string[])e.Data.GetData(DataFormats.FileDrop);\n            if (paths.Length > 0)\n            {\n                ResetForm();\n                assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;\n                if (paths.Length == 1 && Directory.Exists(paths[0]))\n                {\n                    await Task.Run(() => assetsManager.LoadFolder(paths[0]));\n                }\n                else\n                {\n                    await Task.Run(() => assetsManager.LoadFiles(paths));\n                }\n                BuildAssetStructures();\n            }\n        }\n\n        private async void loadFile_Click(object sender, EventArgs e)\n        {\n            openFileDialog1.InitialDirectory = openDirectoryBackup;\n            if (openFileDialog1.ShowDialog(this) == DialogResult.OK)\n            {\n                ResetForm();\n                openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]);\n                assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;\n                await Task.Run(() => assetsManager.LoadFiles(openFileDialog1.FileNames));\n                BuildAssetStructures();\n            }\n        }\n\n        private async void loadFolder_Click(object sender, EventArgs e)\n        {\n            var openFolderDialog = new OpenFolderDialog();\n            openFolderDialog.InitialFolder = openDirectoryBackup;\n            if (openFolderDialog.ShowDialog(this) == DialogResult.OK)\n            {\n                ResetForm();\n                openDirectoryBackup = openFolderDialog.Folder;\n                assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;\n                await Task.Run(() => assetsManager.LoadFolder(openFolderDialog.Folder));\n                BuildAssetStructures();\n            }\n        }\n\n        private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            if (openFileDialog1.ShowDialog(this) == DialogResult.OK)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                saveFolderDialog.Title = \"Select the save folder\";\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    var fileNames = openFileDialog1.FileNames;\n                    var savePath = saveFolderDialog.Folder;\n                    var extractedCount = await Task.Run(() => ExtractFile(fileNames, savePath));\n                    StatusStripUpdate($\"Finished extracting {extractedCount} files.\");\n                }\n            }\n        }\n\n        private async void extractFolderToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            var openFolderDialog = new OpenFolderDialog();\n            if (openFolderDialog.ShowDialog(this) == DialogResult.OK)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                saveFolderDialog.Title = \"Select the save folder\";\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    var path = openFolderDialog.Folder;\n                    var savePath = saveFolderDialog.Folder;\n                    var extractedCount = await Task.Run(() => ExtractFolder(path, savePath));\n                    StatusStripUpdate($\"Finished extracting {extractedCount} files.\");\n                }\n            }\n        }\n\n        private async void BuildAssetStructures()\n        {\n            if (assetsManager.assetsFileList.Count == 0)\n            {\n                StatusStripUpdate(\"No Unity file can be loaded.\");\n                return;\n            }\n\n            (var productName, var treeNodeCollection) = await Task.Run(() => BuildAssetData());\n            var typeMap = await Task.Run(() => BuildClassStructure());\n\n            if (!string.IsNullOrEmpty(productName))\n            {\n                Text = $\"AssetStudioGUI v{Application.ProductVersion} - {productName} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}\";\n            }\n            else\n            {\n                Text = $\"AssetStudioGUI v{Application.ProductVersion} - no productName - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}\";\n            }\n\n            assetListView.VirtualListSize = visibleAssets.Count;\n\n            sceneTreeView.BeginUpdate();\n            sceneTreeView.Nodes.AddRange(treeNodeCollection.ToArray());\n            sceneTreeView.EndUpdate();\n            treeNodeCollection.Clear();\n\n            classesListView.BeginUpdate();\n            foreach (var version in typeMap)\n            {\n                var versionGroup = new ListViewGroup(version.Key);\n                classesListView.Groups.Add(versionGroup);\n\n                foreach (var uclass in version.Value)\n                {\n                    uclass.Value.Group = versionGroup;\n                    classesListView.Items.Add(uclass.Value);\n                }\n            }\n            typeMap.Clear();\n            classesListView.EndUpdate();\n\n            var types = exportableAssets.Select(x => x.Type).Distinct().OrderBy(x => x.ToString()).ToArray();\n            foreach (var type in types)\n            {\n                var typeItem = new ToolStripMenuItem\n                {\n                    CheckOnClick = true,\n                    Name = type.ToString(),\n                    Size = new Size(180, 22),\n                    Text = type.ToString()\n                };\n                typeItem.Click += typeToolStripMenuItem_Click;\n                filterTypeToolStripMenuItem.DropDownItems.Add(typeItem);\n            }\n            allToolStripMenuItem.Checked = true;\n            var log = $\"Finished loading {assetsManager.assetsFileList.Count} files with {assetListView.Items.Count} exportable assets\";\n            var m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.Count);\n            var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);\n            if (m_ObjectsCount != objectsCount)\n            {\n                log += $\" and {m_ObjectsCount - objectsCount} assets failed to read\";\n            }\n            StatusStripUpdate(log);\n        }\n\n        private void typeToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            var typeItem = (ToolStripMenuItem)sender;\n            if (typeItem != allToolStripMenuItem)\n            {\n                allToolStripMenuItem.Checked = false;\n            }\n            else if (allToolStripMenuItem.Checked)\n            {\n                for (var i = 1; i < filterTypeToolStripMenuItem.DropDownItems.Count; i++)\n                {\n                    var item = (ToolStripMenuItem)filterTypeToolStripMenuItem.DropDownItems[i];\n                    item.Checked = false;\n                }\n            }\n            FilterAssetList();\n        }\n\n        private void AssetStudioForm_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (glControl1.Visible)\n            {\n                if (e.Control)\n                {\n                    switch (e.KeyCode)\n                    {\n                        case Keys.W:\n                            //Toggle WireFrame\n                            wireFrameMode = (wireFrameMode + 1) % 3;\n                            glControl1.Invalidate();\n                            break;\n                        case Keys.S:\n                            //Toggle Shade\n                            shadeMode = (shadeMode + 1) % 2;\n                            glControl1.Invalidate();\n                            break;\n                        case Keys.N:\n                            //Normal mode\n                            normalMode = (normalMode + 1) % 2;\n                            CreateVAO();\n                            glControl1.Invalidate();\n                            break;\n                    }\n                }\n            }\n            else if (previewPanel.Visible)\n            {\n                if (e.Control)\n                {\n                    var need = false;\n                    switch (e.KeyCode)\n                    {\n                        case Keys.B:\n                            textureChannels[0] = !textureChannels[0];\n                            need = true;\n                            break;\n                        case Keys.G:\n                            textureChannels[1] = !textureChannels[1];\n                            need = true;\n                            break;\n                        case Keys.R:\n                            textureChannels[2] = !textureChannels[2];\n                            need = true;\n                            break;\n                        case Keys.A:\n                            textureChannels[3] = !textureChannels[3];\n                            need = true;\n                            break;\n                    }\n                    if (need)\n                    {\n                        if (lastSelectedItem != null)\n                        {\n                            PreviewAsset(lastSelectedItem);\n                            assetInfoLabel.Text = lastSelectedItem.InfoText;\n                        }\n                    }\n                }\n            }\n        }\n\n        private void exportClassStructuresMenuItem_Click(object sender, EventArgs e)\n        {\n            if (classesListView.Items.Count > 0)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    var savePath = saveFolderDialog.Folder;\n                    var count = classesListView.Items.Count;\n                    int i = 0;\n                    Progress.Reset();\n                    foreach (TypeTreeItem item in classesListView.Items)\n                    {\n                        var versionPath = Path.Combine(savePath, item.Group.Header);\n                        Directory.CreateDirectory(versionPath);\n\n                        var saveFile = $\"{versionPath}{Path.DirectorySeparatorChar}{item.SubItems[1].Text} {item.Text}.txt\";\n                        File.WriteAllText(saveFile, item.ToString());\n\n                        Progress.Report(++i, count);\n                    }\n\n                    StatusStripUpdate(\"Finished exporting class structures\");\n                }\n            }\n        }\n\n        private void displayAll_CheckedChanged(object sender, EventArgs e)\n        {\n            Properties.Settings.Default.displayAll = displayAll.Checked;\n            Properties.Settings.Default.Save();\n        }\n\n        private void enablePreview_Check(object sender, EventArgs e)\n        {\n            if (lastSelectedItem != null)\n            {\n                switch (lastSelectedItem.Type)\n                {\n                    case ClassIDType.Texture2D:\n                    case ClassIDType.Sprite:\n                        {\n                            if (enablePreview.Checked && imageTexture != null)\n                            {\n                                previewPanel.BackgroundImage = imageTexture.Bitmap;\n                            }\n                            else\n                            {\n                                previewPanel.BackgroundImage = Properties.Resources.preview;\n                                previewPanel.BackgroundImageLayout = ImageLayout.Center;\n                            }\n                        }\n                        break;\n                    case ClassIDType.Shader:\n                    case ClassIDType.TextAsset:\n                    case ClassIDType.MonoBehaviour:\n                        textPreviewBox.Visible = !textPreviewBox.Visible;\n                        break;\n                    case ClassIDType.Font:\n                        fontPreviewBox.Visible = !fontPreviewBox.Visible;\n                        break;\n                    case ClassIDType.AudioClip:\n                        {\n                            FMODpanel.Visible = !FMODpanel.Visible;\n\n                            if (sound != null && channel != null)\n                            {\n                                var result = channel.isPlaying(out var playing);\n                                if (result == FMOD.RESULT.OK && playing)\n                                {\n                                    channel.stop();\n                                    FMODreset();\n                                }\n                            }\n                            else if (FMODpanel.Visible)\n                            {\n                                PreviewAsset(lastSelectedItem);\n                            }\n\n                            break;\n                        }\n\n                }\n\n            }\n            else if (lastSelectedItem != null && enablePreview.Checked)\n            {\n                PreviewAsset(lastSelectedItem);\n            }\n\n            Properties.Settings.Default.enablePreview = enablePreview.Checked;\n            Properties.Settings.Default.Save();\n        }\n\n        private void displayAssetInfo_Check(object sender, EventArgs e)\n        {\n            if (displayInfo.Checked && assetInfoLabel.Text != null)\n            {\n                assetInfoLabel.Visible = true;\n            }\n            else\n            {\n                assetInfoLabel.Visible = false;\n            }\n\n            Properties.Settings.Default.displayInfo = displayInfo.Checked;\n            Properties.Settings.Default.Save();\n        }\n\n        private void showExpOpt_Click(object sender, EventArgs e)\n        {\n            var exportOpt = new ExportOptions();\n            exportOpt.ShowDialog(this);\n        }\n\n        private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)\n        {\n            e.Item = visibleAssets[e.ItemIndex];\n        }\n\n        private void tabPageSelected(object sender, TabControlEventArgs e)\n        {\n            switch (e.TabPageIndex)\n            {\n                case 0:\n                    treeSearch.Select();\n                    break;\n                case 1:\n                    listSearch.Select();\n                    break;\n            }\n        }\n\n        private void treeSearch_Enter(object sender, EventArgs e)\n        {\n            if (treeSearch.Text == \" Search \")\n            {\n                treeSearch.Text = \"\";\n                treeSearch.ForeColor = SystemColors.WindowText;\n            }\n        }\n\n        private void treeSearch_Leave(object sender, EventArgs e)\n        {\n            if (treeSearch.Text == \"\")\n            {\n                treeSearch.Text = \" Search \";\n                treeSearch.ForeColor = SystemColors.GrayText;\n            }\n        }\n\n        private void treeSearch_TextChanged(object sender, EventArgs e)\n        {\n            treeSrcResults.Clear();\n            nextGObject = 0;\n        }\n\n        private void treeSearch_KeyDown(object sender, KeyEventArgs e)\n        {\n            if (e.KeyCode == Keys.Enter)\n            {\n                if (treeSrcResults.Count == 0)\n                {\n                    foreach (TreeNode node in sceneTreeView.Nodes)\n                    {\n                        TreeNodeSearch(node);\n                    }\n                }\n                if (treeSrcResults.Count > 0)\n                {\n                    if (nextGObject >= treeSrcResults.Count)\n                    {\n                        nextGObject = 0;\n                    }\n                    treeSrcResults[nextGObject].EnsureVisible();\n                    sceneTreeView.SelectedNode = treeSrcResults[nextGObject];\n                    nextGObject++;\n                }\n            }\n        }\n\n        private void TreeNodeSearch(TreeNode treeNode)\n        {\n            if (treeNode.Text.IndexOf(treeSearch.Text, StringComparison.OrdinalIgnoreCase) >= 0)\n            {\n                treeSrcResults.Add(treeNode);\n            }\n\n            foreach (TreeNode node in treeNode.Nodes)\n            {\n                TreeNodeSearch(node);\n            }\n        }\n\n        private void sceneTreeView_AfterCheck(object sender, TreeViewEventArgs e)\n        {\n            foreach (TreeNode childNode in e.Node.Nodes)\n            {\n                childNode.Checked = e.Node.Checked;\n            }\n        }\n\n        private void listSearch_Enter(object sender, EventArgs e)\n        {\n            if (listSearch.Text == \" Filter \")\n            {\n                listSearch.Text = \"\";\n                listSearch.ForeColor = SystemColors.WindowText;\n                enableFiltering = true;\n            }\n        }\n\n        private void listSearch_Leave(object sender, EventArgs e)\n        {\n            if (listSearch.Text == \"\")\n            {\n                enableFiltering = false;\n                listSearch.Text = \" Filter \";\n                listSearch.ForeColor = SystemColors.GrayText;\n            }\n        }\n\n        private void ListSearchTextChanged(object sender, EventArgs e)\n        {\n            if (enableFiltering)\n            {\n                if (delayTimer.Enabled)\n                {\n                    delayTimer.Stop();\n                    delayTimer.Start();\n                }\n                else\n                {\n                    delayTimer.Start();\n                }\n            }\n        }\n\n        private void delayTimer_Elapsed(object sender, ElapsedEventArgs e)\n        {\n            delayTimer.Stop();\n            Invoke(new Action(FilterAssetList));\n        }\n\n        private void assetListView_ColumnClick(object sender, ColumnClickEventArgs e)\n        {\n            if (sortColumn != e.Column)\n            {\n                reverseSort = false;\n            }\n            else\n            {\n                reverseSort = !reverseSort;\n            }\n            sortColumn = e.Column;\n            assetListView.BeginUpdate();\n            assetListView.SelectedIndices.Clear();\n            if (sortColumn == 4) //FullSize\n            {\n                visibleAssets.Sort((a, b) =>\n                {\n                    var asf = a.FullSize;\n                    var bsf = b.FullSize;\n                    return reverseSort ? bsf.CompareTo(asf) : asf.CompareTo(bsf);\n                });\n            }\n            else if (sortColumn == 3) // PathID\n            {\n                visibleAssets.Sort((x, y) =>\n                {\n                    long pathID_X = x.m_PathID;\n                    long pathID_Y = y.m_PathID;\n                    return reverseSort ? pathID_Y.CompareTo(pathID_X) : pathID_X.CompareTo(pathID_Y);\n                });\n            }\n            else\n            {\n                visibleAssets.Sort((a, b) =>\n                {\n                    var at = a.SubItems[sortColumn].Text;\n                    var bt = b.SubItems[sortColumn].Text;\n                    return reverseSort ? bt.CompareTo(at) : at.CompareTo(bt);\n                });\n            }\n            assetListView.EndUpdate();\n        }\n\n        private void selectAsset(object sender, ListViewItemSelectionChangedEventArgs e)\n        {\n            previewPanel.BackgroundImage = Properties.Resources.preview;\n            previewPanel.BackgroundImageLayout = ImageLayout.Center;\n            classTextBox.Visible = false;\n            assetInfoLabel.Visible = false;\n            assetInfoLabel.Text = null;\n            textPreviewBox.Visible = false;\n            fontPreviewBox.Visible = false;\n            FMODpanel.Visible = false;\n            glControl1.Visible = false;\n            StatusStripUpdate(\"\");\n\n            FMODreset();\n\n            lastSelectedItem = (AssetItem)e.Item;\n\n            if (e.IsSelected)\n            {\n                if (tabControl2.SelectedIndex == 1)\n                {\n                    dumpTextBox.Text = DumpAsset(lastSelectedItem.Asset);\n                }\n                if (enablePreview.Checked)\n                {\n                    PreviewAsset(lastSelectedItem);\n                    if (displayInfo.Checked && lastSelectedItem.InfoText != null)\n                    {\n                        assetInfoLabel.Text = lastSelectedItem.InfoText;\n                        assetInfoLabel.Visible = true;\n                    }\n                }\n            }\n        }\n\n        private void classesListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)\n        {\n            classTextBox.Visible = true;\n            assetInfoLabel.Visible = false;\n            assetInfoLabel.Text = null;\n            textPreviewBox.Visible = false;\n            fontPreviewBox.Visible = false;\n            FMODpanel.Visible = false;\n            glControl1.Visible = false;\n            StatusStripUpdate(\"\");\n            if (e.IsSelected)\n            {\n                classTextBox.Text = ((TypeTreeItem)classesListView.SelectedItems[0]).ToString();\n            }\n        }\n\n        private void preview_Resize(object sender, EventArgs e)\n        {\n            if (glControlLoaded && glControl1.Visible)\n            {\n                ChangeGLSize(glControl1.Size);\n                glControl1.Invalidate();\n            }\n        }\n\n        private void PreviewAsset(AssetItem assetItem)\n        {\n            if (assetItem == null)\n                return;\n            try\n            {\n                switch (assetItem.Asset)\n                {\n                    case Texture2D m_Texture2D:\n                        PreviewTexture2D(assetItem, m_Texture2D);\n                        break;\n                    case AudioClip m_AudioClip:\n                        PreviewAudioClip(assetItem, m_AudioClip);\n                        break;\n                    case Shader m_Shader:\n                        PreviewShader(m_Shader);\n                        break;\n                    case TextAsset m_TextAsset:\n                        PreviewTextAsset(m_TextAsset);\n                        break;\n                    case MonoBehaviour m_MonoBehaviour:\n                        PreviewMonoBehaviour(m_MonoBehaviour);\n                        break;\n                    case Font m_Font:\n                        PreviewFont(m_Font);\n                        break;\n                    case Mesh m_Mesh:\n                        PreviewMesh(m_Mesh);\n                        break;\n                    case VideoClip _:\n                    case MovieTexture _:\n                        StatusStripUpdate(\"Only supported export.\");\n                        break;\n                    case Sprite m_Sprite:\n                        PreviewSprite(assetItem, m_Sprite);\n                        break;\n                    case Animator _:\n                        StatusStripUpdate(\"Can be exported to FBX file.\");\n                        break;\n                    case AnimationClip _:\n                        StatusStripUpdate(\"Can be exported with Animator or Objects\");\n                        break;\n                    default:\n                        var str = assetItem.Asset.Dump();\n                        if (str != null)\n                        {\n                            textPreviewBox.Text = str;\n                            textPreviewBox.Visible = true;\n                        }\n                        break;\n                }\n            }\n            catch (Exception e)\n            {\n                MessageBox.Show($\"Preview {assetItem.Type}:{assetItem.Text} error\\r\\n{e.Message}\\r\\n{e.StackTrace}\");\n            }\n        }\n\n        private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D)\n        {\n            var image = m_Texture2D.ConvertToImage(true);\n            if (image != null)\n            {\n                var bitmap = new DirectBitmap(image.ConvertToBytes(), m_Texture2D.m_Width, m_Texture2D.m_Height);\n                image.Dispose();\n                assetItem.InfoText = $\"Width: {m_Texture2D.m_Width}\\nHeight: {m_Texture2D.m_Height}\\nFormat: {m_Texture2D.m_TextureFormat}\";\n                switch (m_Texture2D.m_TextureSettings.m_FilterMode)\n                {\n                    case 0: assetItem.InfoText += \"\\nFilter Mode: Point \"; break;\n                    case 1: assetItem.InfoText += \"\\nFilter Mode: Bilinear \"; break;\n                    case 2: assetItem.InfoText += \"\\nFilter Mode: Trilinear \"; break;\n                }\n                assetItem.InfoText += $\"\\nAnisotropic level: {m_Texture2D.m_TextureSettings.m_Aniso}\\nMip map bias: {m_Texture2D.m_TextureSettings.m_MipBias}\";\n                switch (m_Texture2D.m_TextureSettings.m_WrapMode)\n                {\n                    case 0: assetItem.InfoText += \"\\nWrap mode: Repeat\"; break;\n                    case 1: assetItem.InfoText += \"\\nWrap mode: Clamp\"; break;\n                }\n                assetItem.InfoText += \"\\nChannels: \";\n                int validChannel = 0;\n                for (int i = 0; i < 4; i++)\n                {\n                    if (textureChannels[i])\n                    {\n                        assetItem.InfoText += textureChannelNames[i];\n                        validChannel++;\n                    }\n                }\n                if (validChannel == 0)\n                    assetItem.InfoText += \"None\";\n                if (validChannel != 4)\n                {\n                    var bytes = bitmap.Bits;\n                    for (int i = 0; i < bitmap.Height; i++)\n                    {\n                        int offset = Math.Abs(bitmap.Stride) * i;\n                        for (int j = 0; j < bitmap.Width; j++)\n                        {\n                            bytes[offset] = textureChannels[0] ? bytes[offset] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue;\n                            bytes[offset + 1] = textureChannels[1] ? bytes[offset + 1] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue;\n                            bytes[offset + 2] = textureChannels[2] ? bytes[offset + 2] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue;\n                            bytes[offset + 3] = textureChannels[3] ? bytes[offset + 3] : byte.MaxValue;\n                            offset += 4;\n                        }\n                    }\n                }\n                PreviewTexture(bitmap);\n\n                StatusStripUpdate(\"'Ctrl'+'R'/'G'/'B'/'A' for Channel Toggle\");\n            }\n            else\n            {\n                StatusStripUpdate(\"Unsupported image for preview\");\n            }\n        }\n\n        private void PreviewAudioClip(AssetItem assetItem, AudioClip m_AudioClip)\n        {\n            //Info\n            assetItem.InfoText = \"Compression format: \";\n            if (m_AudioClip.version[0] < 5)\n            {\n                switch (m_AudioClip.m_Type)\n                {\n                    case FMODSoundType.ACC:\n                        assetItem.InfoText += \"Acc\";\n                        break;\n                    case FMODSoundType.AIFF:\n                        assetItem.InfoText += \"AIFF\";\n                        break;\n                    case FMODSoundType.IT:\n                        assetItem.InfoText += \"Impulse tracker\";\n                        break;\n                    case FMODSoundType.MOD:\n                        assetItem.InfoText += \"Protracker / Fasttracker MOD\";\n                        break;\n                    case FMODSoundType.MPEG:\n                        assetItem.InfoText += \"MP2/MP3 MPEG\";\n                        break;\n                    case FMODSoundType.OGGVORBIS:\n                        assetItem.InfoText += \"Ogg vorbis\";\n                        break;\n                    case FMODSoundType.S3M:\n                        assetItem.InfoText += \"ScreamTracker 3\";\n                        break;\n                    case FMODSoundType.WAV:\n                        assetItem.InfoText += \"Microsoft WAV\";\n                        break;\n                    case FMODSoundType.XM:\n                        assetItem.InfoText += \"FastTracker 2 XM\";\n                        break;\n                    case FMODSoundType.XMA:\n                        assetItem.InfoText += \"Xbox360 XMA\";\n                        break;\n                    case FMODSoundType.VAG:\n                        assetItem.InfoText += \"PlayStation Portable ADPCM\";\n                        break;\n                    case FMODSoundType.AUDIOQUEUE:\n                        assetItem.InfoText += \"iPhone\";\n                        break;\n                    default:\n                        assetItem.InfoText += \"Unknown\";\n                        break;\n                }\n            }\n            else\n            {\n                switch (m_AudioClip.m_CompressionFormat)\n                {\n                    case AudioCompressionFormat.PCM:\n                        assetItem.InfoText += \"PCM\";\n                        break;\n                    case AudioCompressionFormat.Vorbis:\n                        assetItem.InfoText += \"Vorbis\";\n                        break;\n                    case AudioCompressionFormat.ADPCM:\n                        assetItem.InfoText += \"ADPCM\";\n                        break;\n                    case AudioCompressionFormat.MP3:\n                        assetItem.InfoText += \"MP3\";\n                        break;\n                    case AudioCompressionFormat.PSMVAG:\n                        assetItem.InfoText += \"PlayStation Portable ADPCM\";\n                        break;\n                    case AudioCompressionFormat.HEVAG:\n                        assetItem.InfoText += \"PSVita ADPCM\";\n                        break;\n                    case AudioCompressionFormat.XMA:\n                        assetItem.InfoText += \"Xbox360 XMA\";\n                        break;\n                    case AudioCompressionFormat.AAC:\n                        assetItem.InfoText += \"AAC\";\n                        break;\n                    case AudioCompressionFormat.GCADPCM:\n                        assetItem.InfoText += \"Nintendo 3DS/Wii DSP\";\n                        break;\n                    case AudioCompressionFormat.ATRAC9:\n                        assetItem.InfoText += \"PSVita ATRAC9\";\n                        break;\n                    default:\n                        assetItem.InfoText += \"Unknown\";\n                        break;\n                }\n            }\n\n            var m_AudioData = m_AudioClip.m_AudioData.GetData();\n            if (m_AudioData == null || m_AudioData.Length == 0)\n                return;\n            var exinfo = new FMOD.CREATESOUNDEXINFO();\n\n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n            exinfo.length = (uint)m_AudioClip.m_Size;\n\n            var result = system.createSound(m_AudioData, FMOD.MODE.OPENMEMORY | loopMode, ref exinfo, out sound);\n            if (ERRCHECK(result)) return;\n\n            sound.getNumSubSounds(out var numsubsounds);\n\n            if (numsubsounds > 0)\n            {\n                result = sound.getSubSound(0, out var subsound);\n                if (result == FMOD.RESULT.OK)\n                {\n                    sound = subsound;\n                }\n            }\n\n            result = sound.getLength(out FMODlenms, FMOD.TIMEUNIT.MS);\n            if (ERRCHECK(result)) return;\n\n            result = system.playSound(sound, null, true, out channel);\n            if (ERRCHECK(result)) return;\n\n            FMODpanel.Visible = true;\n\n            result = channel.getFrequency(out var frequency);\n            if (ERRCHECK(result)) return;\n\n            FMODinfoLabel.Text = frequency + \" Hz\";\n            FMODtimerLabel.Text = $\"0:0.0 / {FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}\";\n        }\n\n        private void PreviewShader(Shader m_Shader)\n        {\n            var str = ShaderConverter.Convert(m_Shader);\n            PreviewText(str == null ? \"Serialized Shader can't be read\" : str.Replace(\"\\n\", \"\\r\\n\"));\n        }\n\n        private void PreviewTextAsset(TextAsset m_TextAsset)\n        {\n            var text = Encoding.UTF8.GetString(m_TextAsset.m_Script);\n            text = text.Replace(\"\\n\", \"\\r\\n\").Replace(\"\\0\", \"\");\n            PreviewText(text);\n        }\n\n        private void PreviewMonoBehaviour(MonoBehaviour m_MonoBehaviour)\n        {\n            var obj = m_MonoBehaviour.ToType();\n            if (obj == null)\n            {\n                var type = MonoBehaviourToTypeTree(m_MonoBehaviour);\n                obj = m_MonoBehaviour.ToType(type);\n            }\n            var str = JsonConvert.SerializeObject(obj, Formatting.Indented);\n            PreviewText(str);\n        }\n\n        private void PreviewFont(Font m_Font)\n        {\n            if (m_Font.m_FontData != null)\n            {\n                var data = Marshal.AllocCoTaskMem(m_Font.m_FontData.Length);\n                Marshal.Copy(m_Font.m_FontData, 0, data, m_Font.m_FontData.Length);\n\n                uint cFonts = 0;\n                var re = AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts);\n                if (re != IntPtr.Zero)\n                {\n                    using (var pfc = new PrivateFontCollection())\n                    {\n                        pfc.AddMemoryFont(data, m_Font.m_FontData.Length);\n                        Marshal.FreeCoTaskMem(data);\n                        if (pfc.Families.Length > 0)\n                        {\n                            fontPreviewBox.SelectionStart = 0;\n                            fontPreviewBox.SelectionLength = 80;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 16, FontStyle.Regular);\n                            fontPreviewBox.SelectionStart = 81;\n                            fontPreviewBox.SelectionLength = 56;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 12, FontStyle.Regular);\n                            fontPreviewBox.SelectionStart = 138;\n                            fontPreviewBox.SelectionLength = 56;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 18, FontStyle.Regular);\n                            fontPreviewBox.SelectionStart = 195;\n                            fontPreviewBox.SelectionLength = 56;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 24, FontStyle.Regular);\n                            fontPreviewBox.SelectionStart = 252;\n                            fontPreviewBox.SelectionLength = 56;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 36, FontStyle.Regular);\n                            fontPreviewBox.SelectionStart = 309;\n                            fontPreviewBox.SelectionLength = 56;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 48, FontStyle.Regular);\n                            fontPreviewBox.SelectionStart = 366;\n                            fontPreviewBox.SelectionLength = 56;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 60, FontStyle.Regular);\n                            fontPreviewBox.SelectionStart = 423;\n                            fontPreviewBox.SelectionLength = 55;\n                            fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 72, FontStyle.Regular);\n                            fontPreviewBox.Visible = true;\n                        }\n                    }\n                    return;\n                }\n            }\n            StatusStripUpdate(\"Unsupported font for preview. Try to export.\");\n        }\n\n        private void PreviewMesh(Mesh m_Mesh)\n        {\n            if (m_Mesh.m_VertexCount > 0)\n            {\n                viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6);\n                #region Vertices\n                if (m_Mesh.m_Vertices == null || m_Mesh.m_Vertices.Length == 0)\n                {\n                    StatusStripUpdate(\"Mesh can't be previewed.\");\n                    return;\n                }\n                int count = 3;\n                if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4)\n                {\n                    count = 4;\n                }\n                vertexData = new Vector3[m_Mesh.m_VertexCount];\n                // Calculate Bounding\n                float[] min = new float[3];\n                float[] max = new float[3];\n                for (int i = 0; i < 3; i++)\n                {\n                    min[i] = m_Mesh.m_Vertices[i];\n                    max[i] = m_Mesh.m_Vertices[i];\n                }\n                for (int v = 0; v < m_Mesh.m_VertexCount; v++)\n                {\n                    for (int i = 0; i < 3; i++)\n                    {\n                        min[i] = Math.Min(min[i], m_Mesh.m_Vertices[v * count + i]);\n                        max[i] = Math.Max(max[i], m_Mesh.m_Vertices[v * count + i]);\n                    }\n                    vertexData[v] = new Vector3(\n                        m_Mesh.m_Vertices[v * count],\n                        m_Mesh.m_Vertices[v * count + 1],\n                        m_Mesh.m_Vertices[v * count + 2]);\n                }\n\n                // Calculate modelMatrix\n                Vector3 dist = Vector3.One, offset = Vector3.Zero;\n                for (int i = 0; i < 3; i++)\n                {\n                    dist[i] = max[i] - min[i];\n                    offset[i] = (max[i] + min[i]) / 2;\n                }\n                float d = Math.Max(1e-5f, dist.Length);\n                modelMatrixData = Matrix4.CreateTranslation(-offset) * Matrix4.CreateScale(2f / d);\n                #endregion\n                #region Indicies\n                indiceData = new int[m_Mesh.m_Indices.Count];\n                for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3)\n                {\n                    indiceData[i] = (int)m_Mesh.m_Indices[i];\n                    indiceData[i + 1] = (int)m_Mesh.m_Indices[i + 1];\n                    indiceData[i + 2] = (int)m_Mesh.m_Indices[i + 2];\n                }\n                #endregion\n                #region Normals\n                if (m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0)\n                {\n                    if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3)\n                        count = 3;\n                    else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4)\n                        count = 4;\n                    normalData = new Vector3[m_Mesh.m_VertexCount];\n                    for (int n = 0; n < m_Mesh.m_VertexCount; n++)\n                    {\n                        normalData[n] = new Vector3(\n                            m_Mesh.m_Normals[n * count],\n                            m_Mesh.m_Normals[n * count + 1],\n                            m_Mesh.m_Normals[n * count + 2]);\n                    }\n                }\n                else\n                    normalData = null;\n                // calculate normal by ourself\n                normal2Data = new Vector3[m_Mesh.m_VertexCount];\n                int[] normalCalculatedCount = new int[m_Mesh.m_VertexCount];\n                for (int i = 0; i < m_Mesh.m_VertexCount; i++)\n                {\n                    normal2Data[i] = Vector3.Zero;\n                    normalCalculatedCount[i] = 0;\n                }\n                for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3)\n                {\n                    Vector3 dir1 = vertexData[indiceData[i + 1]] - vertexData[indiceData[i]];\n                    Vector3 dir2 = vertexData[indiceData[i + 2]] - vertexData[indiceData[i]];\n                    Vector3 normal = Vector3.Cross(dir1, dir2);\n                    normal.Normalize();\n                    for (int j = 0; j < 3; j++)\n                    {\n                        normal2Data[indiceData[i + j]] += normal;\n                        normalCalculatedCount[indiceData[i + j]]++;\n                    }\n                }\n                for (int i = 0; i < m_Mesh.m_VertexCount; i++)\n                {\n                    if (normalCalculatedCount[i] == 0)\n                        normal2Data[i] = new Vector3(0, 1, 0);\n                    else\n                        normal2Data[i] /= normalCalculatedCount[i];\n                }\n                #endregion\n                #region Colors\n                if (m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3)\n                {\n                    colorData = new Vector4[m_Mesh.m_VertexCount];\n                    for (int c = 0; c < m_Mesh.m_VertexCount; c++)\n                    {\n                        colorData[c] = new Vector4(\n                            m_Mesh.m_Colors[c * 3],\n                            m_Mesh.m_Colors[c * 3 + 1],\n                            m_Mesh.m_Colors[c * 3 + 2],\n                            1.0f);\n                    }\n                }\n                else if (m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 4)\n                {\n                    colorData = new Vector4[m_Mesh.m_VertexCount];\n                    for (int c = 0; c < m_Mesh.m_VertexCount; c++)\n                    {\n                        colorData[c] = new Vector4(\n                        m_Mesh.m_Colors[c * 4],\n                        m_Mesh.m_Colors[c * 4 + 1],\n                        m_Mesh.m_Colors[c * 4 + 2],\n                        m_Mesh.m_Colors[c * 4 + 3]);\n                    }\n                }\n                else\n                {\n                    colorData = new Vector4[m_Mesh.m_VertexCount];\n                    for (int c = 0; c < m_Mesh.m_VertexCount; c++)\n                    {\n                        colorData[c] = new Vector4(0.5f, 0.5f, 0.5f, 1.0f);\n                    }\n                }\n                #endregion\n                glControl1.Visible = true;\n                CreateVAO();\n                StatusStripUpdate(\"Using OpenGL Version: \" + GL.GetString(StringName.Version) + \"\\n\"\n                                  + \"'Mouse Left'=Rotate | 'Mouse Right'=Move | 'Mouse Wheel'=Zoom \\n\"\n                                  + \"'Ctrl W'=Wireframe | 'Ctrl S'=Shade | 'Ctrl N'=ReNormal \");\n            }\n            else\n            {\n                StatusStripUpdate(\"Unable to preview this mesh\");\n            }\n        }\n\n        private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)\n        {\n            var image = m_Sprite.GetImage();\n            if (image != null)\n            {\n                var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);\n                image.Dispose();\n                assetItem.InfoText = $\"Width: {bitmap.Width}\\nHeight: {bitmap.Height}\\n\";\n                PreviewTexture(bitmap);\n            }\n            else\n            {\n                StatusStripUpdate(\"Unsupported sprite for preview.\");\n            }\n        }\n\n        private void PreviewTexture(DirectBitmap bitmap)\n        {\n            imageTexture?.Dispose();\n            imageTexture = bitmap;\n            previewPanel.BackgroundImage = imageTexture.Bitmap;\n            if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)\n                previewPanel.BackgroundImageLayout = ImageLayout.Zoom;\n            else\n                previewPanel.BackgroundImageLayout = ImageLayout.Center;\n        }\n\n        private void PreviewText(string text)\n        {\n            textPreviewBox.Text = text;\n            textPreviewBox.Visible = true;\n        }\n\n        private void SetProgressBarValue(int value)\n        {\n            if (InvokeRequired)\n            {\n                BeginInvoke(new Action(() => { progressBar1.Value = value; }));\n            }\n            else\n            {\n                progressBar1.Value = value;\n            }\n        }\n\n        private void StatusStripUpdate(string statusText)\n        {\n            if (InvokeRequired)\n            {\n                BeginInvoke(new Action(() => { toolStripStatusLabel1.Text = statusText; }));\n            }\n            else\n            {\n                toolStripStatusLabel1.Text = statusText;\n            }\n        }\n\n        private void ResetForm()\n        {\n            Text = $\"AssetStudioGUI v{Application.ProductVersion}\";\n            assetsManager.Clear();\n            assemblyLoader.Clear();\n            exportableAssets.Clear();\n            visibleAssets.Clear();\n            sceneTreeView.Nodes.Clear();\n            assetListView.VirtualListSize = 0;\n            assetListView.Items.Clear();\n            classesListView.Items.Clear();\n            classesListView.Groups.Clear();\n            previewPanel.BackgroundImage = Properties.Resources.preview;\n            imageTexture?.Dispose();\n            imageTexture = null;\n            previewPanel.BackgroundImageLayout = ImageLayout.Center;\n            assetInfoLabel.Visible = false;\n            assetInfoLabel.Text = null;\n            textPreviewBox.Visible = false;\n            fontPreviewBox.Visible = false;\n            glControl1.Visible = false;\n            lastSelectedItem = null;\n            sortColumn = -1;\n            reverseSort = false;\n            enableFiltering = false;\n            listSearch.Text = \" Filter \";\n\n            var count = filterTypeToolStripMenuItem.DropDownItems.Count;\n            for (var i = 1; i < count; i++)\n            {\n                filterTypeToolStripMenuItem.DropDownItems.RemoveAt(1);\n            }\n\n            FMODreset();\n        }\n\n        private void assetListView_MouseClick(object sender, MouseEventArgs e)\n        {\n            if (e.Button == MouseButtons.Right && assetListView.SelectedIndices.Count > 0)\n            {\n                goToSceneHierarchyToolStripMenuItem.Visible = false;\n                showOriginalFileToolStripMenuItem.Visible = false;\n                exportAnimatorwithselectedAnimationClipMenuItem.Visible = false;\n\n                if (assetListView.SelectedIndices.Count == 1)\n                {\n                    goToSceneHierarchyToolStripMenuItem.Visible = true;\n                    showOriginalFileToolStripMenuItem.Visible = true;\n                }\n                if (assetListView.SelectedIndices.Count >= 1)\n                {\n                    var selectedAssets = GetSelectedAssets();\n                    if (selectedAssets.Any(x => x.Type == ClassIDType.Animator) && selectedAssets.Any(x => x.Type == ClassIDType.AnimationClip))\n                    {\n                        exportAnimatorwithselectedAnimationClipMenuItem.Visible = true;\n                    }\n                }\n\n                tempClipboard = assetListView.HitTest(new Point(e.X, e.Y)).SubItem.Text;\n                contextMenuStrip1.Show(assetListView, e.X, e.Y);\n            }\n        }\n\n        private void copyToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            Clipboard.SetDataObject(tempClipboard);\n        }\n\n        private void exportSelectedAssetsToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.Selected, ExportType.Convert);\n        }\n\n        private void showOriginalFileToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];\n            var args = $\"/select, \\\"{selectasset.SourceFile.originalPath ?? selectasset.SourceFile.fullName}\\\"\";\n            var pfi = new ProcessStartInfo(\"explorer.exe\", args);\n            Process.Start(pfi);\n        }\n\n        private void exportAnimatorwithAnimationClipMenuItem_Click(object sender, EventArgs e)\n        {\n            AssetItem animator = null;\n            List<AssetItem> animationList = new List<AssetItem>();\n            var selectedAssets = GetSelectedAssets();\n            foreach (var assetPreloadData in selectedAssets)\n            {\n                if (assetPreloadData.Type == ClassIDType.Animator)\n                {\n                    animator = assetPreloadData;\n                }\n                else if (assetPreloadData.Type == ClassIDType.AnimationClip)\n                {\n                    animationList.Add(assetPreloadData);\n                }\n            }\n\n            if (animator != null)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                saveFolderDialog.InitialFolder = saveDirectoryBackup;\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    saveDirectoryBackup = saveFolderDialog.Folder;\n                    var exportPath = Path.Combine(saveFolderDialog.Folder, \"Animator\") + Path.DirectorySeparatorChar;\n                    ExportAnimatorWithAnimationClip(animator, animationList, exportPath);\n                }\n            }\n        }\n\n        private void exportSelectedObjectsToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportObjects(false);\n        }\n\n        private void exportObjectswithAnimationClipMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportObjects(true);\n        }\n\n        private void ExportObjects(bool animation)\n        {\n            if (sceneTreeView.Nodes.Count > 0)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                saveFolderDialog.InitialFolder = saveDirectoryBackup;\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    saveDirectoryBackup = saveFolderDialog.Folder;\n                    var exportPath = Path.Combine(saveFolderDialog.Folder, \"GameObject\") + Path.DirectorySeparatorChar;\n                    List<AssetItem> animationList = null;\n                    if (animation)\n                    {\n                        animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList();\n                        if (animationList.Count == 0)\n                        {\n                            animationList = null;\n                        }\n                    }\n                    ExportObjectsWithAnimationClip(exportPath, sceneTreeView.Nodes, animationList);\n                }\n            }\n            else\n            {\n                StatusStripUpdate(\"No Objects available for export\");\n            }\n        }\n\n        private void exportSelectedObjectsmergeToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportMergeObjects(false);\n        }\n\n        private void exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportMergeObjects(true);\n        }\n\n        private void ExportMergeObjects(bool animation)\n        {\n            if (sceneTreeView.Nodes.Count > 0)\n            {\n                var gameObjects = new List<GameObject>();\n                GetSelectedParentNode(sceneTreeView.Nodes, gameObjects);\n                if (gameObjects.Count > 0)\n                {\n                    var saveFileDialog = new SaveFileDialog();\n                    saveFileDialog.FileName = gameObjects[0].m_Name + \" (merge).fbx\";\n                    saveFileDialog.AddExtension = false;\n                    saveFileDialog.Filter = \"Fbx file (*.fbx)|*.fbx\";\n                    saveFileDialog.InitialDirectory = saveDirectoryBackup;\n                    if (saveFileDialog.ShowDialog(this) == DialogResult.OK)\n                    {\n                        saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName);\n                        var exportPath = saveFileDialog.FileName;\n                        List<AssetItem> animationList = null;\n                        if (animation)\n                        {\n                            animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList();\n                            if (animationList.Count == 0)\n                            {\n                                animationList = null;\n                            }\n                        }\n                        ExportObjectsMergeWithAnimationClip(exportPath, gameObjects, animationList);\n                    }\n                }\n                else\n                {\n                    StatusStripUpdate(\"No Object selected for export.\");\n                }\n            }\n        }\n\n        private void goToSceneHierarchyToolStripMenuItem_Click(object sender, EventArgs e)\n        {\n            var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];\n            if (selectasset.TreeNode != null)\n            {\n                sceneTreeView.SelectedNode = selectasset.TreeNode;\n                tabControl1.SelectedTab = tabPage1;\n            }\n        }\n\n        private void exportAllAssetsMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.All, ExportType.Convert);\n        }\n\n        private void exportSelectedAssetsMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.Selected, ExportType.Convert);\n        }\n\n        private void exportFilteredAssetsMenuItem_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.Filtered, ExportType.Convert);\n        }\n\n        private void toolStripMenuItem4_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.All, ExportType.Raw);\n        }\n\n        private void toolStripMenuItem5_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.Selected, ExportType.Raw);\n        }\n\n        private void toolStripMenuItem6_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.Filtered, ExportType.Raw);\n        }\n\n        private void toolStripMenuItem7_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.All, ExportType.Dump);\n        }\n\n        private void toolStripMenuItem8_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.Selected, ExportType.Dump);\n        }\n\n        private void toolStripMenuItem9_Click(object sender, EventArgs e)\n        {\n            ExportAssets(ExportFilter.Filtered, ExportType.Dump);\n        }\n\n        private void toolStripMenuItem11_Click(object sender, EventArgs e)\n        {\n            ExportAssetsList(ExportFilter.All);\n        }\n\n        private void toolStripMenuItem12_Click(object sender, EventArgs e)\n        {\n            ExportAssetsList(ExportFilter.Selected);\n        }\n\n        private void toolStripMenuItem13_Click(object sender, EventArgs e)\n        {\n            ExportAssetsList(ExportFilter.Filtered);\n        }\n\n        private void exportAllObjectssplitToolStripMenuItem1_Click(object sender, EventArgs e)\n        {\n            if (sceneTreeView.Nodes.Count > 0)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                saveFolderDialog.InitialFolder = saveDirectoryBackup;\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    saveDirectoryBackup = saveFolderDialog.Folder;\n                    var savePath = saveFolderDialog.Folder + Path.DirectorySeparatorChar;\n                    ExportSplitObjects(savePath, sceneTreeView.Nodes);\n                }\n            }\n            else\n            {\n                StatusStripUpdate(\"No Objects available for export\");\n            }\n        }\n\n        private List<AssetItem> GetSelectedAssets()\n        {\n            var selectedAssets = new List<AssetItem>(assetListView.SelectedIndices.Count);\n            foreach (int index in assetListView.SelectedIndices)\n            {\n                selectedAssets.Add((AssetItem)assetListView.Items[index]);\n            }\n\n            return selectedAssets;\n        }\n\n        private void FilterAssetList()\n        {\n            assetListView.BeginUpdate();\n            assetListView.SelectedIndices.Clear();\n            var show = new List<ClassIDType>();\n            if (!allToolStripMenuItem.Checked)\n            {\n                for (var i = 1; i < filterTypeToolStripMenuItem.DropDownItems.Count; i++)\n                {\n                    var item = (ToolStripMenuItem)filterTypeToolStripMenuItem.DropDownItems[i];\n                    if (item.Checked)\n                    {\n                        show.Add((ClassIDType)Enum.Parse(typeof(ClassIDType), item.Text));\n                    }\n                }\n                visibleAssets = exportableAssets.FindAll(x => show.Contains(x.Type));\n            }\n            else\n            {\n                visibleAssets = exportableAssets;\n            }\n            if (listSearch.Text != \" Filter \")\n            {\n                visibleAssets = visibleAssets.FindAll(\n                    x => x.Text.IndexOf(listSearch.Text, StringComparison.OrdinalIgnoreCase) >= 0 ||\n                    x.SubItems[1].Text.IndexOf(listSearch.Text, StringComparison.OrdinalIgnoreCase) >= 0 ||\n                    x.SubItems[3].Text.IndexOf(listSearch.Text, StringComparison.OrdinalIgnoreCase) >= 0);\n            }\n            assetListView.VirtualListSize = visibleAssets.Count;\n            assetListView.EndUpdate();\n        }\n\n        private void ExportAssets(ExportFilter type, ExportType exportType)\n        {\n            if (exportableAssets.Count > 0)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                saveFolderDialog.InitialFolder = saveDirectoryBackup;\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    timer.Stop();\n                    saveDirectoryBackup = saveFolderDialog.Folder;\n                    List<AssetItem> toExportAssets = null;\n                    switch (type)\n                    {\n                        case ExportFilter.All:\n                            toExportAssets = exportableAssets;\n                            break;\n                        case ExportFilter.Selected:\n                            toExportAssets = GetSelectedAssets();\n                            break;\n                        case ExportFilter.Filtered:\n                            toExportAssets = visibleAssets;\n                            break;\n                    }\n                    Studio.ExportAssets(saveFolderDialog.Folder, toExportAssets, exportType);\n                }\n            }\n            else\n            {\n                StatusStripUpdate(\"No exportable assets loaded\");\n            }\n        }\n\n        private void ExportAssetsList(ExportFilter type)\n        {\n            // XXX: Only exporting as XML for now, but would JSON(/CSV/other) be useful too?\n\n            if (exportableAssets.Count > 0)\n            {\n                var saveFolderDialog = new OpenFolderDialog();\n                saveFolderDialog.InitialFolder = saveDirectoryBackup;\n                if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)\n                {\n                    timer.Stop();\n                    saveDirectoryBackup = saveFolderDialog.Folder;\n                    List<AssetItem> toExportAssets = null;\n                    switch (type)\n                    {\n                        case ExportFilter.All:\n                            toExportAssets = exportableAssets;\n                            break;\n                        case ExportFilter.Selected:\n                            toExportAssets = GetSelectedAssets();\n                            break;\n                        case ExportFilter.Filtered:\n                            toExportAssets = visibleAssets;\n                            break;\n                    }\n                    Studio.ExportAssetsList(saveFolderDialog.Folder, toExportAssets, ExportListType.XML);\n                }\n            }\n            else\n            {\n                StatusStripUpdate(\"No exportable assets loaded\");\n            }\n        }\n\n        #region FMOD\n        private void FMODinit()\n        {\n            FMODreset();\n\n            var result = FMOD.Factory.System_Create(out system);\n            if (ERRCHECK(result)) { return; }\n\n            result = system.getVersion(out var version);\n            ERRCHECK(result);\n            if (version < FMOD.VERSION.number)\n            {\n                MessageBox.Show($\"Error!  You are using an old version of FMOD {version:X}.  This program requires {FMOD.VERSION.number:X}.\");\n                Application.Exit();\n            }\n\n            result = system.init(2, FMOD.INITFLAGS.NORMAL, IntPtr.Zero);\n            if (ERRCHECK(result)) { return; }\n\n            result = system.getMasterSoundGroup(out masterSoundGroup);\n            if (ERRCHECK(result)) { return; }\n\n            result = masterSoundGroup.setVolume(FMODVolume);\n            if (ERRCHECK(result)) { return; }\n        }\n\n        private void FMODreset()\n        {\n            timer.Stop();\n            FMODprogressBar.Value = 0;\n            FMODtimerLabel.Text = \"0:00.0 / 0:00.0\";\n            FMODstatusLabel.Text = \"Stopped\";\n            FMODinfoLabel.Text = \"\";\n\n            if (sound != null && sound.isValid())\n            {\n                var result = sound.release();\n                ERRCHECK(result);\n                sound = null;\n            }\n        }\n\n        private void FMODplayButton_Click(object sender, EventArgs e)\n        {\n            if (sound != null && channel != null)\n            {\n                timer.Start();\n                var result = channel.isPlaying(out var playing);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    if (ERRCHECK(result)) { return; }\n                }\n\n                if (playing)\n                {\n                    result = channel.stop();\n                    if (ERRCHECK(result)) { return; }\n\n                    result = system.playSound(sound, null, false, out channel);\n                    if (ERRCHECK(result)) { return; }\n\n                    FMODpauseButton.Text = \"Pause\";\n                }\n                else\n                {\n                    result = system.playSound(sound, null, false, out channel);\n                    if (ERRCHECK(result)) { return; }\n                    FMODstatusLabel.Text = \"Playing\";\n\n                    if (FMODprogressBar.Value > 0)\n                    {\n                        uint newms = FMODlenms / 1000 * (uint)FMODprogressBar.Value;\n\n                        result = channel.setPosition(newms, FMOD.TIMEUNIT.MS);\n                        if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                        {\n                            if (ERRCHECK(result)) { return; }\n                        }\n\n                    }\n                }\n            }\n        }\n\n        private void FMODpauseButton_Click(object sender, EventArgs e)\n        {\n            if (sound != null && channel != null)\n            {\n                var result = channel.isPlaying(out var playing);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    if (ERRCHECK(result)) { return; }\n                }\n\n                if (playing)\n                {\n                    result = channel.getPaused(out var paused);\n                    if (ERRCHECK(result)) { return; }\n                    result = channel.setPaused(!paused);\n                    if (ERRCHECK(result)) { return; }\n\n                    if (paused)\n                    {\n                        FMODstatusLabel.Text = \"Playing\";\n                        FMODpauseButton.Text = \"Pause\";\n                        timer.Start();\n                    }\n                    else\n                    {\n                        FMODstatusLabel.Text = \"Paused\";\n                        FMODpauseButton.Text = \"Resume\";\n                        timer.Stop();\n                    }\n                }\n            }\n        }\n\n        private void FMODstopButton_Click(object sender, EventArgs e)\n        {\n            if (channel != null)\n            {\n                var result = channel.isPlaying(out var playing);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    if (ERRCHECK(result)) { return; }\n                }\n\n                if (playing)\n                {\n                    result = channel.stop();\n                    if (ERRCHECK(result)) { return; }\n                    //channel = null;\n                    //don't FMODreset, it will nullify the sound\n                    timer.Stop();\n                    FMODprogressBar.Value = 0;\n                    FMODtimerLabel.Text = \"0:00.0 / 0:00.0\";\n                    FMODstatusLabel.Text = \"Stopped\";\n                    FMODpauseButton.Text = \"Pause\";\n                }\n            }\n        }\n\n        private void FMODloopButton_CheckedChanged(object sender, EventArgs e)\n        {\n            FMOD.RESULT result;\n\n            loopMode = FMODloopButton.Checked ? FMOD.MODE.LOOP_NORMAL : FMOD.MODE.LOOP_OFF;\n\n            if (sound != null)\n            {\n                result = sound.setMode(loopMode);\n                if (ERRCHECK(result)) { return; }\n            }\n\n            if (channel != null)\n            {\n                result = channel.isPlaying(out var playing);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    if (ERRCHECK(result)) { return; }\n                }\n\n                result = channel.getPaused(out var paused);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    if (ERRCHECK(result)) { return; }\n                }\n\n                if (playing || paused)\n                {\n                    result = channel.setMode(loopMode);\n                    if (ERRCHECK(result)) { return; }\n                }\n            }\n        }\n\n        private void FMODvolumeBar_ValueChanged(object sender, EventArgs e)\n        {\n            FMODVolume = Convert.ToSingle(FMODvolumeBar.Value) / 10;\n\n            var result = masterSoundGroup.setVolume(FMODVolume);\n            if (ERRCHECK(result)) { return; }\n        }\n\n        private void FMODprogressBar_Scroll(object sender, EventArgs e)\n        {\n            if (channel != null)\n            {\n                uint newms = FMODlenms / 1000 * (uint)FMODprogressBar.Value;\n                FMODtimerLabel.Text = $\"{newms / 1000 / 60}:{newms / 1000 % 60}.{newms / 10 % 100}/{FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}\";\n            }\n        }\n\n        private void FMODprogressBar_MouseDown(object sender, MouseEventArgs e)\n        {\n            timer.Stop();\n        }\n\n        private void FMODprogressBar_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (channel != null)\n            {\n                uint newms = FMODlenms / 1000 * (uint)FMODprogressBar.Value;\n\n                var result = channel.setPosition(newms, FMOD.TIMEUNIT.MS);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    if (ERRCHECK(result)) { return; }\n                }\n\n\n                result = channel.isPlaying(out var playing);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    if (ERRCHECK(result)) { return; }\n                }\n\n                if (playing) { timer.Start(); }\n            }\n        }\n\n        private void timer_Tick(object sender, EventArgs e)\n        {\n            uint ms = 0;\n            bool playing = false;\n            bool paused = false;\n\n            if (channel != null)\n            {\n                var result = channel.getPosition(out ms, FMOD.TIMEUNIT.MS);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    ERRCHECK(result);\n                }\n\n                result = channel.isPlaying(out playing);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    ERRCHECK(result);\n                }\n\n                result = channel.getPaused(out paused);\n                if ((result != FMOD.RESULT.OK) && (result != FMOD.RESULT.ERR_INVALID_HANDLE))\n                {\n                    ERRCHECK(result);\n                }\n            }\n\n            FMODtimerLabel.Text = $\"{ms / 1000 / 60}:{ms / 1000 % 60}.{ms / 10 % 100} / {FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}\";\n            FMODprogressBar.Value = (int)(ms * 1000 / FMODlenms);\n            FMODstatusLabel.Text = paused ? \"Paused \" : playing ? \"Playing\" : \"Stopped\";\n\n            if (system != null && channel != null)\n            {\n                system.update();\n            }\n        }\n\n        private bool ERRCHECK(FMOD.RESULT result)\n        {\n            if (result != FMOD.RESULT.OK)\n            {\n                FMODreset();\n                StatusStripUpdate($\"FMOD error! {result} - {FMOD.Error.String(result)}\");\n                return true;\n            }\n            return false;\n        }\n        #endregion\n\n        #region GLControl\n        private void InitOpenTK()\n        {\n            ChangeGLSize(glControl1.Size);\n            GL.ClearColor(System.Drawing.Color.CadetBlue);\n            pgmID = GL.CreateProgram();\n            LoadShader(\"vs\", ShaderType.VertexShader, pgmID, out int vsID);\n            LoadShader(\"fs\", ShaderType.FragmentShader, pgmID, out int fsID);\n            GL.LinkProgram(pgmID);\n\n            pgmColorID = GL.CreateProgram();\n            LoadShader(\"vs\", ShaderType.VertexShader, pgmColorID, out vsID);\n            LoadShader(\"fsColor\", ShaderType.FragmentShader, pgmColorID, out fsID);\n            GL.LinkProgram(pgmColorID);\n\n            pgmBlackID = GL.CreateProgram();\n            LoadShader(\"vs\", ShaderType.VertexShader, pgmBlackID, out vsID);\n            LoadShader(\"fsBlack\", ShaderType.FragmentShader, pgmBlackID, out fsID);\n            GL.LinkProgram(pgmBlackID);\n\n            attributeVertexPosition = GL.GetAttribLocation(pgmID, \"vertexPosition\");\n            attributeNormalDirection = GL.GetAttribLocation(pgmID, \"normalDirection\");\n            attributeVertexColor = GL.GetAttribLocation(pgmColorID, \"vertexColor\");\n            uniformModelMatrix = GL.GetUniformLocation(pgmID, \"modelMatrix\");\n            uniformViewMatrix = GL.GetUniformLocation(pgmID, \"viewMatrix\");\n            uniformProjMatrix = GL.GetUniformLocation(pgmID, \"projMatrix\");\n        }\n\n        private static void LoadShader(string filename, ShaderType type, int program, out int address)\n        {\n            address = GL.CreateShader(type);\n            var str = (string)Properties.Resources.ResourceManager.GetObject(filename);\n            GL.ShaderSource(address, str);\n            GL.CompileShader(address);\n            GL.AttachShader(program, address);\n            GL.DeleteShader(address);\n        }\n\n        private static void CreateVBO(out int vboAddress, Vector3[] data, int address)\n        {\n            GL.GenBuffers(1, out vboAddress);\n            GL.BindBuffer(BufferTarget.ArrayBuffer, vboAddress);\n            GL.BufferData(BufferTarget.ArrayBuffer,\n                                    (IntPtr)(data.Length * Vector3.SizeInBytes),\n                                    data,\n                                    BufferUsageHint.StaticDraw);\n            GL.VertexAttribPointer(address, 3, VertexAttribPointerType.Float, false, 0, 0);\n            GL.EnableVertexAttribArray(address);\n        }\n\n        private static void CreateVBO(out int vboAddress, Vector4[] data, int address)\n        {\n            GL.GenBuffers(1, out vboAddress);\n            GL.BindBuffer(BufferTarget.ArrayBuffer, vboAddress);\n            GL.BufferData(BufferTarget.ArrayBuffer,\n                                    (IntPtr)(data.Length * Vector4.SizeInBytes),\n                                    data,\n                                    BufferUsageHint.StaticDraw);\n            GL.VertexAttribPointer(address, 4, VertexAttribPointerType.Float, false, 0, 0);\n            GL.EnableVertexAttribArray(address);\n        }\n\n        private static void CreateVBO(out int vboAddress, Matrix4 data, int address)\n        {\n            GL.GenBuffers(1, out vboAddress);\n            GL.UniformMatrix4(address, false, ref data);\n        }\n\n        private static void CreateEBO(out int address, int[] data)\n        {\n            GL.GenBuffers(1, out address);\n            GL.BindBuffer(BufferTarget.ElementArrayBuffer, address);\n            GL.BufferData(BufferTarget.ElementArrayBuffer,\n                            (IntPtr)(data.Length * sizeof(int)),\n                            data,\n                            BufferUsageHint.StaticDraw);\n        }\n\n        private void CreateVAO()\n        {\n            GL.DeleteVertexArray(vao);\n            GL.GenVertexArrays(1, out vao);\n            GL.BindVertexArray(vao);\n            CreateVBO(out var vboPositions, vertexData, attributeVertexPosition);\n            if (normalMode == 0)\n            {\n                CreateVBO(out var vboNormals, normal2Data, attributeNormalDirection);\n            }\n            else\n            {\n                if (normalData != null)\n                    CreateVBO(out var vboNormals, normalData, attributeNormalDirection);\n            }\n            CreateVBO(out var vboColors, colorData, attributeVertexColor);\n            CreateVBO(out var vboModelMatrix, modelMatrixData, uniformModelMatrix);\n            CreateVBO(out var vboViewMatrix, viewMatrixData, uniformViewMatrix);\n            CreateVBO(out var vboProjMatrix, projMatrixData, uniformProjMatrix);\n            CreateEBO(out var eboElements, indiceData);\n            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);\n            GL.BindVertexArray(0);\n        }\n\n        private void ChangeGLSize(Size size)\n        {\n            GL.Viewport(0, 0, size.Width, size.Height);\n\n            if (size.Width <= size.Height)\n            {\n                float k = 1.0f * size.Width / size.Height;\n                projMatrixData = Matrix4.CreateScale(1, k, 1);\n            }\n            else\n            {\n                float k = 1.0f * size.Height / size.Width;\n                projMatrixData = Matrix4.CreateScale(k, 1, 1);\n            }\n        }\n\n        private void glControl1_Load(object sender, EventArgs e)\n        {\n            InitOpenTK();\n            glControlLoaded = true;\n        }\n\n        private void glControl1_Paint(object sender, PaintEventArgs e)\n        {\n            glControl1.MakeCurrent();\n            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);\n            GL.Enable(EnableCap.DepthTest);\n            GL.DepthFunc(DepthFunction.Lequal);\n            GL.BindVertexArray(vao);\n            if (wireFrameMode == 0 || wireFrameMode == 2)\n            {\n                GL.UseProgram(shadeMode == 0 ? pgmID : pgmColorID);\n                GL.UniformMatrix4(uniformModelMatrix, false, ref modelMatrixData);\n                GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData);\n                GL.UniformMatrix4(uniformProjMatrix, false, ref projMatrixData);\n                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);\n                GL.DrawElements(BeginMode.Triangles, indiceData.Length, DrawElementsType.UnsignedInt, 0);\n            }\n            //Wireframe\n            if (wireFrameMode == 1 || wireFrameMode == 2)\n            {\n                GL.Enable(EnableCap.PolygonOffsetLine);\n                GL.PolygonOffset(-1, -1);\n                GL.UseProgram(pgmBlackID);\n                GL.UniformMatrix4(uniformModelMatrix, false, ref modelMatrixData);\n                GL.UniformMatrix4(uniformViewMatrix, false, ref viewMatrixData);\n                GL.UniformMatrix4(uniformProjMatrix, false, ref projMatrixData);\n                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);\n                GL.DrawElements(BeginMode.Triangles, indiceData.Length, DrawElementsType.UnsignedInt, 0);\n                GL.Disable(EnableCap.PolygonOffsetLine);\n            }\n            GL.BindVertexArray(0);\n            GL.Flush();\n            glControl1.SwapBuffers();\n        }\n\n        private void tabControl2_SelectedIndexChanged(object sender, EventArgs e)\n        {\n            if (tabControl2.SelectedIndex == 1 && lastSelectedItem != null)\n            {\n                dumpTextBox.Text = DumpAsset(lastSelectedItem.Asset);\n            }\n        }\n\n        private void toolStripMenuItem15_Click(object sender, EventArgs e)\n        {\n            logger.ShowErrorMessage = toolStripMenuItem15.Checked;\n        }\n\n        private void glControl1_MouseWheel(object sender, MouseEventArgs e)\n        {\n            if (glControl1.Visible)\n            {\n                viewMatrixData *= Matrix4.CreateScale(1 + e.Delta / 1000f);\n                glControl1.Invalidate();\n            }\n        }\n\n        private void glControl1_MouseDown(object sender, MouseEventArgs e)\n        {\n            mdx = e.X;\n            mdy = e.Y;\n            if (e.Button == MouseButtons.Left)\n            {\n                lmdown = true;\n            }\n            if (e.Button == MouseButtons.Right)\n            {\n                rmdown = true;\n            }\n        }\n\n        private void glControl1_MouseMove(object sender, MouseEventArgs e)\n        {\n            if (lmdown || rmdown)\n            {\n                float dx = mdx - e.X;\n                float dy = mdy - e.Y;\n                mdx = e.X;\n                mdy = e.Y;\n                if (lmdown)\n                {\n                    dx *= 0.01f;\n                    dy *= 0.01f;\n                    viewMatrixData *= Matrix4.CreateRotationX(dy);\n                    viewMatrixData *= Matrix4.CreateRotationY(dx);\n                }\n                if (rmdown)\n                {\n                    dx *= 0.003f;\n                    dy *= 0.003f;\n                    viewMatrixData *= Matrix4.CreateTranslation(-dx, dy, 0);\n                }\n                glControl1.Invalidate();\n            }\n        }\n\n        private void glControl1_MouseUp(object sender, MouseEventArgs e)\n        {\n            if (e.Button == MouseButtons.Left)\n            {\n                lmdown = false;\n            }\n            if (e.Button == MouseButtons.Right)\n            {\n                rmdown = false;\n            }\n        }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/AssetStudioGUIForm.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <metadata name=\"menuStrip1.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>312, 17</value>\n  </metadata>\n  <data name=\"fontPreviewBox.Text\" xml:space=\"preserve\">\n    <value>abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ\n1234567890.:,;'\\\"(!?)+-*/=\n\nThe quick brown fox jumps over the lazy dog. 1234567890\n\nThe quick brown fox jumps over the lazy dog. 1234567890\n\nThe quick brown fox jumps over the lazy dog. 1234567890\n\nThe quick brown fox jumps over the lazy dog. 1234567890\n\nThe quick brown fox jumps over the lazy dog. 1234567890\n\nThe quick brown fox jumps over the lazy dog. 1234567890\n\nThe quick brown fox jumps over the lazy dog. 1234567890</value>\n  </data>\n  <metadata name=\"statusStrip1.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>432, 17</value>\n  </metadata>\n  <metadata name=\"timer.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>553, 17</value>\n  </metadata>\n  <metadata name=\"openFileDialog1.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>636, 17</value>\n  </metadata>\n  <metadata name=\"contextMenuStrip1.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>147, 17</value>\n  </metadata>\n  <metadata name=\"$this.TrayHeight\" type=\"System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>67</value>\n  </metadata>\n</root>"
  },
  {
    "path": "AssetStudioGUI/Components/AssetItem.cs",
    "content": "﻿using System.Windows.Forms;\nusing AssetStudio;\n\nnamespace AssetStudioGUI\n{\n    internal class AssetItem : ListViewItem\n    {\n        public Object Asset;\n        public SerializedFile SourceFile;\n        public string Container = string.Empty;\n        public string TypeString;\n        public long m_PathID;\n        public long FullSize;\n        public ClassIDType Type;\n        public string InfoText;\n        public string UniqueID;\n        public GameObjectTreeNode TreeNode;\n\n        public AssetItem(Object asset)\n        {\n            Asset = asset;\n            SourceFile = asset.assetsFile;\n            Type = asset.type;\n            TypeString = Type.ToString();\n            m_PathID = asset.m_PathID;\n            FullSize = asset.byteSize;\n        }\n\n        public void SetSubItems()\n        {\n            SubItems.AddRange(new[]\n            {\n                Container, //Container\n                TypeString, //Type\n                m_PathID.ToString(), //PathID\n                FullSize.ToString(), //Size\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/Components/GOHierarchy.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Windows.Forms;\n\nnamespace AssetStudioGUI\n{\n    internal class GOHierarchy : TreeView\n    {\n        protected override void WndProc(ref Message m)\n        {\n            // Filter WM_LBUTTONDBLCLK\n            if (m.Msg != 0x203) base.WndProc(ref m);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/Components/GameObjectTreeNode.cs",
    "content": "﻿using System.Windows.Forms;\nusing AssetStudio;\n\nnamespace AssetStudioGUI\n{\n    internal class GameObjectTreeNode : TreeNode\n    {\n        public GameObject gameObject;\n\n        public GameObjectTreeNode(GameObject gameObject)\n        {\n            this.gameObject = gameObject;\n            Text = gameObject.m_Name;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/Components/OpenFolderDialog.cs",
    "content": "﻿using System;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Windows.Forms;\n\nnamespace AssetStudioGUI\n{\n    internal class OpenFolderDialog\n    {\n        public string InitialFolder { get; set; }\n        public string DefaultFolder { get; set; }\n        public string Folder { get; private set; }\n        public string Title { get; set; }\n\n        internal DialogResult ShowDialog(IWin32Window owner = null)\n        {\n//#if NETFRAMEWORK\n            if (Environment.OSVersion.Version.Major >= 6)\n            {\n                return ShowVistaDialog(owner);\n            }\n//#endif\n            return ShowFolderBrowserDialog(owner);\n        }\n\n        private DialogResult ShowVistaDialog(IWin32Window owner)\n        {\n            var frm = (NativeMethods.IFileDialog)(new NativeMethods.FileOpenDialogRCW());\n            frm.GetOptions(out var options);\n            options |= NativeMethods.FOS_PICKFOLDERS | NativeMethods.FOS_FORCEFILESYSTEM | NativeMethods.FOS_NOVALIDATE | NativeMethods.FOS_NOTESTFILECREATE | NativeMethods.FOS_DONTADDTORECENT;\n            frm.SetOptions(options);\n            if (!string.IsNullOrEmpty(Title))\n            {\n                frm.SetTitle(Title);\n            }\n            if (!string.IsNullOrEmpty(InitialFolder))\n            {\n                var riid = new Guid(\"43826D1E-E718-42EE-BC55-A1E261C37BFE\"); //IShellItem  \n                if (NativeMethods.SHCreateItemFromParsingName(InitialFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)\n                {\n                    frm.SetFolder(directoryShellItem);\n                }\n            }\n            if (!string.IsNullOrEmpty(DefaultFolder))\n            {\n                var riid = new Guid(\"43826D1E-E718-42EE-BC55-A1E261C37BFE\"); //IShellItem  \n                if (NativeMethods.SHCreateItemFromParsingName(DefaultFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)\n                {\n                    frm.SetDefaultFolder(directoryShellItem);\n                }\n            }\n\n            if ((owner == null ? frm.Show() : frm.Show(owner.Handle)) == NativeMethods.S_OK)\n            {\n                if (frm.GetResult(out var shellItem) == NativeMethods.S_OK)\n                {\n                    if (shellItem.GetDisplayName(NativeMethods.SIGDN_FILESYSPATH, out var pszString) == NativeMethods.S_OK)\n                    {\n                        if (pszString != IntPtr.Zero)\n                        {\n                            try\n                            {\n                                Folder = Marshal.PtrToStringAuto(pszString);\n                                return DialogResult.OK;\n                            }\n                            finally\n                            {\n                                Marshal.FreeCoTaskMem(pszString);\n                            }\n                        }\n                    }\n                }\n            }\n            return DialogResult.Cancel;\n        }\n\n        private DialogResult ShowFolderBrowserDialog(IWin32Window owner)\n        {\n            using (var frm = new FolderBrowserDialog())\n            {\n                if (InitialFolder != null)\n                {\n                    frm.SelectedPath = InitialFolder;\n                }\n#if !NETFRAMEWORK\n                if (Title != null)\n                {\n                    frm.Description = Title;\n                    frm.UseDescriptionForTitle = true;\n                }\n#endif\n                var result = owner == null ? frm.ShowDialog() : frm.ShowDialog(owner);\n                if (result == DialogResult.OK)\n                {\n                    Folder = frm.SelectedPath;\n                    return result;\n                }\n                return result;\n            }\n        }\n    }\n\n    internal static class NativeMethods\n    {\n\n        #region Constants  \n\n        public const uint FOS_PICKFOLDERS = 0x00000020;\n        public const uint FOS_FORCEFILESYSTEM = 0x00000040;\n        public const uint FOS_NOVALIDATE = 0x00000100;\n        public const uint FOS_NOTESTFILECREATE = 0x00010000;\n        public const uint FOS_DONTADDTORECENT = 0x02000000;\n\n        public const uint S_OK = 0x0000;\n\n        public const uint SIGDN_FILESYSPATH = 0x80058000;\n\n        #endregion\n\n\n        #region COM  \n\n        [ComImport, ClassInterface(ClassInterfaceType.None), TypeLibType(TypeLibTypeFlags.FCanCreate), Guid(\"DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7\")]\n        internal class FileOpenDialogRCW { }\n\n\n        [ComImport(), Guid(\"42F85136-DB7E-439C-85F1-E4075D135FC8\"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\n        internal interface IFileDialog\n        {\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            [PreserveSig()]\n            uint Show([In, Optional] IntPtr hwndOwner); //IModalWindow   \n\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetFileTypes([In] uint cFileTypes, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr rgFilterSpec);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetFileTypeIndex([In] uint iFileType);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetFileTypeIndex(out uint piFileType);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint Advise([In, MarshalAs(UnmanagedType.Interface)] IntPtr pfde, out uint pdwCookie);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint Unadvise([In] uint dwCookie);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetOptions([In] uint fos);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetOptions(out uint fos);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            void SetDefaultFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetFolder([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetCurrentSelection([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetFileName([In, MarshalAs(UnmanagedType.LPWStr)] string pszName);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetTitle([In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetOkButtonLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszText);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetFileNameLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszLabel);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetResult([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint AddPlace([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, uint fdap);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint Close([MarshalAs(UnmanagedType.Error)] uint hr);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetClientGuid([In] ref Guid guid);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint ClearClientData();\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter);\n        }\n\n\n        [ComImport, Guid(\"43826D1E-E718-42EE-BC55-A1E261C37BFE\"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\n        internal interface IShellItem\n        {\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint BindToHandler([In] IntPtr pbc, [In] ref Guid rbhid, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IntPtr ppvOut);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetDisplayName([In] uint sigdnName, out IntPtr ppszName);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint GetAttributes([In] uint sfgaoMask, out uint psfgaoAttribs);\n\n            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]\n            uint Compare([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, [In] uint hint, out int piOrder);\n        }\n\n        #endregion\n\n\n        [DllImport(\"shell32.dll\", CharSet = CharSet.Unicode, SetLastError = true)]\n        internal static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv);\n    }\n}"
  },
  {
    "path": "AssetStudioGUI/Components/TypeTreeItem.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Text;\nusing System.Windows.Forms;\nusing AssetStudio;\n\nnamespace AssetStudioGUI\n{\n    internal class TypeTreeItem : ListViewItem\n    {\n        private TypeTree m_Type;\n\n        public TypeTreeItem(int typeID, TypeTree m_Type)\n        {\n            this.m_Type = m_Type;\n            Text = m_Type.m_Nodes[0].m_Type + \" \" + m_Type.m_Nodes[0].m_Name;\n            SubItems.Add(typeID.ToString());\n        }\n\n        public override string ToString()\n        {\n            var sb = new StringBuilder();\n            foreach (var i in m_Type.m_Nodes)\n            {\n                sb.AppendFormat(\"{0}{1} {2} {3} {4}\\r\\n\", new string('\\t', i.m_Level), i.m_Type, i.m_Name, i.m_ByteSize, (i.m_MetaFlag & 0x4000) != 0);\n            }\n            return sb.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/DirectBitmap.cs",
    "content": "﻿using System;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudioGUI\n{\n    public sealed class DirectBitmap : IDisposable\n    {\n        public DirectBitmap(byte[] buff, int width, int height)\n        {\n            Width = width;\n            Height = height;\n            Bits = buff;\n            m_handle = GCHandle.Alloc(Bits, GCHandleType.Pinned);\n            m_bitmap = new Bitmap(Width, Height, Stride, PixelFormat.Format32bppArgb, m_handle.AddrOfPinnedObject());\n        }\n\n        private void Dispose(bool disposing)\n        {\n            if (disposing)\n            {\n                m_bitmap.Dispose();\n                m_handle.Free();\n            }\n            m_bitmap = null;\n        }\n\n        public void Dispose()\n        {\n            Dispose(true);\n        }\n\n        public int Height { get; }\n        public int Width { get; }\n        public int Stride => Width * 4;\n        public byte[] Bits { get; }\n        public Bitmap Bitmap => m_bitmap;\n\n        private Bitmap m_bitmap;\n        private readonly GCHandle m_handle;\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/ExportOptions.Designer.cs",
    "content": "﻿namespace AssetStudioGUI\n{\n    partial class ExportOptions\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.components = new System.ComponentModel.Container();\n            this.OKbutton = new System.Windows.Forms.Button();\n            this.Cancel = new System.Windows.Forms.Button();\n            this.groupBox1 = new System.Windows.Forms.GroupBox();\n            this.openAfterExport = new System.Windows.Forms.CheckBox();\n            this.restoreExtensionName = new System.Windows.Forms.CheckBox();\n            this.assetGroupOptions = new System.Windows.Forms.ComboBox();\n            this.label6 = new System.Windows.Forms.Label();\n            this.convertAudio = new System.Windows.Forms.CheckBox();\n            this.panel1 = new System.Windows.Forms.Panel();\n            this.totga = new System.Windows.Forms.RadioButton();\n            this.tojpg = new System.Windows.Forms.RadioButton();\n            this.topng = new System.Windows.Forms.RadioButton();\n            this.tobmp = new System.Windows.Forms.RadioButton();\n            this.converttexture = new System.Windows.Forms.CheckBox();\n            this.groupBox2 = new System.Windows.Forms.GroupBox();\n            this.exportAllUvsAsDiffuseMaps = new System.Windows.Forms.CheckBox();\n            this.exportBlendShape = new System.Windows.Forms.CheckBox();\n            this.exportAnimations = new System.Windows.Forms.CheckBox();\n            this.scaleFactor = new System.Windows.Forms.NumericUpDown();\n            this.label5 = new System.Windows.Forms.Label();\n            this.fbxFormat = new System.Windows.Forms.ComboBox();\n            this.label4 = new System.Windows.Forms.Label();\n            this.fbxVersion = new System.Windows.Forms.ComboBox();\n            this.label3 = new System.Windows.Forms.Label();\n            this.boneSize = new System.Windows.Forms.NumericUpDown();\n            this.label2 = new System.Windows.Forms.Label();\n            this.exportSkins = new System.Windows.Forms.CheckBox();\n            this.label1 = new System.Windows.Forms.Label();\n            this.filterPrecision = new System.Windows.Forms.NumericUpDown();\n            this.castToBone = new System.Windows.Forms.CheckBox();\n            this.exportAllNodes = new System.Windows.Forms.CheckBox();\n            this.eulerFilter = new System.Windows.Forms.CheckBox();\n            this.exportUvsTooltip = new System.Windows.Forms.ToolTip(this.components);\n            this.groupBox1.SuspendLayout();\n            this.panel1.SuspendLayout();\n            this.groupBox2.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.boneSize)).BeginInit();\n            ((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).BeginInit();\n            this.SuspendLayout();\n            // \n            // OKbutton\n            // \n            this.OKbutton.Location = new System.Drawing.Point(318, 351);\n            this.OKbutton.Name = \"OKbutton\";\n            this.OKbutton.Size = new System.Drawing.Size(75, 21);\n            this.OKbutton.TabIndex = 6;\n            this.OKbutton.Text = \"OK\";\n            this.OKbutton.UseVisualStyleBackColor = true;\n            this.OKbutton.Click += new System.EventHandler(this.OKbutton_Click);\n            // \n            // Cancel\n            // \n            this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;\n            this.Cancel.Location = new System.Drawing.Point(399, 351);\n            this.Cancel.Name = \"Cancel\";\n            this.Cancel.Size = new System.Drawing.Size(75, 21);\n            this.Cancel.TabIndex = 7;\n            this.Cancel.Text = \"Cancel\";\n            this.Cancel.UseVisualStyleBackColor = true;\n            this.Cancel.Click += new System.EventHandler(this.Cancel_Click);\n            // \n            // groupBox1\n            // \n            this.groupBox1.AutoSize = true;\n            this.groupBox1.Controls.Add(this.openAfterExport);\n            this.groupBox1.Controls.Add(this.restoreExtensionName);\n            this.groupBox1.Controls.Add(this.assetGroupOptions);\n            this.groupBox1.Controls.Add(this.label6);\n            this.groupBox1.Controls.Add(this.convertAudio);\n            this.groupBox1.Controls.Add(this.panel1);\n            this.groupBox1.Controls.Add(this.converttexture);\n            this.groupBox1.Location = new System.Drawing.Point(12, 12);\n            this.groupBox1.Name = \"groupBox1\";\n            this.groupBox1.Size = new System.Drawing.Size(232, 334);\n            this.groupBox1.TabIndex = 9;\n            this.groupBox1.TabStop = false;\n            this.groupBox1.Text = \"Export\";\n            // \n            // openAfterExport\n            // \n            this.openAfterExport.AutoSize = true;\n            this.openAfterExport.Checked = true;\n            this.openAfterExport.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.openAfterExport.Location = new System.Drawing.Point(6, 160);\n            this.openAfterExport.Name = \"openAfterExport\";\n            this.openAfterExport.Size = new System.Drawing.Size(168, 16);\n            this.openAfterExport.TabIndex = 10;\n            this.openAfterExport.Text = \"Open folder after export\";\n            this.openAfterExport.UseVisualStyleBackColor = true;\n            // \n            // restoreExtensionName\n            // \n            this.restoreExtensionName.AutoSize = true;\n            this.restoreExtensionName.Checked = true;\n            this.restoreExtensionName.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.restoreExtensionName.Location = new System.Drawing.Point(6, 58);\n            this.restoreExtensionName.Name = \"restoreExtensionName\";\n            this.restoreExtensionName.Size = new System.Drawing.Size(216, 16);\n            this.restoreExtensionName.TabIndex = 9;\n            this.restoreExtensionName.Text = \"Restore TextAsset extension name\";\n            this.restoreExtensionName.UseVisualStyleBackColor = true;\n            // \n            // assetGroupOptions\n            // \n            this.assetGroupOptions.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.assetGroupOptions.FormattingEnabled = true;\n            this.assetGroupOptions.Items.AddRange(new object[] {\n            \"type name\",\n            \"container path\",\n            \"source file name\",\n            \"do not group\"});\n            this.assetGroupOptions.Location = new System.Drawing.Point(6, 32);\n            this.assetGroupOptions.Name = \"assetGroupOptions\";\n            this.assetGroupOptions.Size = new System.Drawing.Size(149, 20);\n            this.assetGroupOptions.TabIndex = 8;\n            // \n            // label6\n            // \n            this.label6.AutoSize = true;\n            this.label6.Location = new System.Drawing.Point(6, 17);\n            this.label6.Name = \"label6\";\n            this.label6.Size = new System.Drawing.Size(149, 12);\n            this.label6.TabIndex = 7;\n            this.label6.Text = \"Group exported assets by\";\n            // \n            // convertAudio\n            // \n            this.convertAudio.AutoSize = true;\n            this.convertAudio.Checked = true;\n            this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.convertAudio.Location = new System.Drawing.Point(6, 138);\n            this.convertAudio.Name = \"convertAudio\";\n            this.convertAudio.Size = new System.Drawing.Size(198, 16);\n            this.convertAudio.TabIndex = 6;\n            this.convertAudio.Text = \"Convert AudioClip to WAV(PCM)\";\n            this.convertAudio.UseVisualStyleBackColor = true;\n            // \n            // panel1\n            // \n            this.panel1.Controls.Add(this.totga);\n            this.panel1.Controls.Add(this.tojpg);\n            this.panel1.Controls.Add(this.topng);\n            this.panel1.Controls.Add(this.tobmp);\n            this.panel1.Location = new System.Drawing.Point(20, 102);\n            this.panel1.Name = \"panel1\";\n            this.panel1.Size = new System.Drawing.Size(202, 30);\n            this.panel1.TabIndex = 5;\n            // \n            // totga\n            // \n            this.totga.AutoSize = true;\n            this.totga.Location = new System.Drawing.Point(150, 6);\n            this.totga.Name = \"totga\";\n            this.totga.Size = new System.Drawing.Size(41, 16);\n            this.totga.TabIndex = 2;\n            this.totga.Text = \"Tga\";\n            this.totga.UseVisualStyleBackColor = true;\n            // \n            // tojpg\n            // \n            this.tojpg.AutoSize = true;\n            this.tojpg.Location = new System.Drawing.Point(97, 6);\n            this.tojpg.Name = \"tojpg\";\n            this.tojpg.Size = new System.Drawing.Size(47, 16);\n            this.tojpg.TabIndex = 4;\n            this.tojpg.Text = \"Jpeg\";\n            this.tojpg.UseVisualStyleBackColor = true;\n            // \n            // topng\n            // \n            this.topng.AutoSize = true;\n            this.topng.Checked = true;\n            this.topng.Location = new System.Drawing.Point(50, 6);\n            this.topng.Name = \"topng\";\n            this.topng.Size = new System.Drawing.Size(41, 16);\n            this.topng.TabIndex = 3;\n            this.topng.TabStop = true;\n            this.topng.Text = \"Png\";\n            this.topng.UseVisualStyleBackColor = true;\n            // \n            // tobmp\n            // \n            this.tobmp.AutoSize = true;\n            this.tobmp.Location = new System.Drawing.Point(3, 6);\n            this.tobmp.Name = \"tobmp\";\n            this.tobmp.Size = new System.Drawing.Size(41, 16);\n            this.tobmp.TabIndex = 2;\n            this.tobmp.Text = \"Bmp\";\n            this.tobmp.UseVisualStyleBackColor = true;\n            // \n            // converttexture\n            // \n            this.converttexture.AutoSize = true;\n            this.converttexture.Checked = true;\n            this.converttexture.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.converttexture.Location = new System.Drawing.Point(6, 80);\n            this.converttexture.Name = \"converttexture\";\n            this.converttexture.Size = new System.Drawing.Size(126, 16);\n            this.converttexture.TabIndex = 1;\n            this.converttexture.Text = \"Convert Texture2D\";\n            this.converttexture.UseVisualStyleBackColor = true;\n            // \n            // groupBox2\n            // \n            this.groupBox2.AutoSize = true;\n            this.groupBox2.Controls.Add(this.exportAllUvsAsDiffuseMaps);\n            this.groupBox2.Controls.Add(this.exportBlendShape);\n            this.groupBox2.Controls.Add(this.exportAnimations);\n            this.groupBox2.Controls.Add(this.scaleFactor);\n            this.groupBox2.Controls.Add(this.label5);\n            this.groupBox2.Controls.Add(this.fbxFormat);\n            this.groupBox2.Controls.Add(this.label4);\n            this.groupBox2.Controls.Add(this.fbxVersion);\n            this.groupBox2.Controls.Add(this.label3);\n            this.groupBox2.Controls.Add(this.boneSize);\n            this.groupBox2.Controls.Add(this.label2);\n            this.groupBox2.Controls.Add(this.exportSkins);\n            this.groupBox2.Controls.Add(this.label1);\n            this.groupBox2.Controls.Add(this.filterPrecision);\n            this.groupBox2.Controls.Add(this.castToBone);\n            this.groupBox2.Controls.Add(this.exportAllNodes);\n            this.groupBox2.Controls.Add(this.eulerFilter);\n            this.groupBox2.Location = new System.Drawing.Point(250, 12);\n            this.groupBox2.Name = \"groupBox2\";\n            this.groupBox2.Size = new System.Drawing.Size(224, 334);\n            this.groupBox2.TabIndex = 11;\n            this.groupBox2.TabStop = false;\n            this.groupBox2.Text = \"Fbx\";\n            // \n            // exportAllUvsAsDiffuseMaps\n            // \n            this.exportAllUvsAsDiffuseMaps.AccessibleDescription = \"\";\n            this.exportAllUvsAsDiffuseMaps.AutoSize = true;\n            this.exportAllUvsAsDiffuseMaps.Location = new System.Drawing.Point(6, 171);\n            this.exportAllUvsAsDiffuseMaps.Name = \"exportAllUvsAsDiffuseMaps\";\n            this.exportAllUvsAsDiffuseMaps.Size = new System.Drawing.Size(204, 16);\n            this.exportAllUvsAsDiffuseMaps.TabIndex = 23;\n            this.exportAllUvsAsDiffuseMaps.Text = \"Export all UVs as diffuse maps\";\n            this.exportUvsTooltip.SetToolTip(this.exportAllUvsAsDiffuseMaps, \"Unchecked: UV1 exported as normal map. Check this if your export is missing a UV \" +\n        \"map.\");\n            this.exportAllUvsAsDiffuseMaps.UseVisualStyleBackColor = true;\n            // \n            // exportBlendShape\n            // \n            this.exportBlendShape.AutoSize = true;\n            this.exportBlendShape.Checked = true;\n            this.exportBlendShape.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.exportBlendShape.Location = new System.Drawing.Point(6, 127);\n            this.exportBlendShape.Name = \"exportBlendShape\";\n            this.exportBlendShape.Size = new System.Drawing.Size(126, 16);\n            this.exportBlendShape.TabIndex = 22;\n            this.exportBlendShape.Text = \"Export blendshape\";\n            this.exportBlendShape.UseVisualStyleBackColor = true;\n            // \n            // exportAnimations\n            // \n            this.exportAnimations.AutoSize = true;\n            this.exportAnimations.Checked = true;\n            this.exportAnimations.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.exportAnimations.Location = new System.Drawing.Point(6, 105);\n            this.exportAnimations.Name = \"exportAnimations\";\n            this.exportAnimations.Size = new System.Drawing.Size(126, 16);\n            this.exportAnimations.TabIndex = 21;\n            this.exportAnimations.Text = \"Export animations\";\n            this.exportAnimations.UseVisualStyleBackColor = true;\n            // \n            // scaleFactor\n            // \n            this.scaleFactor.DecimalPlaces = 2;\n            this.scaleFactor.Increment = new decimal(new int[] {\n            1,\n            0,\n            0,\n            131072});\n            this.scaleFactor.Location = new System.Drawing.Point(83, 224);\n            this.scaleFactor.Name = \"scaleFactor\";\n            this.scaleFactor.Size = new System.Drawing.Size(60, 21);\n            this.scaleFactor.TabIndex = 20;\n            this.scaleFactor.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;\n            this.scaleFactor.Value = new decimal(new int[] {\n            1,\n            0,\n            0,\n            0});\n            // \n            // label5\n            // \n            this.label5.AutoSize = true;\n            this.label5.Location = new System.Drawing.Point(6, 226);\n            this.label5.Name = \"label5\";\n            this.label5.Size = new System.Drawing.Size(71, 12);\n            this.label5.TabIndex = 19;\n            this.label5.Text = \"ScaleFactor\";\n            // \n            // fbxFormat\n            // \n            this.fbxFormat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.fbxFormat.FormattingEnabled = true;\n            this.fbxFormat.Items.AddRange(new object[] {\n            \"Binary\",\n            \"Ascii\"});\n            this.fbxFormat.Location = new System.Drawing.Point(77, 254);\n            this.fbxFormat.Name = \"fbxFormat\";\n            this.fbxFormat.Size = new System.Drawing.Size(61, 20);\n            this.fbxFormat.TabIndex = 18;\n            // \n            // label4\n            // \n            this.label4.AutoSize = true;\n            this.label4.Location = new System.Drawing.Point(6, 258);\n            this.label4.Name = \"label4\";\n            this.label4.Size = new System.Drawing.Size(59, 12);\n            this.label4.TabIndex = 17;\n            this.label4.Text = \"FBXFormat\";\n            // \n            // fbxVersion\n            // \n            this.fbxVersion.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            this.fbxVersion.FormattingEnabled = true;\n            this.fbxVersion.Items.AddRange(new object[] {\n            \"6.1\",\n            \"7.1\",\n            \"7.2\",\n            \"7.3\",\n            \"7.4\",\n            \"7.5\"});\n            this.fbxVersion.Location = new System.Drawing.Point(77, 284);\n            this.fbxVersion.Name = \"fbxVersion\";\n            this.fbxVersion.Size = new System.Drawing.Size(47, 20);\n            this.fbxVersion.TabIndex = 16;\n            // \n            // label3\n            // \n            this.label3.AutoSize = true;\n            this.label3.Location = new System.Drawing.Point(6, 287);\n            this.label3.Name = \"label3\";\n            this.label3.Size = new System.Drawing.Size(65, 12);\n            this.label3.TabIndex = 15;\n            this.label3.Text = \"FBXVersion\";\n            // \n            // boneSize\n            // \n            this.boneSize.Location = new System.Drawing.Point(65, 197);\n            this.boneSize.Name = \"boneSize\";\n            this.boneSize.Size = new System.Drawing.Size(46, 21);\n            this.boneSize.TabIndex = 11;\n            this.boneSize.Value = new decimal(new int[] {\n            10,\n            0,\n            0,\n            0});\n            // \n            // label2\n            // \n            this.label2.AutoSize = true;\n            this.label2.Location = new System.Drawing.Point(6, 199);\n            this.label2.Name = \"label2\";\n            this.label2.Size = new System.Drawing.Size(53, 12);\n            this.label2.TabIndex = 10;\n            this.label2.Text = \"BoneSize\";\n            // \n            // exportSkins\n            // \n            this.exportSkins.AutoSize = true;\n            this.exportSkins.Checked = true;\n            this.exportSkins.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.exportSkins.Location = new System.Drawing.Point(6, 83);\n            this.exportSkins.Name = \"exportSkins\";\n            this.exportSkins.Size = new System.Drawing.Size(96, 16);\n            this.exportSkins.TabIndex = 8;\n            this.exportSkins.Text = \"Export skins\";\n            this.exportSkins.UseVisualStyleBackColor = true;\n            // \n            // label1\n            // \n            this.label1.AutoSize = true;\n            this.label1.Location = new System.Drawing.Point(26, 39);\n            this.label1.Name = \"label1\";\n            this.label1.Size = new System.Drawing.Size(95, 12);\n            this.label1.TabIndex = 7;\n            this.label1.Text = \"FilterPrecision\";\n            // \n            // filterPrecision\n            // \n            this.filterPrecision.DecimalPlaces = 2;\n            this.filterPrecision.Increment = new decimal(new int[] {\n            1,\n            0,\n            0,\n            131072});\n            this.filterPrecision.Location = new System.Drawing.Point(127, 37);\n            this.filterPrecision.Name = \"filterPrecision\";\n            this.filterPrecision.Size = new System.Drawing.Size(51, 21);\n            this.filterPrecision.TabIndex = 6;\n            this.filterPrecision.Value = new decimal(new int[] {\n            25,\n            0,\n            0,\n            131072});\n            // \n            // castToBone\n            // \n            this.castToBone.AutoSize = true;\n            this.castToBone.Location = new System.Drawing.Point(6, 149);\n            this.castToBone.Name = \"castToBone\";\n            this.castToBone.Size = new System.Drawing.Size(156, 16);\n            this.castToBone.TabIndex = 5;\n            this.castToBone.Text = \"All nodes cast to bone\";\n            this.castToBone.UseVisualStyleBackColor = true;\n            // \n            // exportAllNodes\n            // \n            this.exportAllNodes.AutoSize = true;\n            this.exportAllNodes.Checked = true;\n            this.exportAllNodes.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.exportAllNodes.Location = new System.Drawing.Point(6, 61);\n            this.exportAllNodes.Name = \"exportAllNodes\";\n            this.exportAllNodes.Size = new System.Drawing.Size(120, 16);\n            this.exportAllNodes.TabIndex = 4;\n            this.exportAllNodes.Text = \"Export all nodes\";\n            this.exportAllNodes.UseVisualStyleBackColor = true;\n            // \n            // eulerFilter\n            // \n            this.eulerFilter.AutoSize = true;\n            this.eulerFilter.Checked = true;\n            this.eulerFilter.CheckState = System.Windows.Forms.CheckState.Checked;\n            this.eulerFilter.Location = new System.Drawing.Point(6, 20);\n            this.eulerFilter.Name = \"eulerFilter\";\n            this.eulerFilter.Size = new System.Drawing.Size(90, 16);\n            this.eulerFilter.TabIndex = 3;\n            this.eulerFilter.Text = \"EulerFilter\";\n            this.eulerFilter.UseVisualStyleBackColor = true;\n            // \n            // ExportOptions\n            // \n            this.AcceptButton = this.OKbutton;\n            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.CancelButton = this.Cancel;\n            this.ClientSize = new System.Drawing.Size(486, 384);\n            this.Controls.Add(this.groupBox2);\n            this.Controls.Add(this.groupBox1);\n            this.Controls.Add(this.Cancel);\n            this.Controls.Add(this.OKbutton);\n            this.MaximizeBox = false;\n            this.MinimizeBox = false;\n            this.Name = \"ExportOptions\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;\n            this.Text = \"Export options\";\n            this.TopMost = true;\n            this.groupBox1.ResumeLayout(false);\n            this.groupBox1.PerformLayout();\n            this.panel1.ResumeLayout(false);\n            this.panel1.PerformLayout();\n            this.groupBox2.ResumeLayout(false);\n            this.groupBox2.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.boneSize)).EndInit();\n            ((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).EndInit();\n            this.ResumeLayout(false);\n            this.PerformLayout();\n\n        }\n\n        #endregion\n        private System.Windows.Forms.Button OKbutton;\n        private System.Windows.Forms.Button Cancel;\n        private System.Windows.Forms.GroupBox groupBox1;\n        private System.Windows.Forms.CheckBox converttexture;\n        private System.Windows.Forms.RadioButton tojpg;\n        private System.Windows.Forms.RadioButton topng;\n        private System.Windows.Forms.RadioButton tobmp;\n        private System.Windows.Forms.RadioButton totga;\n        private System.Windows.Forms.CheckBox convertAudio;\n        private System.Windows.Forms.Panel panel1;\n        private System.Windows.Forms.GroupBox groupBox2;\n        private System.Windows.Forms.NumericUpDown boneSize;\n        private System.Windows.Forms.Label label2;\n        private System.Windows.Forms.CheckBox exportSkins;\n        private System.Windows.Forms.Label label1;\n        private System.Windows.Forms.NumericUpDown filterPrecision;\n        private System.Windows.Forms.CheckBox castToBone;\n        private System.Windows.Forms.CheckBox exportAllNodes;\n        private System.Windows.Forms.CheckBox eulerFilter;\n        private System.Windows.Forms.Label label3;\n        private System.Windows.Forms.ComboBox fbxVersion;\n        private System.Windows.Forms.ComboBox fbxFormat;\n        private System.Windows.Forms.Label label4;\n        private System.Windows.Forms.NumericUpDown scaleFactor;\n        private System.Windows.Forms.Label label5;\n        private System.Windows.Forms.CheckBox exportBlendShape;\n        private System.Windows.Forms.CheckBox exportAnimations;\n        private System.Windows.Forms.ComboBox assetGroupOptions;\n        private System.Windows.Forms.Label label6;\n        private System.Windows.Forms.CheckBox restoreExtensionName;\n        private System.Windows.Forms.CheckBox openAfterExport;\n        private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps;\n        private System.Windows.Forms.ToolTip exportUvsTooltip;\n    }\n}"
  },
  {
    "path": "AssetStudioGUI/ExportOptions.cs",
    "content": "﻿using AssetStudio;\nusing System;\nusing System.Windows.Forms;\n\nnamespace AssetStudioGUI\n{\n    public partial class ExportOptions : Form\n    {\n        public ExportOptions()\n        {\n            InitializeComponent();\n            assetGroupOptions.SelectedIndex = Properties.Settings.Default.assetGroupOption;\n            restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName;\n            converttexture.Checked = Properties.Settings.Default.convertTexture;\n            convertAudio.Checked = Properties.Settings.Default.convertAudio;\n            var str = Properties.Settings.Default.convertType.ToString();\n            foreach (Control c in panel1.Controls)\n            {\n                if (c.Text == str)\n                {\n                    ((RadioButton)c).Checked = true;\n                    break;\n                }\n            }\n            openAfterExport.Checked = Properties.Settings.Default.openAfterExport;\n            eulerFilter.Checked = Properties.Settings.Default.eulerFilter;\n            filterPrecision.Value = Properties.Settings.Default.filterPrecision;\n            exportAllNodes.Checked = Properties.Settings.Default.exportAllNodes;\n            exportSkins.Checked = Properties.Settings.Default.exportSkins;\n            exportAnimations.Checked = Properties.Settings.Default.exportAnimations;\n            exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape;\n            castToBone.Checked = Properties.Settings.Default.castToBone;\n            exportAllUvsAsDiffuseMaps.Checked = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;\n            boneSize.Value = Properties.Settings.Default.boneSize;\n            scaleFactor.Value = Properties.Settings.Default.scaleFactor;\n            fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;\n            fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat;\n\n        }\n\n        private void OKbutton_Click(object sender, EventArgs e)\n        {\n            Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;\n            Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;\n            Properties.Settings.Default.convertTexture = converttexture.Checked;\n            Properties.Settings.Default.convertAudio = convertAudio.Checked;\n            foreach (Control c in panel1.Controls)\n            {\n                if (((RadioButton)c).Checked)\n                {\n                    Properties.Settings.Default.convertType = (ImageFormat)Enum.Parse(typeof(ImageFormat), c.Text);\n                    break;\n                }\n            }\n            Properties.Settings.Default.openAfterExport = openAfterExport.Checked;\n            Properties.Settings.Default.eulerFilter = eulerFilter.Checked;\n            Properties.Settings.Default.filterPrecision = filterPrecision.Value;\n            Properties.Settings.Default.exportAllNodes = exportAllNodes.Checked;\n            Properties.Settings.Default.exportSkins = exportSkins.Checked;\n            Properties.Settings.Default.exportAnimations = exportAnimations.Checked;\n            Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked;\n            Properties.Settings.Default.castToBone = castToBone.Checked;\n            Properties.Settings.Default.exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps.Checked;\n            Properties.Settings.Default.boneSize = boneSize.Value;\n            Properties.Settings.Default.scaleFactor = scaleFactor.Value;\n            Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;\n            Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex;\n            Properties.Settings.Default.Save();\n            DialogResult = DialogResult.OK;\n            Close();\n        }\n\n        private void Cancel_Click(object sender, EventArgs e)\n        {\n            DialogResult = DialogResult.Cancel;\n            Close();\n        }\n\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/ExportOptions.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <metadata name=\"exportUvsTooltip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </metadata>\n</root>"
  },
  {
    "path": "AssetStudioGUI/Exporter.cs",
    "content": "﻿using AssetStudio;\nusing Newtonsoft.Json;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudioGUI\n{\n    internal static class Exporter\n    {\n        public static bool ExportTexture2D(AssetItem item, string exportPath)\n        {\n            var m_Texture2D = (Texture2D)item.Asset;\n            if (Properties.Settings.Default.convertTexture)\n            {\n                var type = Properties.Settings.Default.convertType;\n                if (!TryExportFile(exportPath, item, \".\" + type.ToString().ToLower(), out var exportFullPath))\n                    return false;\n                var image = m_Texture2D.ConvertToImage(true);\n                if (image == null)\n                    return false;\n                using (image)\n                {\n                    using (var file = File.OpenWrite(exportFullPath))\n                    {\n                        image.WriteToStream(file, type);\n                    }\n                    return true;\n                }\n            }\n            else\n            {\n                if (!TryExportFile(exportPath, item, \".tex\", out var exportFullPath))\n                    return false;\n                File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());\n                return true;\n            }\n        }\n\n        public static bool ExportAudioClip(AssetItem item, string exportPath)\n        {\n            var m_AudioClip = (AudioClip)item.Asset;\n            var m_AudioData = m_AudioClip.m_AudioData.GetData();\n            if (m_AudioData == null || m_AudioData.Length == 0)\n                return false;\n            var converter = new AudioClipConverter(m_AudioClip);\n            if (Properties.Settings.Default.convertAudio && converter.IsSupport)\n            {\n                if (!TryExportFile(exportPath, item, \".wav\", out var exportFullPath))\n                    return false;\n                var buffer = converter.ConvertToWav();\n                if (buffer == null)\n                    return false;\n                File.WriteAllBytes(exportFullPath, buffer);\n            }\n            else\n            {\n                if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out var exportFullPath))\n                    return false;\n                File.WriteAllBytes(exportFullPath, m_AudioData);\n            }\n            return true;\n        }\n\n        public static bool ExportShader(AssetItem item, string exportPath)\n        {\n            if (!TryExportFile(exportPath, item, \".shader\", out var exportFullPath))\n                return false;\n            var m_Shader = (Shader)item.Asset;\n            var str = m_Shader.Convert();\n            File.WriteAllText(exportFullPath, str);\n            return true;\n        }\n\n        public static bool ExportTextAsset(AssetItem item, string exportPath)\n        {\n            var m_TextAsset = (TextAsset)(item.Asset);\n            var extension = \".txt\";\n            if (Properties.Settings.Default.restoreExtensionName)\n            {\n                if (!string.IsNullOrEmpty(item.Container))\n                {\n                    extension = Path.GetExtension(item.Container);\n                }\n            }\n            if (!TryExportFile(exportPath, item, extension, out var exportFullPath))\n                return false;\n            File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);\n            return true;\n        }\n\n        public static bool ExportMonoBehaviour(AssetItem item, string exportPath)\n        {\n            if (!TryExportFile(exportPath, item, \".json\", out var exportFullPath))\n                return false;\n            var m_MonoBehaviour = (MonoBehaviour)item.Asset;\n            var type = m_MonoBehaviour.ToType();\n            if (type == null)\n            {\n                var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);\n                type = m_MonoBehaviour.ToType(m_Type);\n            }\n            var str = JsonConvert.SerializeObject(type, Formatting.Indented);\n            File.WriteAllText(exportFullPath, str);\n            return true;\n        }\n\n        public static bool ExportFont(AssetItem item, string exportPath)\n        {\n            var m_Font = (Font)item.Asset;\n            if (m_Font.m_FontData != null)\n            {\n                var extension = \".ttf\";\n                if (m_Font.m_FontData[0] == 79 && m_Font.m_FontData[1] == 84 && m_Font.m_FontData[2] == 84 && m_Font.m_FontData[3] == 79)\n                {\n                    extension = \".otf\";\n                }\n                if (!TryExportFile(exportPath, item, extension, out var exportFullPath))\n                    return false;\n                File.WriteAllBytes(exportFullPath, m_Font.m_FontData);\n                return true;\n            }\n            return false;\n        }\n\n        public static bool ExportMesh(AssetItem item, string exportPath)\n        {\n            var m_Mesh = (Mesh)item.Asset;\n            if (m_Mesh.m_VertexCount <= 0)\n                return false;\n            if (!TryExportFile(exportPath, item, \".obj\", out var exportFullPath))\n                return false;\n            var sb = new StringBuilder();\n            sb.AppendLine(\"g \" + m_Mesh.m_Name);\n            #region Vertices\n            if (m_Mesh.m_Vertices == null || m_Mesh.m_Vertices.Length == 0)\n            {\n                return false;\n            }\n            int c = 3;\n            if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4)\n            {\n                c = 4;\n            }\n            for (int v = 0; v < m_Mesh.m_VertexCount; v++)\n            {\n                sb.AppendFormat(\"v {0} {1} {2}\\r\\n\", -m_Mesh.m_Vertices[v * c], m_Mesh.m_Vertices[v * c + 1], m_Mesh.m_Vertices[v * c + 2]);\n            }\n            #endregion\n\n            #region UV\n            if (m_Mesh.m_UV0?.Length > 0)\n            {\n                c = 4;\n                if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)\n                {\n                    c = 2;\n                }\n                else if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 3)\n                {\n                    c = 3;\n                }\n                for (int v = 0; v < m_Mesh.m_VertexCount; v++)\n                {\n                    sb.AppendFormat(\"vt {0} {1}\\r\\n\", m_Mesh.m_UV0[v * c], m_Mesh.m_UV0[v * c + 1]);\n                }\n            }\n            #endregion\n\n            #region Normals\n            if (m_Mesh.m_Normals?.Length > 0)\n            {\n                if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3)\n                {\n                    c = 3;\n                }\n                else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4)\n                {\n                    c = 4;\n                }\n                for (int v = 0; v < m_Mesh.m_VertexCount; v++)\n                {\n                    sb.AppendFormat(\"vn {0} {1} {2}\\r\\n\", -m_Mesh.m_Normals[v * c], m_Mesh.m_Normals[v * c + 1], m_Mesh.m_Normals[v * c + 2]);\n                }\n            }\n            #endregion\n\n            #region Face\n            int sum = 0;\n            for (var i = 0; i < m_Mesh.m_SubMeshes.Length; i++)\n            {\n                sb.AppendLine($\"g {m_Mesh.m_Name}_{i}\");\n                int indexCount = (int)m_Mesh.m_SubMeshes[i].indexCount;\n                var end = sum + indexCount / 3;\n                for (int f = sum; f < end; f++)\n                {\n                    sb.AppendFormat(\"f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\\r\\n\", m_Mesh.m_Indices[f * 3 + 2] + 1, m_Mesh.m_Indices[f * 3 + 1] + 1, m_Mesh.m_Indices[f * 3] + 1);\n                }\n                sum = end;\n            }\n            #endregion\n\n            sb.Replace(\"NaN\", \"0\");\n            File.WriteAllText(exportFullPath, sb.ToString());\n            return true;\n        }\n\n        public static bool ExportVideoClip(AssetItem item, string exportPath)\n        {\n            var m_VideoClip = (VideoClip)item.Asset;\n            if (m_VideoClip.m_ExternalResources.m_Size > 0)\n            {\n                if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))\n                    return false;\n                m_VideoClip.m_VideoData.WriteData(exportFullPath);\n                return true;\n            }\n            return false;\n        }\n\n        public static bool ExportMovieTexture(AssetItem item, string exportPath)\n        {\n            var m_MovieTexture = (MovieTexture)item.Asset;\n            if (!TryExportFile(exportPath, item, \".ogv\", out var exportFullPath))\n                return false;\n            File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);\n            return true;\n        }\n\n        public static bool ExportSprite(AssetItem item, string exportPath)\n        {\n            var type = Properties.Settings.Default.convertType;\n            if (!TryExportFile(exportPath, item, \".\" + type.ToString().ToLower(), out var exportFullPath))\n                return false;\n            var image = ((Sprite)item.Asset).GetImage();\n            if (image != null)\n            {\n                using (image)\n                {\n                    using (var file = File.OpenWrite(exportFullPath))\n                    {\n                        image.WriteToStream(file, type);\n                    }\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public static bool ExportRawFile(AssetItem item, string exportPath)\n        {\n            if (!TryExportFile(exportPath, item, \".dat\", out var exportFullPath))\n                return false;\n            File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());\n            return true;\n        }\n\n        private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)\n        {\n            var fileName = FixFileName(item.Text);\n            fullPath = Path.Combine(dir, fileName + extension);\n            if (!File.Exists(fullPath))\n            {\n                Directory.CreateDirectory(dir);\n                return true;\n            }\n            fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);\n            if (!File.Exists(fullPath))\n            {\n                Directory.CreateDirectory(dir);\n                return true;\n            }\n            return false;\n        }\n\n        public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null)\n        {\n            var exportFullPath = Path.Combine(exportPath, item.Text, item.Text + \".fbx\");\n            if (File.Exists(exportFullPath))\n            {\n                exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + \".fbx\");\n            }\n            var m_Animator = (Animator)item.Asset;\n            var convert = animationList != null\n                ? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())\n                : new ModelConverter(m_Animator, Properties.Settings.Default.convertType);\n            ExportFbx(convert, exportFullPath);\n            return true;\n        }\n\n        public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)\n        {\n            var convert = animationList != null\n                ? new ModelConverter(gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())\n                : new ModelConverter(gameObject, Properties.Settings.Default.convertType);\n            exportPath = exportPath + FixFileName(gameObject.m_Name) + \".fbx\";\n            ExportFbx(convert, exportPath);\n        }\n\n        public static void ExportGameObjectMerge(List<GameObject> gameObject, string exportPath, List<AssetItem> animationList = null)\n        {\n            var rootName = Path.GetFileNameWithoutExtension(exportPath);\n            var convert = animationList != null\n                ? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())\n                : new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType);\n            ExportFbx(convert, exportPath);\n        }\n\n        private static void ExportFbx(IImported convert, string exportPath)\n        {\n            var eulerFilter = Properties.Settings.Default.eulerFilter;\n            var filterPrecision = (float)Properties.Settings.Default.filterPrecision;\n            var exportAllNodes = Properties.Settings.Default.exportAllNodes;\n            var exportSkins = Properties.Settings.Default.exportSkins;\n            var exportAnimations = Properties.Settings.Default.exportAnimations;\n            var exportBlendShape = Properties.Settings.Default.exportBlendShape;\n            var castToBone = Properties.Settings.Default.castToBone;\n            var boneSize = (int)Properties.Settings.Default.boneSize;\n            var exportAllUvsAsDiffuseMaps = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;\n            var scaleFactor = (float)Properties.Settings.Default.scaleFactor;\n            var fbxVersion = Properties.Settings.Default.fbxVersion;\n            var fbxFormat = Properties.Settings.Default.fbxFormat;\n            ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,\n                exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1);\n        }\n\n        public static bool ExportDumpFile(AssetItem item, string exportPath)\n        {\n            if (!TryExportFile(exportPath, item, \".txt\", out var exportFullPath))\n                return false;\n            var str = item.Asset.Dump();\n            if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)\n            {\n                var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);\n                str = m_MonoBehaviour.Dump(m_Type);\n            }\n            if (str != null)\n            {\n                File.WriteAllText(exportFullPath, str);\n                return true;\n            }\n            return false;\n        }\n\n        public static bool ExportConvertFile(AssetItem item, string exportPath)\n        {\n            switch (item.Type)\n            {\n                case ClassIDType.Texture2D:\n                    return ExportTexture2D(item, exportPath);\n                case ClassIDType.AudioClip:\n                    return ExportAudioClip(item, exportPath);\n                case ClassIDType.Shader:\n                    return ExportShader(item, exportPath);\n                case ClassIDType.TextAsset:\n                    return ExportTextAsset(item, exportPath);\n                case ClassIDType.MonoBehaviour:\n                    return ExportMonoBehaviour(item, exportPath);\n                case ClassIDType.Font:\n                    return ExportFont(item, exportPath);\n                case ClassIDType.Mesh:\n                    return ExportMesh(item, exportPath);\n                case ClassIDType.VideoClip:\n                    return ExportVideoClip(item, exportPath);\n                case ClassIDType.MovieTexture:\n                    return ExportMovieTexture(item, exportPath);\n                case ClassIDType.Sprite:\n                    return ExportSprite(item, exportPath);\n                case ClassIDType.Animator:\n                    return ExportAnimator(item, exportPath);\n                case ClassIDType.AnimationClip:\n                    return false;\n                default:\n                    return ExportRawFile(item, exportPath);\n            }\n        }\n\n        public static string FixFileName(string str)\n        {\n            if (str.Length >= 260) return Path.GetRandomFileName();\n            return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/GUILogger.cs",
    "content": "﻿using AssetStudio;\nusing System;\nusing System.Windows.Forms;\n\nnamespace AssetStudioGUI\n{\n    class GUILogger : ILogger\n    {\n        public bool ShowErrorMessage = true;\n        private Action<string> action;\n\n        public GUILogger(Action<string> action)\n        {\n            this.action = action;\n        }\n\n        public void Log(LoggerEvent loggerEvent, string message)\n        {\n            switch (loggerEvent)\n            {\n                case LoggerEvent.Error:\n                    if (ShowErrorMessage)\n                    {\n                        MessageBox.Show(message);\n                    }\n                    break;\n                default:\n                    action(message);\n                    break;\n            }\n\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\n\nnamespace AssetStudioGUI\n{\n    static class Program\n    {\n        /// <summary>\n        ///  The main entry point for the application.\n        /// </summary>\n        [STAThread]\n        static void Main()\n        {\n#if !NETFRAMEWORK\n            Application.SetHighDpiMode(HighDpiMode.SystemAware);\n#endif\n            Application.EnableVisualStyles();\n            Application.SetCompatibleTextRenderingDefault(false);\n            Application.Run(new AssetStudioGUIForm());\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/Properties/Resources.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace AssetStudioGUI.Properties {\n    using System;\n    \n    \n    /// <summary>\n    ///   一个强类型的资源类，用于查找本地化的字符串等。\n    /// </summary>\n    // 此类是由 StronglyTypedResourceBuilder\n    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。\n    // 若要添加或移除成员，请编辑 .ResX 文件，然后重新运行 ResGen\n    // (以 /str 作为命令选项)，或重新生成 VS 项目。\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"16.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class Resources {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal Resources() {\n        }\n        \n        /// <summary>\n        ///   返回此类使用的缓存的 ResourceManager 实例。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"AssetStudioGUI.Properties.Resources\", typeof(Resources).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   重写当前线程的 CurrentUICulture 属性，对\n        ///   使用此强类型资源类的所有资源查找执行重写。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Icon _as {\n            get {\n                object obj = ResourceManager.GetObject(\"_as\", resourceCulture);\n                return ((System.Drawing.Icon)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 #version 140\n        ///\n        ///in vec3 normal;\n        ///\n        ///out vec4 outputColor;\n        ///\n        ///void main()\n        ///{\n        ///\tvec3 unitNormal = normalize(normal);\n        ///\tfloat nDotProduct = clamp(dot(unitNormal, vec3(0.707, 0, 0.707)), 0, 1);\n        ///\tvec2 ContributionWeightsSqrt = vec2(0.5, 0.5f) + vec2(0.5f, -0.5f) * unitNormal.y;\n        ///\tvec2 ContributionWeights = ContributionWeightsSqrt * ContributionWeightsSqrt;\n        ///\n        ///\tvec3 color = nDotProduct * vec3(1, 0.957, 0.839) / 3.14159;\n        ///\tcolor += vec3(0.779, 0.716, 0.453) * ContributionWeights.y;\n        ///\tcolor += vec3(0.368, 0.477, 0. [字符串的其余部分被截断]&quot;; 的本地化字符串。\n        /// </summary>\n        internal static string fs {\n            get {\n                return ResourceManager.GetString(\"fs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 #version 140\n        ///\n        ///out vec4 outputColor;\n        ///\n        ///void main()\n        ///{\n        ///\toutputColor = vec4(0, 0, 0, 1);\n        ///} 的本地化字符串。\n        /// </summary>\n        internal static string fsBlack {\n            get {\n                return ResourceManager.GetString(\"fsBlack\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 #version 140\n        ///\n        ///out vec4 outputColor;\n        ///in vec4 color;\n        ///\n        ///void main()\n        ///{\n        ///\toutputColor = color;\n        ///} 的本地化字符串。\n        /// </summary>\n        internal static string fsColor {\n            get {\n                return ResourceManager.GetString(\"fsColor\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap preview {\n            get {\n                object obj = ResourceManager.GetObject(\"preview\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 #version 140\n        ///\n        ///in vec3 vertexPosition;\n        ///in vec3 normalDirection;\n        ///in vec4 vertexColor;\n        ///uniform mat4 modelMatrix;\n        ///uniform mat4 viewMatrix;\n        ///uniform mat4 projMatrix;\n        ///\n        ///out vec3 normal;\n        ///out vec4 color;\n        ///\n        ///void main()\n        ///{\n        ///\tgl_Position = projMatrix * viewMatrix * modelMatrix * vec4(vertexPosition, 1.0);\n        ///\tnormal = normalDirection;\n        ///\tcolor = vertexColor; \n        ///} 的本地化字符串。\n        /// </summary>\n        internal static string vs {\n            get {\n                return ResourceManager.GetString(\"vs\", resourceCulture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/Properties/Resources.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"fs\" xml:space=\"preserve\">\n    <value>#version 140\n\nin vec3 normal;\n\nout vec4 outputColor;\n\nvoid main()\n{\n\tvec3 unitNormal = normalize(normal);\n\tfloat nDotProduct = clamp(dot(unitNormal, vec3(0.707, 0, 0.707)), 0, 1);\n\tvec2 ContributionWeightsSqrt = vec2(0.5, 0.5f) + vec2(0.5f, -0.5f) * unitNormal.y;\n\tvec2 ContributionWeights = ContributionWeightsSqrt * ContributionWeightsSqrt;\n\n\tvec3 color = nDotProduct * vec3(1, 0.957, 0.839) / 3.14159;\n\tcolor += vec3(0.779, 0.716, 0.453) * ContributionWeights.y;\n\tcolor += vec3(0.368, 0.477, 0.735) * ContributionWeights.x;\n\toutputColor = vec4(sqrt(color), 1);\n}</value>\n  </data>\n  <data name=\"fsBlack\" xml:space=\"preserve\">\n    <value>#version 140\n\nout vec4 outputColor;\n\nvoid main()\n{\n\toutputColor = vec4(0, 0, 0, 1);\n}</value>\n  </data>\n  <data name=\"fsColor\" xml:space=\"preserve\">\n    <value>#version 140\n\nout vec4 outputColor;\nin vec4 color;\n\nvoid main()\n{\n\toutputColor = color;\n}</value>\n  </data>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"preview\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\Resources\\preview.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>\n  </data>\n  <data name=\"vs\" xml:space=\"preserve\">\n    <value>#version 140\n\nin vec3 vertexPosition;\nin vec3 normalDirection;\nin vec4 vertexColor;\nuniform mat4 modelMatrix;\nuniform mat4 viewMatrix;\nuniform mat4 projMatrix;\n\nout vec3 normal;\nout vec4 color;\n\nvoid main()\n{\n\tgl_Position = projMatrix * viewMatrix * modelMatrix * vec4(vertexPosition, 1.0);\n\tnormal = normalDirection;\n\tcolor = vertexColor; \n}</value>\n  </data>\n  <data name=\"_as\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\Resources\\as.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>\n  </data>\n</root>"
  },
  {
    "path": "AssetStudioGUI/Properties/Settings.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace AssetStudioGUI.Properties {\n    \n    \n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator\", \"16.10.0.0\")]\n    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {\n        \n        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));\n        \n        public static Settings Default {\n            get {\n                return defaultInstance;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"False\")]\n        public bool displayAll {\n            get {\n                return ((bool)(this[\"displayAll\"]));\n            }\n            set {\n                this[\"displayAll\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool enablePreview {\n            get {\n                return ((bool)(this[\"enablePreview\"]));\n            }\n            set {\n                this[\"enablePreview\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool displayInfo {\n            get {\n                return ((bool)(this[\"displayInfo\"]));\n            }\n            set {\n                this[\"displayInfo\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool openAfterExport {\n            get {\n                return ((bool)(this[\"openAfterExport\"]));\n            }\n            set {\n                this[\"openAfterExport\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"0\")]\n        public int assetGroupOption {\n            get {\n                return ((int)(this[\"assetGroupOption\"]));\n            }\n            set {\n                this[\"assetGroupOption\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool convertTexture {\n            get {\n                return ((bool)(this[\"convertTexture\"]));\n            }\n            set {\n                this[\"convertTexture\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool convertAudio {\n            get {\n                return ((bool)(this[\"convertAudio\"]));\n            }\n            set {\n                this[\"convertAudio\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"Png\")]\n        public global::AssetStudio.ImageFormat convertType {\n            get {\n                return ((global::AssetStudio.ImageFormat)(this[\"convertType\"]));\n            }\n            set {\n                this[\"convertType\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool eulerFilter {\n            get {\n                return ((bool)(this[\"eulerFilter\"]));\n            }\n            set {\n                this[\"eulerFilter\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"0.25\")]\n        public decimal filterPrecision {\n            get {\n                return ((decimal)(this[\"filterPrecision\"]));\n            }\n            set {\n                this[\"filterPrecision\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool exportAllNodes {\n            get {\n                return ((bool)(this[\"exportAllNodes\"]));\n            }\n            set {\n                this[\"exportAllNodes\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool exportSkins {\n            get {\n                return ((bool)(this[\"exportSkins\"]));\n            }\n            set {\n                this[\"exportSkins\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool exportAnimations {\n            get {\n                return ((bool)(this[\"exportAnimations\"]));\n            }\n            set {\n                this[\"exportAnimations\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"10\")]\n        public decimal boneSize {\n            get {\n                return ((decimal)(this[\"boneSize\"]));\n            }\n            set {\n                this[\"boneSize\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"3\")]\n        public int fbxVersion {\n            get {\n                return ((int)(this[\"fbxVersion\"]));\n            }\n            set {\n                this[\"fbxVersion\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"0\")]\n        public int fbxFormat {\n            get {\n                return ((int)(this[\"fbxFormat\"]));\n            }\n            set {\n                this[\"fbxFormat\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"1\")]\n        public decimal scaleFactor {\n            get {\n                return ((decimal)(this[\"scaleFactor\"]));\n            }\n            set {\n                this[\"scaleFactor\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool exportBlendShape {\n            get {\n                return ((bool)(this[\"exportBlendShape\"]));\n            }\n            set {\n                this[\"exportBlendShape\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"False\")]\n        public bool castToBone {\n            get {\n                return ((bool)(this[\"castToBone\"]));\n            }\n            set {\n                this[\"castToBone\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"True\")]\n        public bool restoreExtensionName {\n            get {\n                return ((bool)(this[\"restoreExtensionName\"]));\n            }\n            set {\n                this[\"restoreExtensionName\"] = value;\n            }\n        }\n        \n        [global::System.Configuration.UserScopedSettingAttribute()]\n        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n        [global::System.Configuration.DefaultSettingValueAttribute(\"False\")]\n        public bool exportAllUvsAsDiffuseMaps {\n            get {\n                return ((bool)(this[\"exportAllUvsAsDiffuseMaps\"]));\n            }\n            set {\n                this[\"exportAllUvsAsDiffuseMaps\"] = value;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioGUI/Properties/Settings.settings",
    "content": "﻿<?xml version='1.0' encoding='utf-8'?>\n<SettingsFile xmlns=\"http://schemas.microsoft.com/VisualStudio/2004/01/settings\" CurrentProfile=\"(Default)\" GeneratedClassNamespace=\"AssetStudioGUI.Properties\" GeneratedClassName=\"Settings\">\n  <Profiles />\n  <Settings>\n    <Setting Name=\"displayAll\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">False</Value>\n    </Setting>\n    <Setting Name=\"enablePreview\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"displayInfo\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"openAfterExport\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"assetGroupOption\" Type=\"System.Int32\" Scope=\"User\">\n      <Value Profile=\"(Default)\">0</Value>\n    </Setting>\n    <Setting Name=\"convertTexture\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"convertAudio\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"convertType\" Type=\"AssetStudio.ImageFormat\" Scope=\"User\">\n      <Value Profile=\"(Default)\">Png</Value>\n    </Setting>\n    <Setting Name=\"eulerFilter\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"filterPrecision\" Type=\"System.Decimal\" Scope=\"User\">\n      <Value Profile=\"(Default)\">0.25</Value>\n    </Setting>\n    <Setting Name=\"exportAllNodes\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"exportSkins\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"exportAnimations\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"boneSize\" Type=\"System.Decimal\" Scope=\"User\">\n      <Value Profile=\"(Default)\">10</Value>\n    </Setting>\n    <Setting Name=\"fbxVersion\" Type=\"System.Int32\" Scope=\"User\">\n      <Value Profile=\"(Default)\">3</Value>\n    </Setting>\n    <Setting Name=\"fbxFormat\" Type=\"System.Int32\" Scope=\"User\">\n      <Value Profile=\"(Default)\">0</Value>\n    </Setting>\n    <Setting Name=\"scaleFactor\" Type=\"System.Decimal\" Scope=\"User\">\n      <Value Profile=\"(Default)\">1</Value>\n    </Setting>\n    <Setting Name=\"exportBlendShape\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"castToBone\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">False</Value>\n    </Setting>\n    <Setting Name=\"restoreExtensionName\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">True</Value>\n    </Setting>\n    <Setting Name=\"exportAllUvsAsDiffuseMaps\" Type=\"System.Boolean\" Scope=\"User\">\n      <Value Profile=\"(Default)\">False</Value>\n    </Setting>\n  </Settings>\n</SettingsFile>"
  },
  {
    "path": "AssetStudioGUI/Studio.cs",
    "content": "﻿using AssetStudio;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\nusing System.Windows.Forms;\nusing System.Xml.Linq;\nusing static AssetStudioGUI.Exporter;\nusing Object = AssetStudio.Object;\n\nnamespace AssetStudioGUI\n{\n    internal enum ExportType\n    {\n        Convert,\n        Raw,\n        Dump\n    }\n\n    internal enum ExportFilter\n    {\n        All,\n        Selected,\n        Filtered\n    }\n\n    internal enum ExportListType\n    {\n        XML\n    }\n\n    internal static class Studio\n    {\n        public static AssetsManager assetsManager = new AssetsManager();\n        public static AssemblyLoader assemblyLoader = new AssemblyLoader();\n        public static List<AssetItem> exportableAssets = new List<AssetItem>();\n        public static List<AssetItem> visibleAssets = new List<AssetItem>();\n        internal static Action<string> StatusStripUpdate = x => { };\n\n        public static int ExtractFolder(string path, string savePath)\n        {\n            int extractedCount = 0;\n            Progress.Reset();\n            var files = Directory.GetFiles(path, \"*.*\", SearchOption.AllDirectories);\n            for (int i = 0; i < files.Length; i++)\n            {\n                var file = files[i];\n                var fileOriPath = Path.GetDirectoryName(file);\n                var fileSavePath = fileOriPath.Replace(path, savePath);\n                extractedCount += ExtractFile(file, fileSavePath);\n                Progress.Report(i + 1, files.Length);\n            }\n            return extractedCount;\n        }\n\n        public static int ExtractFile(string[] fileNames, string savePath)\n        {\n            int extractedCount = 0;\n            Progress.Reset();\n            for (var i = 0; i < fileNames.Length; i++)\n            {\n                var fileName = fileNames[i];\n                extractedCount += ExtractFile(fileName, savePath);\n                Progress.Report(i + 1, fileNames.Length);\n            }\n            return extractedCount;\n        }\n\n        public static int ExtractFile(string fileName, string savePath)\n        {\n            int extractedCount = 0;\n            var reader = new FileReader(fileName);\n            if (reader.FileType == FileType.BundleFile)\n                extractedCount += ExtractBundleFile(reader, savePath);\n            else if (reader.FileType == FileType.WebFile)\n                extractedCount += ExtractWebDataFile(reader, savePath);\n            else\n                reader.Dispose();\n            return extractedCount;\n        }\n\n        private static int ExtractBundleFile(FileReader reader, string savePath)\n        {\n            StatusStripUpdate($\"Decompressing {reader.FileName} ...\");\n            var bundleFile = new BundleFile(reader);\n            reader.Dispose();\n            if (bundleFile.fileList.Length > 0)\n            {\n                var extractPath = Path.Combine(savePath, reader.FileName + \"_unpacked\");\n                return ExtractStreamFile(extractPath, bundleFile.fileList);\n            }\n            return 0;\n        }\n\n        private static int ExtractWebDataFile(FileReader reader, string savePath)\n        {\n            StatusStripUpdate($\"Decompressing {reader.FileName} ...\");\n            var webFile = new WebFile(reader);\n            reader.Dispose();\n            if (webFile.fileList.Length > 0)\n            {\n                var extractPath = Path.Combine(savePath, reader.FileName + \"_unpacked\");\n                return ExtractStreamFile(extractPath, webFile.fileList);\n            }\n            return 0;\n        }\n\n        private static int ExtractStreamFile(string extractPath, StreamFile[] fileList)\n        {\n            int extractedCount = 0;\n            foreach (var file in fileList)\n            {\n                var filePath = Path.Combine(extractPath, file.path);\n                var fileDirectory = Path.GetDirectoryName(filePath);\n                if (!Directory.Exists(fileDirectory))\n                {\n                    Directory.CreateDirectory(fileDirectory);\n                }\n                if (!File.Exists(filePath))\n                {\n                    using (var fileStream = File.Create(filePath))\n                    {\n                        file.stream.CopyTo(fileStream);\n                    }\n                    extractedCount += 1;\n                }\n                file.stream.Dispose();\n            }\n            return extractedCount;\n        }\n\n        public static (string, List<TreeNode>) BuildAssetData()\n        {\n            StatusStripUpdate(\"Building asset list...\");\n\n            string productName = null;\n            var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);\n            var objectAssetItemDic = new Dictionary<Object, AssetItem>(objectCount);\n            var containers = new List<(PPtr<Object>, string)>();\n            int i = 0;\n            Progress.Reset();\n            foreach (var assetsFile in assetsManager.assetsFileList)\n            {\n                foreach (var asset in assetsFile.Objects)\n                {\n                    var assetItem = new AssetItem(asset);\n                    objectAssetItemDic.Add(asset, assetItem);\n                    assetItem.UniqueID = \" #\" + i;\n                    var exportable = false;\n                    switch (asset)\n                    {\n                        case GameObject m_GameObject:\n                            assetItem.Text = m_GameObject.m_Name;\n                            break;\n                        case Texture2D m_Texture2D:\n                            if (!string.IsNullOrEmpty(m_Texture2D.m_StreamData?.path))\n                                assetItem.FullSize = asset.byteSize + m_Texture2D.m_StreamData.size;\n                            assetItem.Text = m_Texture2D.m_Name;\n                            exportable = true;\n                            break;\n                        case AudioClip m_AudioClip:\n                            if (!string.IsNullOrEmpty(m_AudioClip.m_Source))\n                                assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;\n                            assetItem.Text = m_AudioClip.m_Name;\n                            exportable = true;\n                            break;\n                        case VideoClip m_VideoClip:\n                            if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))\n                                assetItem.FullSize = asset.byteSize + (long)m_VideoClip.m_ExternalResources.m_Size;\n                            assetItem.Text = m_VideoClip.m_Name;\n                            exportable = true;\n                            break;\n                        case Shader m_Shader:\n                            assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;\n                            exportable = true;\n                            break;\n                        case Mesh _:\n                        case TextAsset _:\n                        case AnimationClip _:\n                        case Font _:\n                        case MovieTexture _:\n                        case Sprite _:\n                            assetItem.Text = ((NamedObject)asset).m_Name;\n                            exportable = true;\n                            break;\n                        case Animator m_Animator:\n                            if (m_Animator.m_GameObject.TryGet(out var gameObject))\n                            {\n                                assetItem.Text = gameObject.m_Name;\n                            }\n                            exportable = true;\n                            break;\n                        case MonoBehaviour m_MonoBehaviour:\n                            if (m_MonoBehaviour.m_Name == \"\" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))\n                            {\n                                assetItem.Text = m_Script.m_ClassName;\n                            }\n                            else\n                            {\n                                assetItem.Text = m_MonoBehaviour.m_Name;\n                            }\n                            exportable = true;\n                            break;\n                        case PlayerSettings m_PlayerSettings:\n                            productName = m_PlayerSettings.productName;\n                            break;\n                        case AssetBundle m_AssetBundle:\n                            foreach (var m_Container in m_AssetBundle.m_Container)\n                            {\n                                var preloadIndex = m_Container.Value.preloadIndex;\n                                var preloadSize = m_Container.Value.preloadSize;\n                                var preloadEnd = preloadIndex + preloadSize;\n                                for (int k = preloadIndex; k < preloadEnd; k++)\n                                {\n                                    containers.Add((m_AssetBundle.m_PreloadTable[k], m_Container.Key));\n                                }\n                            }\n                            assetItem.Text = m_AssetBundle.m_Name;\n                            break;\n                        case ResourceManager m_ResourceManager:\n                            foreach (var m_Container in m_ResourceManager.m_Container)\n                            {\n                                containers.Add((m_Container.Value, m_Container.Key));\n                            }\n                            break;\n                        case NamedObject m_NamedObject:\n                            assetItem.Text = m_NamedObject.m_Name;\n                            break;\n                    }\n                    if (assetItem.Text == \"\")\n                    {\n                        assetItem.Text = assetItem.TypeString + assetItem.UniqueID;\n                    }\n                    if (Properties.Settings.Default.displayAll || exportable)\n                    {\n                        exportableAssets.Add(assetItem);\n                    }\n                    Progress.Report(++i, objectCount);\n                }\n            }\n            foreach ((var pptr, var container) in containers)\n            {\n                if (pptr.TryGet(out var obj))\n                {\n                    objectAssetItemDic[obj].Container = container;\n                }\n            }\n            foreach (var tmp in exportableAssets)\n            {\n                tmp.SetSubItems();\n            }\n            containers.Clear();\n\n            visibleAssets = exportableAssets;\n\n            StatusStripUpdate(\"Building tree structure...\");\n\n            var treeNodeCollection = new List<TreeNode>();\n            var treeNodeDictionary = new Dictionary<GameObject, GameObjectTreeNode>();\n            var assetsFileCount = assetsManager.assetsFileList.Count;\n            int j = 0;\n            Progress.Reset();\n            foreach (var assetsFile in assetsManager.assetsFileList)\n            {\n                var fileNode = new TreeNode(assetsFile.fileName); //RootNode\n\n                foreach (var obj in assetsFile.Objects)\n                {\n                    if (obj is GameObject m_GameObject)\n                    {\n                        if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))\n                        {\n                            currentNode = new GameObjectTreeNode(m_GameObject);\n                            treeNodeDictionary.Add(m_GameObject, currentNode);\n                        }\n\n                        foreach (var pptr in m_GameObject.m_Components)\n                        {\n                            if (pptr.TryGet(out var m_Component))\n                            {\n                                objectAssetItemDic[m_Component].TreeNode = currentNode;\n                                if (m_Component is MeshFilter m_MeshFilter)\n                                {\n                                    if (m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))\n                                    {\n                                        objectAssetItemDic[m_Mesh].TreeNode = currentNode;\n                                    }\n                                }\n                                else if (m_Component is SkinnedMeshRenderer m_SkinnedMeshRenderer)\n                                {\n                                    if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out var m_Mesh))\n                                    {\n                                        objectAssetItemDic[m_Mesh].TreeNode = currentNode;\n                                    }\n                                }\n                            }\n                        }\n\n                        var parentNode = fileNode;\n\n                        if (m_GameObject.m_Transform != null)\n                        {\n                            if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))\n                            {\n                                if (m_Father.m_GameObject.TryGet(out var parentGameObject))\n                                {\n                                    if (!treeNodeDictionary.TryGetValue(parentGameObject, out var parentGameObjectNode))\n                                    {\n                                        parentGameObjectNode = new GameObjectTreeNode(parentGameObject);\n                                        treeNodeDictionary.Add(parentGameObject, parentGameObjectNode);\n                                    }\n                                    parentNode = parentGameObjectNode;\n                                }\n                            }\n                        }\n\n                        parentNode.Nodes.Add(currentNode);\n                    }\n                }\n\n                if (fileNode.Nodes.Count > 0)\n                {\n                    treeNodeCollection.Add(fileNode);\n                }\n\n                Progress.Report(++j, assetsFileCount);\n            }\n            treeNodeDictionary.Clear();\n\n            objectAssetItemDic.Clear();\n\n            return (productName, treeNodeCollection);\n        }\n\n        public static Dictionary<string, SortedDictionary<int, TypeTreeItem>> BuildClassStructure()\n        {\n            var typeMap = new Dictionary<string, SortedDictionary<int, TypeTreeItem>>();\n            foreach (var assetsFile in assetsManager.assetsFileList)\n            {\n                if (typeMap.TryGetValue(assetsFile.unityVersion, out var curVer))\n                {\n                    foreach (var type in assetsFile.m_Types.Where(x => x.m_Type != null))\n                    {\n                        var key = type.classID;\n                        if (type.m_ScriptTypeIndex >= 0)\n                        {\n                            key = -1 - type.m_ScriptTypeIndex;\n                        }\n                        curVer[key] = new TypeTreeItem(key, type.m_Type);\n                    }\n                }\n                else\n                {\n                    var items = new SortedDictionary<int, TypeTreeItem>();\n                    foreach (var type in assetsFile.m_Types.Where(x => x.m_Type != null))\n                    {\n                        var key = type.classID;\n                        if (type.m_ScriptTypeIndex >= 0)\n                        {\n                            key = -1 - type.m_ScriptTypeIndex;\n                        }\n                        items[key] = new TypeTreeItem(key, type.m_Type);\n                    }\n                    typeMap.Add(assetsFile.unityVersion, items);\n                }\n            }\n\n            return typeMap;\n        }\n\n        public static void ExportAssets(string savePath, List<AssetItem> toExportAssets, ExportType exportType)\n        {\n            ThreadPool.QueueUserWorkItem(state =>\n            {\n                Thread.CurrentThread.CurrentCulture = new CultureInfo(\"en-US\");\n\n                int toExportCount = toExportAssets.Count;\n                int exportedCount = 0;\n                int i = 0;\n                Progress.Reset();\n                foreach (var asset in toExportAssets)\n                {\n                    string exportPath;\n                    switch (Properties.Settings.Default.assetGroupOption)\n                    {\n                        case 0: //type name\n                            exportPath = Path.Combine(savePath, asset.TypeString);\n                            break;\n                        case 1: //container path\n                            if (!string.IsNullOrEmpty(asset.Container))\n                            {\n                                exportPath = Path.Combine(savePath, Path.GetDirectoryName(asset.Container));\n                            }\n                            else\n                            {\n                                exportPath = savePath;\n                            }\n                            break;\n                        case 2: //source file\n                            if (string.IsNullOrEmpty(asset.SourceFile.originalPath))\n                            {\n                                exportPath = Path.Combine(savePath, asset.SourceFile.fileName + \"_export\");\n                            }\n                            else\n                            {\n                                exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + \"_export\", asset.SourceFile.fileName);\n                            }\n                            break;\n                        default:\n                            exportPath = savePath;\n                            break;\n                    }\n                    exportPath += Path.DirectorySeparatorChar;\n                    StatusStripUpdate($\"[{exportedCount}/{toExportCount}] Exporting {asset.TypeString}: {asset.Text}\");\n                    try\n                    {\n                        switch (exportType)\n                        {\n                            case ExportType.Raw:\n                                if (ExportRawFile(asset, exportPath))\n                                {\n                                    exportedCount++;\n                                }\n                                break;\n                            case ExportType.Dump:\n                                if (ExportDumpFile(asset, exportPath))\n                                {\n                                    exportedCount++;\n                                }\n                                break;\n                            case ExportType.Convert:\n                                if (ExportConvertFile(asset, exportPath))\n                                {\n                                    exportedCount++;\n                                }\n                                break;\n                        }\n                    }\n                    catch (Exception ex)\n                    {\n                        MessageBox.Show($\"Export {asset.Type}:{asset.Text} error\\r\\n{ex.Message}\\r\\n{ex.StackTrace}\");\n                    }\n\n                    Progress.Report(++i, toExportCount);\n                }\n\n                var statusText = exportedCount == 0 ? \"Nothing exported.\" : $\"Finished exporting {exportedCount} assets.\";\n\n                if (toExportCount > exportedCount)\n                {\n                    statusText += $\" {toExportCount - exportedCount} assets skipped (not extractable or files already exist)\";\n                }\n\n                StatusStripUpdate(statusText);\n\n                if (Properties.Settings.Default.openAfterExport && exportedCount > 0)\n                {\n                    OpenFolderInExplorer(savePath);\n                }\n            });\n        }\n\n        public static void ExportAssetsList(string savePath, List<AssetItem> toExportAssets, ExportListType exportListType)\n        {\n            ThreadPool.QueueUserWorkItem(state =>\n            {\n                Thread.CurrentThread.CurrentCulture = new CultureInfo(\"en-US\");\n\n                Progress.Reset();\n\n                switch (exportListType)\n                {\n                    case ExportListType.XML:\n                        var filename = Path.Combine(savePath, \"assets.xml\");\n                        var doc = new XDocument(\n                            new XElement(\"Assets\",\n                                new XAttribute(\"filename\", filename),\n                                new XAttribute(\"createdAt\", DateTime.UtcNow.ToString(\"s\")),\n                                toExportAssets.Select(\n                                    asset => new XElement(\"Asset\",\n                                        new XElement(\"Name\", asset.Text),\n                                        new XElement(\"Container\", asset.Container),\n                                        new XElement(\"Type\", new XAttribute(\"id\", (int)asset.Type), asset.TypeString),\n                                        new XElement(\"PathID\", asset.m_PathID),\n                                        new XElement(\"Source\", asset.SourceFile.fullName),\n                                        new XElement(\"Size\", asset.FullSize)\n                                    )\n                                )\n                            )\n                        );\n\n                        doc.Save(filename);\n\n                        break;\n                }\n\n                var statusText = $\"Finished exporting asset list with {toExportAssets.Count()} items.\";\n\n                StatusStripUpdate(statusText);\n\n                if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0)\n                {\n                    OpenFolderInExplorer(savePath);\n                }\n            });\n        }\n\n        public static void ExportSplitObjects(string savePath, TreeNodeCollection nodes)\n        {\n            ThreadPool.QueueUserWorkItem(state =>\n            {\n                var count = nodes.Cast<TreeNode>().Sum(x => x.Nodes.Count);\n                int k = 0;\n                Progress.Reset();\n                foreach (TreeNode node in nodes)\n                {\n                    //遍历一级子节点\n                    foreach (GameObjectTreeNode j in node.Nodes)\n                    {\n                        //收集所有子节点\n                        var gameObjects = new List<GameObject>();\n                        CollectNode(j, gameObjects);\n                        //跳过一些不需要导出的object\n                        if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))\n                        {\n                            Progress.Report(++k, count);\n                            continue;\n                        }\n                        //处理非法文件名\n                        var filename = FixFileName(j.Text);\n                        //每个文件存放在单独的文件夹\n                        var targetPath = $\"{savePath}{filename}{Path.DirectorySeparatorChar}\";\n                        //重名文件处理\n                        for (int i = 1; ; i++)\n                        {\n                            if (Directory.Exists(targetPath))\n                            {\n                                targetPath = $\"{savePath}{filename} ({i}){Path.DirectorySeparatorChar}\";\n                            }\n                            else\n                            {\n                                break;\n                            }\n                        }\n                        Directory.CreateDirectory(targetPath);\n                        //导出FBX\n                        StatusStripUpdate($\"Exporting {filename}.fbx\");\n                        try\n                        {\n                            ExportGameObject(j.gameObject, targetPath);\n                        }\n                        catch (Exception ex)\n                        {\n                            MessageBox.Show($\"Export GameObject:{j.Text} error\\r\\n{ex.Message}\\r\\n{ex.StackTrace}\");\n                        }\n\n                        Progress.Report(++k, count);\n                        StatusStripUpdate($\"Finished exporting {filename}.fbx\");\n                    }\n                }\n                if (Properties.Settings.Default.openAfterExport)\n                {\n                    OpenFolderInExplorer(savePath);\n                }\n                StatusStripUpdate(\"Finished\");\n            });\n        }\n\n        private static void CollectNode(GameObjectTreeNode node, List<GameObject> gameObjects)\n        {\n            gameObjects.Add(node.gameObject);\n            foreach (GameObjectTreeNode i in node.Nodes)\n            {\n                CollectNode(i, gameObjects);\n            }\n        }\n\n        public static void ExportAnimatorWithAnimationClip(AssetItem animator, List<AssetItem> animationList, string exportPath)\n        {\n            ThreadPool.QueueUserWorkItem(state =>\n            {\n                Progress.Reset();\n                StatusStripUpdate($\"Exporting {animator.Text}\");\n                try\n                {\n                    ExportAnimator(animator, exportPath, animationList);\n                    if (Properties.Settings.Default.openAfterExport)\n                    {\n                        OpenFolderInExplorer(exportPath);\n                    }\n                    Progress.Report(1, 1);\n                    StatusStripUpdate($\"Finished exporting {animator.Text}\");\n                }\n                catch (Exception ex)\n                {\n                    MessageBox.Show($\"Export Animator:{animator.Text} error\\r\\n{ex.Message}\\r\\n{ex.StackTrace}\");\n                    StatusStripUpdate(\"Error in export\");\n                }\n            });\n        }\n\n        public static void ExportObjectsWithAnimationClip(string exportPath, TreeNodeCollection nodes, List<AssetItem> animationList = null)\n        {\n            ThreadPool.QueueUserWorkItem(state =>\n            {\n                var gameObjects = new List<GameObject>();\n                GetSelectedParentNode(nodes, gameObjects);\n                if (gameObjects.Count > 0)\n                {\n                    var count = gameObjects.Count;\n                    int i = 0;\n                    Progress.Reset();\n                    foreach (var gameObject in gameObjects)\n                    {\n                        StatusStripUpdate($\"Exporting {gameObject.m_Name}\");\n                        try\n                        {\n                            ExportGameObject(gameObject, exportPath, animationList);\n                            StatusStripUpdate($\"Finished exporting {gameObject.m_Name}\");\n                        }\n                        catch (Exception ex)\n                        {\n                            MessageBox.Show($\"Export GameObject:{gameObject.m_Name} error\\r\\n{ex.Message}\\r\\n{ex.StackTrace}\");\n                            StatusStripUpdate(\"Error in export\");\n                        }\n\n                        Progress.Report(++i, count);\n                    }\n                    if (Properties.Settings.Default.openAfterExport)\n                    {\n                        OpenFolderInExplorer(exportPath);\n                    }\n                }\n                else\n                {\n                    StatusStripUpdate(\"No Object selected for export.\");\n                }\n            });\n        }\n\n        public static void ExportObjectsMergeWithAnimationClip(string exportPath, List<GameObject> gameObjects, List<AssetItem> animationList = null)\n        {\n            ThreadPool.QueueUserWorkItem(state =>\n            {\n                var name = Path.GetFileName(exportPath);\n                Progress.Reset();\n                StatusStripUpdate($\"Exporting {name}\");\n                try\n                {\n                    ExportGameObjectMerge(gameObjects, exportPath, animationList);\n                    Progress.Report(1, 1);\n                    StatusStripUpdate($\"Finished exporting {name}\");\n                }\n                catch (Exception ex)\n                {\n                    MessageBox.Show($\"Export Model:{name} error\\r\\n{ex.Message}\\r\\n{ex.StackTrace}\");\n                    StatusStripUpdate(\"Error in export\");\n                }\n                if (Properties.Settings.Default.openAfterExport)\n                {\n                    OpenFolderInExplorer(Path.GetDirectoryName(exportPath));\n                }\n            });\n        }\n\n        public static void GetSelectedParentNode(TreeNodeCollection nodes, List<GameObject> gameObjects)\n        {\n            foreach (TreeNode i in nodes)\n            {\n                if (i is GameObjectTreeNode gameObjectTreeNode && i.Checked)\n                {\n                    gameObjects.Add(gameObjectTreeNode.gameObject);\n                }\n                else\n                {\n                    GetSelectedParentNode(i.Nodes, gameObjects);\n                }\n            }\n        }\n\n        public static TypeTree MonoBehaviourToTypeTree(MonoBehaviour m_MonoBehaviour)\n        {\n            if (!assemblyLoader.Loaded)\n            {\n                var openFolderDialog = new OpenFolderDialog();\n                openFolderDialog.Title = \"Select Assembly Folder\";\n                if (openFolderDialog.ShowDialog() == DialogResult.OK)\n                {\n                    assemblyLoader.Load(openFolderDialog.Folder);\n                }\n                else\n                {\n                    assemblyLoader.Loaded = true;\n                }\n            }\n            return m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);\n        }\n\n        public static string DumpAsset(Object obj)\n        {\n            var str = obj.Dump();\n            if (str == null && obj is MonoBehaviour m_MonoBehaviour)\n            {\n                var type = MonoBehaviourToTypeTree(m_MonoBehaviour);\n                str = m_MonoBehaviour.Dump(type);\n            }\n            return str;\n        }\n\n        public static void OpenFolderInExplorer(string path)\n        {\n            var info = new ProcessStartInfo(path);\n            info.UseShellExecute = true;\n            Process.Start(info);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/AssemblyLoader.cs",
    "content": "﻿using Mono.Cecil;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace AssetStudio\n{\n    public class AssemblyLoader\n    {\n        public bool Loaded;\n        private Dictionary<string, ModuleDefinition> moduleDic = new Dictionary<string, ModuleDefinition>();\n\n        public void Load(string path)\n        {\n            var files = Directory.GetFiles(path, \"*.dll\");\n            var resolver = new MyAssemblyResolver();\n            var readerParameters = new ReaderParameters();\n            readerParameters.AssemblyResolver = resolver;\n            foreach (var file in files)\n            {\n                try\n                {\n                    var assembly = AssemblyDefinition.ReadAssembly(file, readerParameters);\n                    resolver.Register(assembly);\n                    moduleDic.Add(assembly.MainModule.Name, assembly.MainModule);\n                }\n                catch\n                {\n                    // ignored\n                }\n            }\n            Loaded = true;\n        }\n\n        public TypeDefinition GetTypeDefinition(string assemblyName, string fullName)\n        {\n            if (moduleDic.TryGetValue(assemblyName, out var module))\n            {\n                var typeDef = module.GetType(fullName);\n                if (typeDef == null && assemblyName == \"UnityEngine.dll\")\n                {\n                    foreach (var pair in moduleDic)\n                    {\n                        typeDef = pair.Value.GetType(fullName);\n                        if (typeDef != null)\n                        {\n                            break;\n                        }\n                    }\n                }\n                return typeDef;\n            }\n            return null;\n        }\n\n        public void Clear()\n        {\n            foreach (var pair in moduleDic)\n            {\n                pair.Value.Dispose();\n            }\n            moduleDic.Clear();\n            Loaded = false;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/AssetStudioUtility.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>\n    <Version>0.16.0.0</Version>\n    <AssemblyVersion>0.16.0.0</AssemblyVersion>\n    <FileVersion>0.16.0.0</FileVersion>\n    <Copyright>Copyright © Perfare 2018-2022</Copyright>\n    <DebugType>embedded</DebugType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Mono.Cecil\" Version=\"0.11.3\" />\n    <PackageReference Include=\"SixLabors.ImageSharp.Drawing\" Version=\"1.0.0-beta13\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\AssetStudio.PInvoke\\AssetStudio.PInvoke.csproj\" />\n    <ProjectReference Include=\"..\\AssetStudioFBXWrapper\\AssetStudioFBXWrapper.csproj\" />\n    <ProjectReference Include=\"..\\AssetStudio\\AssetStudio.csproj\" />\n    <ProjectReference Include=\"..\\Texture2DDecoderWrapper\\Texture2DDecoderWrapper.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "AssetStudioUtility/AudioClipConverter.cs",
    "content": "﻿using FMOD;\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class AudioClipConverter\n    {\n        private AudioClip m_AudioClip;\n\n        public AudioClipConverter(AudioClip audioClip)\n        {\n            m_AudioClip = audioClip;\n        }\n\n        public byte[] ConvertToWav()\n        {\n            var m_AudioData = m_AudioClip.m_AudioData.GetData();\n            if (m_AudioData == null || m_AudioData.Length == 0)\n                return null;\n            var exinfo = new CREATESOUNDEXINFO();\n            var result = Factory.System_Create(out var system);\n            if (result != RESULT.OK)\n                return null;\n            result = system.init(1, INITFLAGS.NORMAL, IntPtr.Zero);\n            if (result != RESULT.OK)\n                return null;\n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n            exinfo.length = (uint)m_AudioClip.m_Size;\n            result = system.createSound(m_AudioData, MODE.OPENMEMORY, ref exinfo, out var sound);\n            if (result != RESULT.OK)\n                return null;\n            result = sound.getNumSubSounds(out var numsubsounds);\n            if (result != RESULT.OK)\n                return null;\n            byte[] buff;\n            if (numsubsounds > 0)\n            {\n                result = sound.getSubSound(0, out var subsound);\n                if (result != RESULT.OK)\n                    return null;\n                buff = SoundToWav(subsound);\n                subsound.release();\n            }\n            else\n            {\n                buff = SoundToWav(sound);\n            }\n            sound.release();\n            system.release();\n            return buff;\n        }\n\n        public byte[] SoundToWav(Sound sound)\n        {\n            var result = sound.getFormat(out _, out _, out int channels, out int bits);\n            if (result != RESULT.OK)\n                return null;\n            result = sound.getDefaults(out var frequency, out _);\n            if (result != RESULT.OK)\n                return null;\n            var sampleRate = (int)frequency;\n            result = sound.getLength(out var length, TIMEUNIT.PCMBYTES);\n            if (result != RESULT.OK)\n                return null;\n            result = sound.@lock(0, length, out var ptr1, out var ptr2, out var len1, out var len2);\n            if (result != RESULT.OK)\n                return null;\n            byte[] buffer = new byte[len1 + 44];\n            //添加wav头\n            Encoding.UTF8.GetBytes(\"RIFF\").CopyTo(buffer, 0);\n            BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4);\n            Encoding.UTF8.GetBytes(\"WAVEfmt \").CopyTo(buffer, 8);\n            BitConverter.GetBytes(16).CopyTo(buffer, 16);\n            BitConverter.GetBytes((short)1).CopyTo(buffer, 20);\n            BitConverter.GetBytes((short)channels).CopyTo(buffer, 22);\n            BitConverter.GetBytes(sampleRate).CopyTo(buffer, 24);\n            BitConverter.GetBytes(sampleRate * channels * bits / 8).CopyTo(buffer, 28);\n            BitConverter.GetBytes((short)(channels * bits / 8)).CopyTo(buffer, 32);\n            BitConverter.GetBytes((short)bits).CopyTo(buffer, 34);\n            Encoding.UTF8.GetBytes(\"data\").CopyTo(buffer, 36);\n            BitConverter.GetBytes(len1).CopyTo(buffer, 40);\n            Marshal.Copy(ptr1, buffer, 44, (int)len1);\n            result = sound.unlock(ptr1, ptr2, len1, len2);\n            if (result != RESULT.OK)\n                return null;\n            return buffer;\n        }\n\n        public string GetExtensionName()\n        {\n            if (m_AudioClip.version[0] < 5)\n            {\n                switch (m_AudioClip.m_Type)\n                {\n                    case FMODSoundType.ACC:\n                        return \".m4a\";\n                    case FMODSoundType.AIFF:\n                        return \".aif\";\n                    case FMODSoundType.IT:\n                        return \".it\";\n                    case FMODSoundType.MOD:\n                        return \".mod\";\n                    case FMODSoundType.MPEG:\n                        return \".mp3\";\n                    case FMODSoundType.OGGVORBIS:\n                        return \".ogg\";\n                    case FMODSoundType.S3M:\n                        return \".s3m\";\n                    case FMODSoundType.WAV:\n                        return \".wav\";\n                    case FMODSoundType.XM:\n                        return \".xm\";\n                    case FMODSoundType.XMA:\n                        return \".wav\";\n                    case FMODSoundType.VAG:\n                        return \".vag\";\n                    case FMODSoundType.AUDIOQUEUE:\n                        return \".fsb\";\n                }\n\n            }\n            else\n            {\n                switch (m_AudioClip.m_CompressionFormat)\n                {\n                    case AudioCompressionFormat.PCM:\n                        return \".fsb\";\n                    case AudioCompressionFormat.Vorbis:\n                        return \".fsb\";\n                    case AudioCompressionFormat.ADPCM:\n                        return \".fsb\";\n                    case AudioCompressionFormat.MP3:\n                        return \".fsb\";\n                    case AudioCompressionFormat.PSMVAG:\n                        return \".fsb\";\n                    case AudioCompressionFormat.HEVAG:\n                        return \".fsb\";\n                    case AudioCompressionFormat.XMA:\n                        return \".fsb\";\n                    case AudioCompressionFormat.AAC:\n                        return \".m4a\";\n                    case AudioCompressionFormat.GCADPCM:\n                        return \".fsb\";\n                    case AudioCompressionFormat.ATRAC9:\n                        return \".fsb\";\n                }\n            }\n\n            return \".AudioClip\";\n        }\n\n        public bool IsSupport\n        {\n            get\n            {\n                if (m_AudioClip.version[0] < 5)\n                {\n                    switch (m_AudioClip.m_Type)\n                    {\n                        case FMODSoundType.AIFF:\n                        case FMODSoundType.IT:\n                        case FMODSoundType.MOD:\n                        case FMODSoundType.S3M:\n                        case FMODSoundType.XM:\n                        case FMODSoundType.XMA:\n                        case FMODSoundType.AUDIOQUEUE:\n                            return true;\n                        default:\n                            return false;\n                    }\n                }\n                else\n                {\n                    switch (m_AudioClip.m_CompressionFormat)\n                    {\n                        case AudioCompressionFormat.PCM:\n                        case AudioCompressionFormat.Vorbis:\n                        case AudioCompressionFormat.ADPCM:\n                        case AudioCompressionFormat.MP3:\n                        case AudioCompressionFormat.XMA:\n                            return true;\n                        default:\n                            return false;\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/CSspv/Disassembler.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace SpirV\n{\n\tpublic struct ModuleHeader\n\t{\n\t\tpublic Version Version { get; set; }\n\t\tpublic string GeneratorVendor { get; set; }\n\t\tpublic string GeneratorName { get; set; }\n\t\tpublic int GeneratorVersion { get; set; }\n\t\tpublic uint Bound { get; set; }\n\t\tpublic uint Reserved { get; set; }\n\t}\n\n\t[Flags]\n\tpublic enum DisassemblyOptions\n\t{\n\t\tNone,\n\t\tShowTypes,\n\t\tShowNames,\n\t\tDefault = ShowTypes | ShowNames\n\t}\n\n\tpublic class Disassembler\n\t{\n\t\tpublic string Disassemble (Module module)\n\t\t{\n\t\t\treturn Disassemble(module, DisassemblyOptions.Default);\n\t\t}\n\n\t\tpublic string Disassemble(Module module, DisassemblyOptions options)\n\t\t{\n\t\t\tm_sb.AppendLine(\"; SPIR-V\");\n\t\t\tm_sb.Append(\"; Version: \").Append(module.Header.Version).AppendLine();\n\t\t\tif (module.Header.GeneratorName == null)\n\t\t\t{\n\t\t\t\tm_sb.Append(\"; Generator: unknown; \").Append(module.Header.GeneratorVersion).AppendLine();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_sb.Append(\"; Generator: \").Append(module.Header.GeneratorVendor).Append(' ').\n\t\t\t\t\tAppend(module.Header.GeneratorName).Append(\"; \").Append(module.Header.GeneratorVersion).AppendLine();\n\t\t\t}\n\t\t\tm_sb.Append(\"; Bound: \").Append(module.Header.Bound).AppendLine();\n\t\t\tm_sb.Append(\"; Schema: \").Append(module.Header.Reserved).AppendLine();\n\n\t\t\tstring[] lines = new string[module.Instructions.Count + 1];\n\t\t\tlines[0] = m_sb.ToString();\n\t\t\tm_sb.Clear();\n\n\t\t\tfor (int i = 0; i < module.Instructions.Count; i++)\n\t\t\t{\n\t\t\t\tParsedInstruction instruction = module.Instructions[i];\n\t\t\t\tPrintInstruction(m_sb, instruction, options);\n\t\t\t\tlines[i + 1] = m_sb.ToString();\n\t\t\t\tm_sb.Clear();\n\t\t\t}\n\n\t\t\tint longestPrefix = 0;\n\t\t\tfor (int i = 0; i < lines.Length; i++)\n\t\t\t{\n\t\t\t\tstring line = lines[i];\n\t\t\t\tlongestPrefix = Math.Max(longestPrefix, line.IndexOf('='));\n\t\t\t\tif (longestPrefix > 50)\n\t\t\t\t{\n\t\t\t\t\tlongestPrefix = 50;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_sb.Append(lines[0]);\n\t\t\tfor (int i = 1; i < lines.Length; i++)\n\t\t\t{\n\t\t\t\tstring line = lines[i];\n\t\t\t\tint index = line.IndexOf('=');\n\t\t\t\tif (index == -1)\n\t\t\t\t{\n\t\t\t\t\tm_sb.Append(' ', longestPrefix + 4);\n\t\t\t\t\tm_sb.Append(line);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tint pad = Math.Max(0, longestPrefix - index);\n\t\t\t\t\tm_sb.Append(' ', pad);\n\t\t\t\t\tm_sb.Append(line, 0, index);\n\t\t\t\t\tm_sb.Append('=');\n\t\t\t\t\tm_sb.Append(line, index + 1, line.Length - index - 1);\n\t\t\t\t}\n\t\t\t\tm_sb.AppendLine();\n\t\t\t}\n\n\t\t\tstring result = m_sb.ToString();\n\t\t\tm_sb.Clear();\n\t\t\treturn result;\n\t\t}\n\n\t\tprivate static void PrintInstruction(StringBuilder sb, ParsedInstruction instruction, DisassemblyOptions options)\n\t\t{\n\t\t\tif (instruction.Operands.Count == 0)\n\t\t\t{\n\t\t\t\tsb.Append(instruction.Instruction.Name);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tint currentOperand = 0;\n\t\t\tif (instruction.Instruction.Operands[currentOperand].Type is IdResultType)\n\t\t\t{\n\t\t\t\tif (options.HasFlag(DisassemblyOptions.ShowTypes))\n\t\t\t\t{\n\t\t\t\t\tinstruction.ResultType.ToString(sb).Append(' ');\n\t\t\t\t}\n\t\t\t\t++currentOperand;\n\t\t\t}\n\n\t\t\tif (currentOperand < instruction.Operands.Count && instruction.Instruction.Operands[currentOperand].Type is IdResult)\n\t\t\t{\n\t\t\t\tif (!options.HasFlag(DisassemblyOptions.ShowNames) || string.IsNullOrWhiteSpace(instruction.Name))\n\t\t\t\t{\n\t\t\t\t\tPrintOperandValue(sb, instruction.Operands[currentOperand].Value, options);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsb.Append(instruction.Name);\n\t\t\t\t}\n\t\t\t\tsb.Append(\" = \");\n\n\t\t\t\t++currentOperand;\n\t\t\t}\n\n\t\t\tsb.Append(instruction.Instruction.Name);\n\t\t\tsb.Append(' ');\n\n\t\t\tfor (; currentOperand < instruction.Operands.Count; ++currentOperand)\n\t\t\t{\n\t\t\t\tPrintOperandValue(sb, instruction.Operands[currentOperand].Value, options);\n\t\t\t\tsb.Append(' ');\n\t\t\t}\n\t\t}\n\n\t\tprivate static void PrintOperandValue(StringBuilder sb, object value, DisassemblyOptions options)\n\t\t{\n\t\t\tswitch (value)\n\t\t\t{\n\t\t\t\tcase System.Type t:\n\t\t\t\t\tsb.Append(t.Name);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase string s:\n\t\t\t\t\t{\n\t\t\t\t\t\tsb.Append('\"');\n\t\t\t\t\t\tsb.Append(s);\n\t\t\t\t\t\tsb.Append('\"');\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ObjectReference or:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (options.HasFlag(DisassemblyOptions.ShowNames) && or.Reference != null && !string.IsNullOrWhiteSpace(or.Reference.Name))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsb.Append(or.Reference.Name);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tor.ToString(sb);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase IBitEnumOperandValue beov:\n\t\t\t\t\tPrintBitEnumValue(sb, beov, options);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase IValueEnumOperandValue veov:\n\t\t\t\t\tPrintValueEnumValue(sb, veov, options);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase VaryingOperandValue varOpVal:\n\t\t\t\t\tvarOpVal.ToString(sb);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tsb.Append(value);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tprivate static void PrintBitEnumValue(StringBuilder sb, IBitEnumOperandValue enumOperandValue, DisassemblyOptions options)\n\t\t{\n\t\t\tforeach (uint key in enumOperandValue.Values.Keys)\n\t\t\t{\n\t\t\t\tsb.Append(enumOperandValue.EnumerationType.GetEnumName(key));\n\t\t\t\tIReadOnlyList<object> value = enumOperandValue.Values[key];\n\t\t\t\tif (value.Count != 0)\n\t\t\t\t{\n\t\t\t\t\tsb.Append(' ');\n\t\t\t\t\tforeach (object v in value)\n\t\t\t\t\t{\n\t\t\t\t\t\tPrintOperandValue(sb, v, options);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate static void PrintValueEnumValue(StringBuilder sb, IValueEnumOperandValue valueOperandValue, DisassemblyOptions options)\n\t\t{\n\t\t\tsb.Append(valueOperandValue.Key);\n\t\t\tif (valueOperandValue.Value is IList<object> valueList && valueList.Count > 0)\n\t\t\t{\n\t\t\t\tsb.Append(' ');\n\t\t\t\tforeach (object v in valueList)\n\t\t\t\t{\n\t\t\t\t\tPrintOperandValue(sb, v, options);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate readonly StringBuilder m_sb = new StringBuilder();\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/CSspv/EnumValuesExtensions.cs",
    "content": "#if NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2 || NETSTANDARD1_3 || NETSTANDARD1_4 || NETSTANDARD1_5 || NETSTANDARD1_6\nusing System;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace SpirV\n{\n\tpublic static class EnumValuesExtensions\n\t{\n\t\tpublic static Array GetEnumValues(this System.Type _this)\n\t\t{\n\t\t\tTypeInfo typeInfo = _this.GetTypeInfo ();\n\t\t\tif (!typeInfo.IsEnum) {\n\t\t\t\tthrow new ArgumentException (\"GetEnumValues: Type '\" + _this.Name + \"' is not an enum\");\n\t\t\t}\n\n\t\t\treturn\n\t\t\t\t(\n\t\t\t\t  from field in typeInfo.DeclaredFields\n\t\t\t\t  where field.IsLiteral\n\t\t\t\t  select field.GetValue (null)\n\t\t\t\t)\n\t\t\t\t.ToArray();\n\t\t}\n\n\t\tpublic static string GetEnumName(this System.Type _this, object value)\n\t\t{\n\t\t\tTypeInfo typeInfo = _this.GetTypeInfo ();\n\t\t\tif (!typeInfo.IsEnum) {\n\t\t\t\tthrow new ArgumentException (\"GetEnumName: Type '\" + _this.Name + \"' is not an enum\");\n\t\t\t}\n\t\t\treturn\n\t\t\t\t(\n\t\t\t\t  from field in typeInfo.DeclaredFields\n\t\t\t\t  where field.IsLiteral && (uint)field.GetValue(null) == (uint)value\n\t\t\t\t  select field.Name\n\t\t\t\t)\n\t\t\t\t.First();\n\t\t}\n\t}\n}\n#endif"
  },
  {
    "path": "AssetStudioUtility/CSspv/Instruction.cs",
    "content": "using System.Collections.Generic;\n\nnamespace SpirV\n{\n\tpublic enum OperandQuantifier\n\t{\n\t\t/// <summary>\n\t\t/// 1\n\t\t/// </summary>\n\t\tDefault,\n\t\t/// <summary>\n\t\t/// 0 or 1\n\t\t/// </summary>\n\t\tOptional,\n\t\t/// <summary>\n\t\t/// 0+\n\t\t/// </summary>\n\t\tVarying\n\t}\n\n\tpublic class Operand\n\t{\n\t\tpublic Operand(OperandType kind, string name, OperandQuantifier quantifier)\n\t\t{\n\t\t\tName = name;\n\t\t\tType = kind;\n\t\t\tQuantifier = quantifier;\n\t\t}\n\n\t\tpublic string Name { get; }\n\t\tpublic OperandType Type { get; }\n\t\tpublic OperandQuantifier Quantifier { get; }\n\t}\n\n\tpublic class Instruction\n\t{\n\t\tpublic Instruction (string name)\n\t\t\t: this (name, new List<Operand> ())\n\t\t{\n\t\t}\n\n\t\tpublic Instruction (string name, IReadOnlyList<Operand> operands)\n\t\t{\n\t\t\tOperands = operands;\n\t\t\tName = name;\n\t\t}\n\n\t\tpublic string Name { get; }\n\t\tpublic IReadOnlyList<Operand> Operands { get; }\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/CSspv/LICENSE",
    "content": "BSD 2-Clause License\n\nCopyright (c) 2017, Matthäus G. Chajdas\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "AssetStudioUtility/CSspv/Module.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Runtime.InteropServices;\n\nnamespace SpirV\n{\n\tpublic class Module\n\t{\n\t\t[StructLayout(LayoutKind.Explicit)]\n\t\tprivate struct FloatUIntUnion\n\t\t{\n\t\t\t[FieldOffset(0)]\n\t\t\tpublic uint Int;\n\t\t\t[FieldOffset(0)]\n\t\t\tpublic float Float;\n\t\t}\n\n\t\t[StructLayout(LayoutKind.Explicit)]\n\t\tprivate struct DoubleULongUnion\n\t\t{\n\t\t\t[FieldOffset(0)]\n\t\t\tpublic ulong Long;\n\t\t\t[FieldOffset(0)]\n\t\t\tpublic double Double;\n\t\t}\n\n\t\tpublic Module(ModuleHeader header, IReadOnlyList<ParsedInstruction> instructions)\n\t\t{\n\t\t\tHeader = header;\n\t\t\tInstructions = instructions;\n\n\t\t\tRead(Instructions, objects_);\n\t\t}\n\n\t\tpublic static bool IsDebugInstruction(ParsedInstruction instruction)\n\t\t{\n\t\t\treturn debugInstructions_.Contains(instruction.Instruction.Name);\n\t\t}\n\n\t\tprivate static void Read(IReadOnlyList<ParsedInstruction> instructions, Dictionary<uint, ParsedInstruction> objects)\n\t\t{\n\t\t\t// Debug instructions can be only processed after everything\n\t\t\t// else has been parsed, as they may reference types which haven't\n\t\t\t// been seen in the file yet\n\t\t\tList<ParsedInstruction> debugInstructions = new List<ParsedInstruction>();\n\t\t\t// Entry points contain forward references\n\t\t\t// Those need to be resolved afterwards\n\t\t\tList<ParsedInstruction> entryPoints = new List<ParsedInstruction>();\n\t\t\t\n\t\t\tforeach (var instruction in instructions)\n\t\t\t{\n\t\t\t\tif (IsDebugInstruction(instruction))\n\t\t\t\t{\n\t\t\t\t\tdebugInstructions.Add(instruction);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (instruction.Instruction is OpEntryPoint)\n\t\t\t\t{\n\t\t\t\t\tentryPoints.Add(instruction);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (instruction.Instruction.Name.StartsWith(\"OpType\", StringComparison.Ordinal))\n\t\t\t\t{\n\t\t\t\t\tProcessTypeInstruction(instruction, objects);\n\t\t\t\t}\n\n\t\t\t\tinstruction.ResolveResultType(objects);\n\t\t\t\tif (instruction.HasResult)\n\t\t\t\t{\n\t\t\t\t\tobjects[instruction.ResultId] = instruction;\n\t\t\t\t}\n\n\t\t\t\tswitch (instruction.Instruction)\n\t\t\t\t{\n\t\t\t\t\t// Constants require that the result type has been resolved\n\t\t\t\t\tcase OpSpecConstant sc:\n\t\t\t\t\tcase OpConstant oc:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType t = instruction.ResultType;\n\t\t\t\t\t\t\tDebug.Assert (t != null);\n\t\t\t\t\t\t\tDebug.Assert (t is ScalarType);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tobject constant = ConvertConstant(instruction.ResultType as ScalarType, instruction.Words, 3);\n\t\t\t\t\t\t\tinstruction.Operands[2].Value = constant;\n\t\t\t\t\t\t\tinstruction.Value = constant;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tforeach (ParsedInstruction instruction in debugInstructions)\n\t\t\t{\n\t\t\t\tswitch (instruction.Instruction)\n\t\t\t\t{\n\t\t\t\t\tcase OpMemberName mn:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tStructType t = (StructType)objects[instruction.Words[1]].ResultType;\n\t\t\t\t\t\t\tt.SetMemberName((uint)instruction.Operands[1].Value, (string)instruction.Operands[2].Value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase OpName n:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// We skip naming objects we don't know about\n\t\t\t\t\t\t\tParsedInstruction t = objects[instruction.Words[1]];\n\t\t\t\t\t\t\tt.Name = (string)instruction.Operands[1].Value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tforeach (ParsedInstruction instruction in instructions)\n\t\t\t{\n\t\t\t\tinstruction.ResolveReferences(objects);\n\t\t\t}\n\t\t}\n\n\t\tpublic static Module ReadFrom(Stream stream)\n\t\t{\n\t\t\tBinaryReader br = new BinaryReader(stream);\n\t\t\tReader reader = new Reader(br);\n\n\t\t\tuint versionNumber = reader.ReadDWord();\n\t\t\tint majorVersion = (int)(versionNumber >> 16);\n\t\t\tint minorVersion = (int)((versionNumber >> 8) & 0xFF);\n\t\t\tVersion version = new Version(majorVersion, minorVersion);\n\n\t\t\tuint generatorMagicNumber = reader.ReadDWord();\n\t\t\tint generatorToolId = (int)(generatorMagicNumber >> 16);\n\t\t\tstring generatorVendor = \"unknown\";\n\t\t\tstring generatorName = null;\n\n\t\t\tif (Meta.Tools.ContainsKey(generatorToolId))\n\t\t\t{\n\t\t\t\tMeta.ToolInfo toolInfo = Meta.Tools[generatorToolId];\n\t\t\t\tgeneratorVendor = toolInfo.Vendor;\n\t\t\t\tif (toolInfo.Name != null)\n\t\t\t\t{\n\t\t\t\t\tgeneratorName = toolInfo.Name;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Read header\n\t\t\tModuleHeader header = new ModuleHeader();\n\t\t\theader.Version = version;\n\t\t\theader.GeneratorName = generatorName;\n\t\t\theader.GeneratorVendor = generatorVendor;\n\t\t\theader.GeneratorVersion = (int)(generatorMagicNumber & 0xFFFF);\n\t\t\theader.Bound = reader.ReadDWord();\n\t\t\theader.Reserved = reader.ReadDWord();\n\n\t\t\tList<ParsedInstruction> instructions = new List<ParsedInstruction>();\n\t\t\twhile (!reader.EndOfStream)\n\t\t\t{\n\t\t\t\tuint instructionStart = reader.ReadDWord ();\n\t\t\t\tushort wordCount = (ushort)(instructionStart >> 16);\n\t\t\t\tint opCode = (int)(instructionStart & 0xFFFF);\n\n\t\t\t\tuint[] words = new uint[wordCount];\n\t\t\t\twords[0] = instructionStart;\n\t\t\t\tfor (ushort i = 1; i < wordCount; ++i)\n\t\t\t\t{\n\t\t\t\t\twords[i] = reader.ReadDWord();\n\t\t\t\t}\n\n\t\t\t\tParsedInstruction instruction = new ParsedInstruction(opCode, words);\n\t\t\t\tinstructions.Add(instruction);\n\t\t\t}\n\n\t\t\treturn new Module(header, instructions);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Collect types from OpType* instructions\n\t\t/// </summary>\n\t\tprivate static void ProcessTypeInstruction(ParsedInstruction i, IReadOnlyDictionary<uint, ParsedInstruction> objects)\n\t\t{\n\t\t\tswitch (i.Instruction)\n\t\t\t{\n\t\t\t\tcase OpTypeInt t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new IntegerType((int)i.Words[2], i.Words[3] == 1u);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeFloat t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new FloatingPointType((int)i.Words[2]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeVector t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new VectorType((ScalarType)objects[i.Words[2]].ResultType, (int)i.Words[3]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeMatrix t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new MatrixType((VectorType)objects[i.Words[2]].ResultType, (int)i.Words[3]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeArray t:\n\t\t\t\t\t{\n\t\t\t\t\t\tobject constant = objects[i.Words[3]].Value;\n\t\t\t\t\t\tint size = 0;\n\n\t\t\t\t\t\tswitch (constant)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase ushort u16:\n\t\t\t\t\t\t\t\tsize = u16;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase uint u32:\n\t\t\t\t\t\t\t\tsize = (int)u32;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase ulong u64:\n\t\t\t\t\t\t\t\tsize = (int)u64;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase short i16:\n\t\t\t\t\t\t\t\tsize = i16;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase int i32:\n\t\t\t\t\t\t\t\tsize = i32;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase long i64:\n\t\t\t\t\t\t\t\tsize = (int)i64;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti.ResultType = new ArrayType(objects[i.Words[2]].ResultType, size);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeRuntimeArray t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new RuntimeArrayType((Type)objects[i.Words[2]].ResultType);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeBool t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new BoolType();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeOpaque t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new OpaqueType();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeVoid t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new VoidType();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeImage t:\n\t\t\t\t\t{\n\t\t\t\t\t\tType sampledType = objects[i.Operands[1].GetId ()].ResultType;\n\t\t\t\t\t\tDim dim = i.Operands[2].GetSingleEnumValue<Dim>();\n\t\t\t\t\t\tuint depth = (uint)i.Operands[3].Value;\n\t\t\t\t\t\tbool isArray = (uint)i.Operands[4].Value != 0;\n\t\t\t\t\t\tbool isMultiSampled = (uint)i.Operands[5].Value != 0;\n\t\t\t\t\t\tuint sampled = (uint)i.Operands[6].Value;\n\t\t\t\t\t\tImageFormat imageFormat = i.Operands[7].GetSingleEnumValue<ImageFormat>();\n\n\t\t\t\t\t\ti.ResultType = new ImageType(sampledType,\n\t\t\t\t\t\t\tdim,\n\t\t\t\t\t\t\t(int)depth, isArray, isMultiSampled,\n\t\t\t\t\t\t\t(int)sampled, imageFormat,\n\t\t\t\t\t\t\ti.Operands.Count > 8 ? i.Operands[8].GetSingleEnumValue<AccessQualifier>() : AccessQualifier.ReadOnly);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeSampler st:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new SamplerType();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\tcase OpTypeSampledImage t:\n\t\t\t\t\t{\n\t\t\t\t\t\ti.ResultType = new SampledImageType((ImageType)objects[i.Words[2]].ResultType);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeFunction t:\n\t\t\t\t\t{\n\t\t\t\t\t\tList<Type> parameterTypes = new List<Type>();\n\t\t\t\t\t\tfor (int j = 3; j < i.Words.Count; ++j)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tparameterTypes.Add(objects[i.Words[j]].ResultType);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ti.ResultType = new FunctionType(objects[i.Words[2]].ResultType, parameterTypes);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeForwardPointer t:\n\t\t\t\t\t{\n\t\t\t\t\t\t// We create a normal pointer, but with unspecified type\n\t\t\t\t\t\t// This will get resolved later on\n\t\t\t\t\t\ti.ResultType = new PointerType((StorageClass)i.Words[2]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypePointer t:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (objects.ContainsKey(i.Words[1]))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// If there is something present, it must have been\n\t\t\t\t\t\t\t// a forward reference. The storage type must\n\t\t\t\t\t\t\t// match\n\t\t\t\t\t\t\tPointerType pt = (PointerType)i.ResultType;\n\t\t\t\t\t\t\tDebug.Assert (pt != null);\n\t\t\t\t\t\t\tDebug.Assert (pt.StorageClass == (StorageClass)i.Words[2]);\n\t\t\t\t\t\t\tpt.ResolveForwardReference (objects[i.Words[3]].ResultType);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ti.ResultType = new PointerType((StorageClass)i.Words[2], objects[i.Words[3]].ResultType);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase OpTypeStruct t:\n\t\t\t\t\t{\n\t\t\t\t\t\tList<Type> memberTypes = new List<Type>();\n\t\t\t\t\t\tfor (int j = 2; j < i.Words.Count; ++j)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmemberTypes.Add(objects[i.Words[j]].ResultType);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ti.ResultType = new StructType(memberTypes);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tprivate static object ConvertConstant(ScalarType type, IReadOnlyList<uint> words, int index)\n\t\t{\n\t\t\tswitch (type)\n\t\t\t{\n\t\t\t\tcase IntegerType i:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (i.Signed)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (i.Width == 16)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn unchecked((short)(words[index]));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (i.Width == 32)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn unchecked((int)(words[index]));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (i.Width == 64)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn unchecked((long)(words[index] | (ulong)(words[index + 1]) << 32));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (i.Width == 16)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn unchecked((ushort)(words[index]));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (i.Width == 32)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn words[index];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (i.Width == 64)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn words[index] | (ulong)(words[index + 1]) << 32;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthrow new Exception (\"Cannot construct integer literal.\");\n\t\t\t\t\t}\n\n\t\t\t\tcase FloatingPointType f:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (f.Width == 32)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn new FloatUIntUnion { Int = words[0] }.Float;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (f.Width == 64)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn new DoubleULongUnion { Long = (words[index] | (ulong)(words[index + 1]) << 32) }.Double;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthrow new Exception(\"Cannot construct floating point literal.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tpublic ModuleHeader Header { get; }\n\t\tpublic IReadOnlyList<ParsedInstruction> Instructions { get; }\n\n\t\tprivate static HashSet<string> debugInstructions_ = new HashSet<string>\n\t\t{\n\t\t\t\"OpSourceContinued\",\n\t\t\t\"OpSource\",\n\t\t\t\"OpSourceExtension\",\n\t\t\t\"OpName\",\n\t\t\t\"OpMemberName\",\n\t\t\t\"OpString\",\n\t\t\t\"OpLine\",\n\t\t\t\"OpNoLine\",\n\t\t\t\"OpModuleProcessed\"\n\t\t};\n\n\t\tprivate readonly Dictionary<uint, ParsedInstruction> objects_ = new Dictionary<uint, ParsedInstruction>();\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/CSspv/OperandType.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace SpirV\n{\n\tpublic class OperandType\n\t{\n\t\tpublic virtual bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\t// This returns the dynamic type\n\t\t\tvalue = GetType();\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class Literal : OperandType\n\t{\n\t}\n\n\tpublic class LiteralNumber : Literal\n\t{\n\t}\n\n\t// The SPIR-V JSON file uses only literal integers\n\tpublic class LiteralInteger : LiteralNumber\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tvalue = words[index];\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class LiteralString : Literal\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\t// This is just a fail-safe -- the loop below must terminate\n\t\t\twordsUsed = 1;\n\t\t\tint bytesUsed = 0;\n\t\t\tbyte[] bytes = new byte[(words.Count - index) * 4];\n\t\t\tfor (int i = index; i < words.Count; ++i)\n\t\t\t{\n\t\t\t\tuint word = words[i];\n\t\t\t\tbyte b0 = (byte)(word & 0xFF);\n\t\t\t\tif (b0 == 0)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbytes[bytesUsed++] = b0;\n\t\t\t\t}\n\n\t\t\t\tbyte b1 = (byte)((word >> 8) & 0xFF);\n\t\t\t\tif (b1 == 0)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbytes[bytesUsed++] = b1;\n\t\t\t\t}\n\n\t\t\t\tbyte b2 = (byte)((word >> 16) & 0xFF);\n\t\t\t\tif (b2 == 0)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbytes[bytesUsed++] = b2;\n\t\t\t\t}\n\n\t\t\t\tbyte b3 = (byte)(word >> 24);\n\t\t\t\tif (b3 == 0)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbytes[bytesUsed++] = b3;\n\t\t\t\t}\n\t\t\t\twordsUsed++;\n\t\t\t}\n\n\t\t\tvalue = Encoding.UTF8.GetString(bytes, 0, bytesUsed);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class LiteralContextDependentNumber : Literal\n\t{\n\t\t// This is handled during parsing by ConvertConstant\n\t}\n\n\tpublic class LiteralExtInstInteger : Literal\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tvalue = words[index];\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class LiteralSpecConstantOpInteger : Literal\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tList<ObjectReference> result = new List<ObjectReference>();\n\t\t\tfor (int i = index; i < words.Count; i++)\n\t\t\t{\n\t\t\t\tObjectReference objRef = new ObjectReference(words[i]);\n\t\t\t\tresult.Add(objRef);\n\t\t\t}\n\n\t\t\tvalue = result;\n\t\t\twordsUsed = words.Count - index;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class Parameter\n\t{\n\t\tpublic virtual IReadOnlyList<OperandType> OperandTypes { get; }\n\t}\n\n\tpublic class ParameterFactory\n\t{\n\t\tpublic virtual Parameter CreateParameter(object value)\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic class EnumType<T> : EnumType<T, ParameterFactory>\n\t\twhere T : Enum\n\t{\n\t};\n\n\tpublic class EnumType<T, U> : OperandType\n\t\twhere T : Enum\n\t\twhere U : ParameterFactory, new ()\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tint wordsUsedForParameters = 0;\n\t\t\tif (typeof(T).GetTypeInfo().GetCustomAttributes<FlagsAttribute>().Any())\n\t\t\t{\n\t\t\t\tDictionary<uint, IReadOnlyList<object>> result = new Dictionary<uint, IReadOnlyList<object>>();\n\t\t\t\tforeach (object enumValue in EnumerationType.GetEnumValues())\n\t\t\t\t{\n\t\t\t\t\tuint bit = (uint)enumValue;\n\t\t\t\t\t// bit == 0 and words[0] == 0 handles the 0x0 = None cases\n\t\t\t\t\tif ((words[index] & bit) != 0 || (bit == 0 && words[index] == 0))\n\t\t\t\t\t{\n\t\t\t\t\t\tParameter p = parameterFactory_.CreateParameter(bit);\n\t\t\t\t\t\tif (p == null)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tresult.Add(bit, Array.Empty<object>());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tobject[] resultItems = new object[p.OperandTypes.Count];\n\t\t\t\t\t\t\tfor (int j = 0; j < p.OperandTypes.Count; ++j)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tp.OperandTypes[j].ReadValue(words, 1 + wordsUsedForParameters, out object pValue, out int pWordsUsed);\n\t\t\t\t\t\t\t\twordsUsedForParameters += pWordsUsed;\n\t\t\t\t\t\t\t\tresultItems[j] = pValue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresult.Add(bit, resultItems);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvalue = new BitEnumOperandValue<T>(result);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tobject[] resultItems;\n\t\t\t\tParameter p = parameterFactory_.CreateParameter(words[index]);\n\t\t\t\tif (p == null)\n\t\t\t\t{\n\t\t\t\t\tresultItems = Array.Empty<object>();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tresultItems = new object[p.OperandTypes.Count];\n\t\t\t\t\tfor (int j = 0; j < p.OperandTypes.Count; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tp.OperandTypes[j].ReadValue(words, 1 + wordsUsedForParameters, out object pValue, out int pWordsUsed);\n\t\t\t\t\t\twordsUsedForParameters += pWordsUsed;\n\t\t\t\t\t\tresultItems[j] = pValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvalue = new ValueEnumOperandValue<T>((T)(object)words[index], resultItems);\n\t\t\t}\n\n\t\t\twordsUsed = wordsUsedForParameters + 1;\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic System.Type EnumerationType => typeof(T);\n\n\t\tprivate U parameterFactory_ = new U();\n\t}\n\n\tpublic class IdScope : OperandType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tvalue = (Scope)words[index];\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class IdMemorySemantics : OperandType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tvalue = (MemorySemantics)words[index];\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class IdType : OperandType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tvalue = words[index];\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class IdResult : IdType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tvalue = new ObjectReference(words[index]);\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class IdResultType : IdType\n\t{\n\t}\n\n\tpublic class IdRef : IdType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tvalue = new ObjectReference(words[index]);\n\t\t\twordsUsed = 1;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class PairIdRefIdRef : OperandType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tObjectReference variable = new ObjectReference(words[index]);\n\t\t\tObjectReference parent = new ObjectReference(words[index + 1]);\n\t\t\tvalue = new { Variable = variable, Parent = parent };\n\t\t\twordsUsed = 2;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class PairIdRefLiteralInteger : OperandType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tObjectReference type = new ObjectReference(words[index]);\n\t\t\tuint word = words[index + 1];\n\t\t\tvalue = new { Type = type, Member = word };\n\t\t\twordsUsed = 2;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic class PairLiteralIntegerIdRef : OperandType\n\t{\n\t\tpublic override bool ReadValue(IReadOnlyList<uint> words, int index, out object value, out int wordsUsed)\n\t\t{\n\t\t\tuint selector = words[index];\n\t\t\tObjectReference label = new ObjectReference(words[index + 1]);\n\t\t\tvalue = new { Selector = selector, Label = label };\n\t\t\twordsUsed = 2;\n\t\t\treturn true;\n\t\t}\n\t}\n}"
  },
  {
    "path": "AssetStudioUtility/CSspv/ParsedInstruction.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace SpirV\n{\n\tpublic class ParsedOperand\n\t{\n\t\tpublic ParsedOperand(IReadOnlyList<uint> words, int index, int count, object value, Operand operand)\n\t\t{\n\t\t\tuint[] array = new uint[count];\n\t\t\tfor (int i = 0; i < count; i++)\n\t\t\t{\n\t\t\t\tarray[i] = words[index + i];\n\t\t\t}\n\n\t\t\tWords = array;\n\t\t\tValue = value;\n\t\t\tOperand = operand;\n\t\t}\n\n\t\tpublic T GetSingleEnumValue<T>()\n\t\t\twhere T : Enum\n\t\t{\n\t\t\tIValueEnumOperandValue v = (IValueEnumOperandValue)Value;\n\t\t\tif (v.Value.Count == 0)\n\t\t\t{\n\t\t\t\t// If there's no value at all, the enum is probably something like ImageFormat.\n\t\t\t\t// In which case we just return the enum value\n\t\t\t\treturn (T)v.Key;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// This means the enum has a value attached to it, so we return the attached value\n\t\t\t\treturn (T)((IValueEnumOperandValue)Value).Value[0];\n\t\t\t}\n\t\t}\n\n\t\tpublic uint GetId()\n\t\t{\n\t\t\treturn ((ObjectReference)Value).Id;\n\t\t}\n\n\t\tpublic T GetBitEnumValue<T>()\n\t\t\twhere T : Enum\n\t\t{\n\t\t\tvar v = Value as IBitEnumOperandValue;\n\n\t\t\tuint result = 0;\n\t\t\tforeach (var k in v.Values.Keys)\n\t\t\t{\n\t\t\t\tresult |= k;\n\t\t\t}\n\n\t\t\treturn (T)(object)result;\n\t\t}\n\n\t\tpublic IReadOnlyList<uint> Words { get; }\n\t\tpublic object Value { get; set; }\n\t\tpublic Operand Operand { get; }\n\t}\n\n\tpublic class VaryingOperandValue\n\t{\n\t\tpublic VaryingOperandValue(IReadOnlyList<object> values)\n\t\t{\n\t\t\tValues = values;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\tToString(sb);\n\t\t\treturn sb.ToString();\n\t\t}\n\n\t\tpublic StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\tfor (int i = 0; i < Values.Count; ++i)\n\t\t\t{\n\t\t\t\tif (Values[i] is ObjectReference objRef)\n\t\t\t\t{\n\t\t\t\t\tobjRef.ToString(sb);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsb.Append(Values[i]);\n\t\t\t\t}\n\t\t\t\tif (i < (Values.Count - 1))\n\t\t\t\t{\n\t\t\t\t\tsb.Append(' ');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn sb;\n\t\t}\n\n\t\tpublic IReadOnlyList<object> Values { get; }\n\t}\n\n\tpublic interface IEnumOperandValue\n\t{\n\t\tSystem.Type EnumerationType { get; }\n\t}\n\n\tpublic interface IBitEnumOperandValue : IEnumOperandValue\n\t{\n\t\tIReadOnlyDictionary<uint, IReadOnlyList<object>> Values { get; }\n\t}\n\n\tpublic interface IValueEnumOperandValue : IEnumOperandValue\n\t{\n\t\tobject Key { get; }\n\t\tIReadOnlyList<object> Value { get; }\n\t}\n\n\tpublic class ValueEnumOperandValue<T> : IValueEnumOperandValue\n\t\twhere T : Enum\n\t{\n\t\tpublic ValueEnumOperandValue(T key, IReadOnlyList<object> value)\n\t\t{\n\t\t\tKey = key;\n\t\t\tValue = value;\n\t\t}\n\n\t\tpublic System.Type EnumerationType => typeof(T);\n\t\tpublic object Key { get; }\n\t\tpublic IReadOnlyList<object> Value { get; }\n\t}\n\n\tpublic class BitEnumOperandValue<T> : IBitEnumOperandValue\n\t\twhere T : Enum\n\t{\n\t\tpublic BitEnumOperandValue(Dictionary<uint, IReadOnlyList<object>> values)\n\t\t{\n\t\t\tValues = values;\n\t\t}\n\n\t\tpublic IReadOnlyDictionary<uint, IReadOnlyList<object>> Values { get; }\n\t\tpublic System.Type EnumerationType => typeof(T);\n\t}\n\n\tpublic class ObjectReference\n\t{\n\t\tpublic ObjectReference(uint id)\n\t\t{\n\t\t\tId = id;\n\t\t}\n\n\t\tpublic void Resolve(IReadOnlyDictionary<uint, ParsedInstruction> objects)\n\t\t{\n\t\t\tReference = objects[Id];\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn $\"%{Id}\";\n\t\t}\n\n\t\tpublic StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn sb.Append('%').Append(Id);\n\t\t}\n\n\t\tpublic uint Id { get; }\n\t\tpublic ParsedInstruction Reference { get; private set; }\n\t}\n\n\tpublic class ParsedInstruction\n\t{\n\t\tpublic ParsedInstruction(int opCode, IReadOnlyList<uint> words)\n\t\t{\n\t\t\tWords = words;\n\t\t\tInstruction = Instructions.OpcodeToInstruction[opCode];\n\t\t\tParseOperands();\n\t\t}\n\n\t\tprivate void ParseOperands()\n\t\t{\n\t\t\tif (Instruction.Operands.Count == 0)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Word 0 describes this instruction so we can ignore it\n\t\t\tint currentWord = 1;\n\t\t\tint currentOperand = 0;\n\t\t\tList<object> varyingOperandValues = new List<object>();\n\t\t\tint varyingWordStart = 0;\n\t\t\tOperand varyingOperand = null;\n\n\t\t\twhile (currentWord < Words.Count)\n\t\t\t{\n\t\t\t\tOperand operand = Instruction.Operands[currentOperand];\n\t\t\t\toperand.Type.ReadValue(Words, currentWord, out object value, out int wordsUsed);\n\t\t\t\tif (operand.Quantifier == OperandQuantifier.Varying)\n\t\t\t\t{\n\t\t\t\t\tvaryingOperandValues.Add(value);\n\t\t\t\t\tvaryingWordStart = currentWord;\n\t\t\t\t\tvaryingOperand = operand;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tint wordCount = Math.Min(Words.Count - currentWord, wordsUsed);\n\t\t\t\t\tParsedOperand parsedOperand = new ParsedOperand(Words, currentWord, wordCount, value, operand);\n\t\t\t\t\tOperands.Add(parsedOperand);\n\t\t\t\t}\n\n\t\t\t\tcurrentWord += wordsUsed;\n\t\t\t\tif (operand.Quantifier != OperandQuantifier.Varying)\n\t\t\t\t{\n\t\t\t\t\t++currentOperand;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (varyingOperand != null)\n\t\t\t{\n\t\t\t\tVaryingOperandValue varOperantValue = new VaryingOperandValue(varyingOperandValues);\n\t\t\t\tParsedOperand parsedOperand = new ParsedOperand(Words, currentWord, Words.Count - currentWord, varOperantValue, varyingOperand);\n\t\t\t\tOperands.Add(parsedOperand);\n\t\t\t}\n\t\t}\n\n\t\tpublic void ResolveResultType(IReadOnlyDictionary<uint, ParsedInstruction> objects)\n\t\t{\n\t\t\tif (Instruction.Operands.Count > 0 && Instruction.Operands[0].Type is IdResultType)\n\t\t\t{\n\t\t\t\tResultType = objects[(uint)Operands[0].Value].ResultType;\n\t\t\t}\n\t\t}\n\n\t\tpublic void ResolveReferences (IReadOnlyDictionary<uint, ParsedInstruction> objects)\n\t\t{\n\t\t\tforeach (var operand in Operands)\n\t\t\t{\n\t\t\t\tif (operand.Value is ObjectReference objectReference)\n\t\t\t\t{\n\t\t\t\t\tobjectReference.Resolve (objects);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic Type ResultType { get; set; }\n\t\tpublic uint ResultId\n\t\t{\n\t\t\tget\n\t\t\t{\n\t\t\t\tfor (int i = 0; i < Instruction.Operands.Count; ++i)\n\t\t\t\t{\n\t\t\t\t\tif (Instruction.Operands[i].Type is IdResult)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn Operands[i].GetId();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t\tpublic bool HasResult => ResultId != 0;\n\n\t\tpublic IReadOnlyList<uint> Words { get; }\n\t\tpublic Instruction Instruction { get; }\n\t\tpublic IList<ParsedOperand> Operands { get; } = new List<ParsedOperand>();\n\t\tpublic string Name { get; set; }\n\t\tpublic object Value { get; set; }\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/CSspv/Reader.cs",
    "content": "using System;\nusing System.IO;\nusing System.Runtime.CompilerServices;\n\nnamespace SpirV\n{\n\tinternal sealed class Reader\n\t{\n\t\tpublic Reader(BinaryReader reader)\n\t\t{\n\t\t\treader_ = reader;\n\t\t\tuint magicNumber = reader_.ReadUInt32();\n\t\t\tif (magicNumber == Meta.MagicNumber)\n\t\t\t{\n\t\t\t\tlittleEndian_ = true;\n\t\t\t}\n\t\t\telse if (Reverse(magicNumber) == Meta.MagicNumber)\n\t\t\t{\n\t\t\t\tlittleEndian_ = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow new Exception(\"Invalid magic number\");\n\t\t\t}\n\t\t}\n\n\t\tpublic uint ReadDWord()\n\t\t{\n\t\t\tif (littleEndian_)\n\t\t\t{\n\t\t\t\treturn reader_.ReadUInt32 ();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn Reverse(reader_.ReadUInt32());\n\t\t\t}\n\t\t}\n\n\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]\n\t\tprivate static uint Reverse(uint u)\n\t\t{\n\t\t\treturn (u << 24) | (u & 0xFF00U) << 8 | (u >> 8) & 0xFF00U | (u >> 24);\n\t\t}\n\n\t\tpublic bool EndOfStream => reader_.BaseStream.Position == reader_.BaseStream.Length;\n\n\t\tprivate readonly BinaryReader reader_;\n\t\tprivate readonly bool littleEndian_;\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/CSspv/SpirV.Core.Grammar.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace SpirV\n{\n    [Flags]\n    public enum ImageOperands : uint\n    {\n        None = 0,\n        Bias = 1,\n        Lod = 2,\n        Grad = 4,\n        ConstOffset = 8,\n        Offset = 16,\n        ConstOffsets = 32,\n        Sample = 64,\n        MinLod = 128,\n    }\n    public class ImageOperandsParameterFactory : ParameterFactory\n    {\n        public class BiasParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class LodParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class GradParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), new IdRef(), };\n        }\n\n        public class ConstOffsetParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class OffsetParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class ConstOffsetsParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class SampleParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class MinLodParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public override Parameter CreateParameter(object value)\n        {\n            switch ((ImageOperands)value)\n            {\n                case ImageOperands.Bias:\n                    return new BiasParameter();\n                case ImageOperands.Lod:\n                    return new LodParameter();\n                case ImageOperands.Grad:\n                    return new GradParameter();\n                case ImageOperands.ConstOffset:\n                    return new ConstOffsetParameter();\n                case ImageOperands.Offset:\n                    return new OffsetParameter();\n                case ImageOperands.ConstOffsets:\n                    return new ConstOffsetsParameter();\n                case ImageOperands.Sample:\n                    return new SampleParameter();\n                case ImageOperands.MinLod:\n                    return new MinLodParameter();\n            }\n\n            return null;\n        }\n    }\n    [Flags]\n    public enum FPFastMathMode : uint\n    {\n        None = 0,\n        NotNaN = 1,\n        NotInf = 2,\n        NSZ = 4,\n        AllowRecip = 8,\n        Fast = 16,\n    }\n    public class FPFastMathModeParameterFactory : ParameterFactory\n    {\n    }\n    [Flags]\n    public enum SelectionControl : uint\n    {\n        None = 0,\n        Flatten = 1,\n        DontFlatten = 2,\n    }\n    public class SelectionControlParameterFactory : ParameterFactory\n    {\n    }\n    [Flags]\n    public enum LoopControl : uint\n    {\n        None = 0,\n        Unroll = 1,\n        DontUnroll = 2,\n        DependencyInfinite = 4,\n        DependencyLength = 8,\n    }\n    public class LoopControlParameterFactory : ParameterFactory\n    {\n        public class DependencyLengthParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public override Parameter CreateParameter(object value)\n        {\n            switch ((LoopControl)value)\n            {\n                case LoopControl.DependencyLength:\n                    return new DependencyLengthParameter();\n            }\n\n            return null;\n        }\n    }\n    [Flags]\n    public enum FunctionControl : uint\n    {\n        None = 0,\n        Inline = 1,\n        DontInline = 2,\n        Pure = 4,\n        Const = 8,\n    }\n    public class FunctionControlParameterFactory : ParameterFactory\n    {\n    }\n    [Flags]\n    public enum MemorySemantics : uint\n    {\n        Relaxed = 0,\n        None = 0,\n        Acquire = 2,\n        Release = 4,\n        AcquireRelease = 8,\n        SequentiallyConsistent = 16,\n        UniformMemory = 64,\n        SubgroupMemory = 128,\n        WorkgroupMemory = 256,\n        CrossWorkgroupMemory = 512,\n        AtomicCounterMemory = 1024,\n        ImageMemory = 2048,\n    }\n    public class MemorySemanticsParameterFactory : ParameterFactory\n    {\n    }\n    [Flags]\n    public enum MemoryAccess : uint\n    {\n        None = 0,\n        Volatile = 1,\n        Aligned = 2,\n        Nontemporal = 4,\n    }\n    public class MemoryAccessParameterFactory : ParameterFactory\n    {\n        public class AlignedParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public override Parameter CreateParameter(object value)\n        {\n            switch ((MemoryAccess)value)\n            {\n                case MemoryAccess.Aligned:\n                    return new AlignedParameter();\n            }\n\n            return null;\n        }\n    }\n    [Flags]\n    public enum KernelProfilingInfo : uint\n    {\n        None = 0,\n        CmdExecTime = 1,\n    }\n    public class KernelProfilingInfoParameterFactory : ParameterFactory\n    {\n    }\n    public enum SourceLanguage : uint\n    {\n        Unknown = 0,\n        ESSL = 1,\n        GLSL = 2,\n        OpenCL_C = 3,\n        OpenCL_CPP = 4,\n        HLSL = 5,\n    }\n    public class SourceLanguageParameterFactory : ParameterFactory\n    {\n    }\n    public enum ExecutionModel : uint\n    {\n        Vertex = 0,\n        TessellationControl = 1,\n        TessellationEvaluation = 2,\n        Geometry = 3,\n        Fragment = 4,\n        GLCompute = 5,\n        Kernel = 6,\n    }\n    public class ExecutionModelParameterFactory : ParameterFactory\n    {\n    }\n    public enum AddressingModel : uint\n    {\n        Logical = 0,\n        Physical32 = 1,\n        Physical64 = 2,\n    }\n    public class AddressingModelParameterFactory : ParameterFactory\n    {\n    }\n    public enum MemoryModel : uint\n    {\n        Simple = 0,\n        GLSL450 = 1,\n        OpenCL = 2,\n    }\n    public class MemoryModelParameterFactory : ParameterFactory\n    {\n    }\n    public enum ExecutionMode : uint\n    {\n        Invocations = 0,\n        SpacingEqual = 1,\n        SpacingFractionalEven = 2,\n        SpacingFractionalOdd = 3,\n        VertexOrderCw = 4,\n        VertexOrderCcw = 5,\n        PixelCenterInteger = 6,\n        OriginUpperLeft = 7,\n        OriginLowerLeft = 8,\n        EarlyFragmentTests = 9,\n        PointMode = 10,\n        Xfb = 11,\n        DepthReplacing = 12,\n        DepthGreater = 14,\n        DepthLess = 15,\n        DepthUnchanged = 16,\n        LocalSize = 17,\n        LocalSizeHint = 18,\n        InputPoints = 19,\n        InputLines = 20,\n        InputLinesAdjacency = 21,\n        Triangles = 22,\n        InputTrianglesAdjacency = 23,\n        Quads = 24,\n        Isolines = 25,\n        OutputVertices = 26,\n        OutputPoints = 27,\n        OutputLineStrip = 28,\n        OutputTriangleStrip = 29,\n        VecTypeHint = 30,\n        ContractionOff = 31,\n        Initializer = 33,\n        Finalizer = 34,\n        SubgroupSize = 35,\n        SubgroupsPerWorkgroup = 36,\n        SubgroupsPerWorkgroupId = 37,\n        LocalSizeId = 38,\n        LocalSizeHintId = 39,\n        PostDepthCoverage = 4446,\n        StencilRefReplacingEXT = 5027,\n    }\n    public class ExecutionModeParameterFactory : ParameterFactory\n    {\n        public class InvocationsParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class LocalSizeParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), new LiteralInteger(), new LiteralInteger(), };\n        }\n\n        public class LocalSizeHintParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), new LiteralInteger(), new LiteralInteger(), };\n        }\n\n        public class OutputVerticesParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class VecTypeHintParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class SubgroupSizeParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class SubgroupsPerWorkgroupParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class SubgroupsPerWorkgroupIdParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class LocalSizeIdParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), new IdRef(), new IdRef(), };\n        }\n\n        public class LocalSizeHintIdParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public override Parameter CreateParameter(object value)\n        {\n            switch ((ExecutionMode)value)\n            {\n                case ExecutionMode.Invocations:\n                    return new InvocationsParameter();\n                case ExecutionMode.LocalSize:\n                    return new LocalSizeParameter();\n                case ExecutionMode.LocalSizeHint:\n                    return new LocalSizeHintParameter();\n                case ExecutionMode.OutputVertices:\n                    return new OutputVerticesParameter();\n                case ExecutionMode.VecTypeHint:\n                    return new VecTypeHintParameter();\n                case ExecutionMode.SubgroupSize:\n                    return new SubgroupSizeParameter();\n                case ExecutionMode.SubgroupsPerWorkgroup:\n                    return new SubgroupsPerWorkgroupParameter();\n                case ExecutionMode.SubgroupsPerWorkgroupId:\n                    return new SubgroupsPerWorkgroupIdParameter();\n                case ExecutionMode.LocalSizeId:\n                    return new LocalSizeIdParameter();\n                case ExecutionMode.LocalSizeHintId:\n                    return new LocalSizeHintIdParameter();\n            }\n\n            return null;\n        }\n    }\n    public enum StorageClass : uint\n    {\n        UniformConstant = 0,\n        Input = 1,\n        Uniform = 2,\n        Output = 3,\n        Workgroup = 4,\n        CrossWorkgroup = 5,\n        Private = 6,\n        Function = 7,\n        Generic = 8,\n        PushConstant = 9,\n        AtomicCounter = 10,\n        Image = 11,\n        StorageBuffer = 12,\n    }\n    public class StorageClassParameterFactory : ParameterFactory\n    {\n    }\n    public enum Dim : uint\n    {\n        Dim1D = 0,\n        Dim2D = 1,\n        Dim3D = 2,\n        Cube = 3,\n        Rect = 4,\n        Buffer = 5,\n        SubpassData = 6,\n    }\n    public class DimParameterFactory : ParameterFactory\n    {\n    }\n    public enum SamplerAddressingMode : uint\n    {\n        None = 0,\n        ClampToEdge = 1,\n        Clamp = 2,\n        Repeat = 3,\n        RepeatMirrored = 4,\n    }\n    public class SamplerAddressingModeParameterFactory : ParameterFactory\n    {\n    }\n    public enum SamplerFilterMode : uint\n    {\n        Nearest = 0,\n        Linear = 1,\n    }\n    public class SamplerFilterModeParameterFactory : ParameterFactory\n    {\n    }\n    public enum ImageFormat : uint\n    {\n        Unknown = 0,\n        Rgba32f = 1,\n        Rgba16f = 2,\n        R32f = 3,\n        Rgba8 = 4,\n        Rgba8Snorm = 5,\n        Rg32f = 6,\n        Rg16f = 7,\n        R11fG11fB10f = 8,\n        R16f = 9,\n        Rgba16 = 10,\n        Rgb10A2 = 11,\n        Rg16 = 12,\n        Rg8 = 13,\n        R16 = 14,\n        R8 = 15,\n        Rgba16Snorm = 16,\n        Rg16Snorm = 17,\n        Rg8Snorm = 18,\n        R16Snorm = 19,\n        R8Snorm = 20,\n        Rgba32i = 21,\n        Rgba16i = 22,\n        Rgba8i = 23,\n        R32i = 24,\n        Rg32i = 25,\n        Rg16i = 26,\n        Rg8i = 27,\n        R16i = 28,\n        R8i = 29,\n        Rgba32ui = 30,\n        Rgba16ui = 31,\n        Rgba8ui = 32,\n        R32ui = 33,\n        Rgb10a2ui = 34,\n        Rg32ui = 35,\n        Rg16ui = 36,\n        Rg8ui = 37,\n        R16ui = 38,\n        R8ui = 39,\n    }\n    public class ImageFormatParameterFactory : ParameterFactory\n    {\n    }\n    public enum ImageChannelOrder : uint\n    {\n        R = 0,\n        A = 1,\n        RG = 2,\n        RA = 3,\n        RGB = 4,\n        RGBA = 5,\n        BGRA = 6,\n        ARGB = 7,\n        Intensity = 8,\n        Luminance = 9,\n        Rx = 10,\n        RGx = 11,\n        RGBx = 12,\n        Depth = 13,\n        DepthStencil = 14,\n        sRGB = 15,\n        sRGBx = 16,\n        sRGBA = 17,\n        sBGRA = 18,\n        ABGR = 19,\n    }\n    public class ImageChannelOrderParameterFactory : ParameterFactory\n    {\n    }\n    public enum ImageChannelDataType : uint\n    {\n        SnormInt8 = 0,\n        SnormInt16 = 1,\n        UnormInt8 = 2,\n        UnormInt16 = 3,\n        UnormShort565 = 4,\n        UnormShort555 = 5,\n        UnormInt101010 = 6,\n        SignedInt8 = 7,\n        SignedInt16 = 8,\n        SignedInt32 = 9,\n        UnsignedInt8 = 10,\n        UnsignedInt16 = 11,\n        UnsignedInt32 = 12,\n        HalfFloat = 13,\n        Float = 14,\n        UnormInt24 = 15,\n        UnormInt101010_2 = 16,\n    }\n    public class ImageChannelDataTypeParameterFactory : ParameterFactory\n    {\n    }\n    public enum FPRoundingMode : uint\n    {\n        RTE = 0,\n        RTZ = 1,\n        RTP = 2,\n        RTN = 3,\n    }\n    public class FPRoundingModeParameterFactory : ParameterFactory\n    {\n    }\n    public enum LinkageType : uint\n    {\n        Export = 0,\n        Import = 1,\n    }\n    public class LinkageTypeParameterFactory : ParameterFactory\n    {\n    }\n    public enum AccessQualifier : uint\n    {\n        ReadOnly = 0,\n        WriteOnly = 1,\n        ReadWrite = 2,\n    }\n    public class AccessQualifierParameterFactory : ParameterFactory\n    {\n    }\n    public enum FunctionParameterAttribute : uint\n    {\n        Zext = 0,\n        Sext = 1,\n        ByVal = 2,\n        Sret = 3,\n        NoAlias = 4,\n        NoCapture = 5,\n        NoWrite = 6,\n        NoReadWrite = 7,\n    }\n    public class FunctionParameterAttributeParameterFactory : ParameterFactory\n    {\n    }\n    public enum Decoration : uint\n    {\n        RelaxedPrecision = 0,\n        SpecId = 1,\n        Block = 2,\n        BufferBlock = 3,\n        RowMajor = 4,\n        ColMajor = 5,\n        ArrayStride = 6,\n        MatrixStride = 7,\n        GLSLShared = 8,\n        GLSLPacked = 9,\n        CPacked = 10,\n        BuiltIn = 11,\n        NoPerspective = 13,\n        Flat = 14,\n        Patch = 15,\n        Centroid = 16,\n        Sample = 17,\n        Invariant = 18,\n        Restrict = 19,\n        Aliased = 20,\n        Volatile = 21,\n        Constant = 22,\n        Coherent = 23,\n        NonWritable = 24,\n        NonReadable = 25,\n        Uniform = 26,\n        SaturatedConversion = 28,\n        Stream = 29,\n        Location = 30,\n        Component = 31,\n        Index = 32,\n        Binding = 33,\n        DescriptorSet = 34,\n        Offset = 35,\n        XfbBuffer = 36,\n        XfbStride = 37,\n        FuncParamAttr = 38,\n        FPRoundingMode = 39,\n        FPFastMathMode = 40,\n        LinkageAttributes = 41,\n        NoContraction = 42,\n        InputAttachmentIndex = 43,\n        Alignment = 44,\n        MaxByteOffset = 45,\n        AlignmentId = 46,\n        MaxByteOffsetId = 47,\n        ExplicitInterpAMD = 4999,\n        OverrideCoverageNV = 5248,\n        PassthroughNV = 5250,\n        ViewportRelativeNV = 5252,\n        SecondaryViewportRelativeNV = 5256,\n    }\n    public class DecorationParameterFactory : ParameterFactory\n    {\n        public class SpecIdParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class ArrayStrideParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class MatrixStrideParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class BuiltInParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new EnumType<BuiltIn>(), };\n        }\n\n        public class StreamParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class LocationParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class ComponentParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class IndexParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class BindingParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class DescriptorSetParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class OffsetParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class XfbBufferParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class XfbStrideParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class FuncParamAttrParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new EnumType<FunctionParameterAttribute>(), };\n        }\n\n        public class FPRoundingModeParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new EnumType<FPRoundingMode>(), };\n        }\n\n        public class FPFastMathModeParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new EnumType<FPFastMathMode>(), };\n        }\n\n        public class LinkageAttributesParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralString(), new EnumType<LinkageType>(), };\n        }\n\n        public class InputAttachmentIndexParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class AlignmentParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class MaxByteOffsetParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public class AlignmentIdParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class MaxByteOffsetIdParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new IdRef(), };\n        }\n\n        public class SecondaryViewportRelativeNVParameter : Parameter\n        {\n            public override IReadOnlyList<OperandType> OperandTypes\n            {\n                get => operandTypes_;\n            }\n\n            private static readonly List<OperandType> operandTypes_ = new List<OperandType>()\n        {new LiteralInteger(), };\n        }\n\n        public override Parameter CreateParameter(object value)\n        {\n            switch ((Decoration)value)\n            {\n                case Decoration.SpecId:\n                    return new SpecIdParameter();\n                case Decoration.ArrayStride:\n                    return new ArrayStrideParameter();\n                case Decoration.MatrixStride:\n                    return new MatrixStrideParameter();\n                case Decoration.BuiltIn:\n                    return new BuiltInParameter();\n                case Decoration.Stream:\n                    return new StreamParameter();\n                case Decoration.Location:\n                    return new LocationParameter();\n                case Decoration.Component:\n                    return new ComponentParameter();\n                case Decoration.Index:\n                    return new IndexParameter();\n                case Decoration.Binding:\n                    return new BindingParameter();\n                case Decoration.DescriptorSet:\n                    return new DescriptorSetParameter();\n                case Decoration.Offset:\n                    return new OffsetParameter();\n                case Decoration.XfbBuffer:\n                    return new XfbBufferParameter();\n                case Decoration.XfbStride:\n                    return new XfbStrideParameter();\n                case Decoration.FuncParamAttr:\n                    return new FuncParamAttrParameter();\n                case Decoration.FPRoundingMode:\n                    return new FPRoundingModeParameter();\n                case Decoration.FPFastMathMode:\n                    return new FPFastMathModeParameter();\n                case Decoration.LinkageAttributes:\n                    return new LinkageAttributesParameter();\n                case Decoration.InputAttachmentIndex:\n                    return new InputAttachmentIndexParameter();\n                case Decoration.Alignment:\n                    return new AlignmentParameter();\n                case Decoration.MaxByteOffset:\n                    return new MaxByteOffsetParameter();\n                case Decoration.AlignmentId:\n                    return new AlignmentIdParameter();\n                case Decoration.MaxByteOffsetId:\n                    return new MaxByteOffsetIdParameter();\n                case Decoration.SecondaryViewportRelativeNV:\n                    return new SecondaryViewportRelativeNVParameter();\n            }\n\n            return null;\n        }\n    }\n    public enum BuiltIn : uint\n    {\n        Position = 0,\n        PointSize = 1,\n        ClipDistance = 3,\n        CullDistance = 4,\n        VertexId = 5,\n        InstanceId = 6,\n        PrimitiveId = 7,\n        InvocationId = 8,\n        Layer = 9,\n        ViewportIndex = 10,\n        TessLevelOuter = 11,\n        TessLevelInner = 12,\n        TessCoord = 13,\n        PatchVertices = 14,\n        FragCoord = 15,\n        PointCoord = 16,\n        FrontFacing = 17,\n        SampleId = 18,\n        SamplePosition = 19,\n        SampleMask = 20,\n        FragDepth = 22,\n        HelperInvocation = 23,\n        NumWorkgroups = 24,\n        WorkgroupSize = 25,\n        WorkgroupId = 26,\n        LocalInvocationId = 27,\n        GlobalInvocationId = 28,\n        LocalInvocationIndex = 29,\n        WorkDim = 30,\n        GlobalSize = 31,\n        EnqueuedWorkgroupSize = 32,\n        GlobalOffset = 33,\n        GlobalLinearId = 34,\n        SubgroupSize = 36,\n        SubgroupMaxSize = 37,\n        NumSubgroups = 38,\n        NumEnqueuedSubgroups = 39,\n        SubgroupId = 40,\n        SubgroupLocalInvocationId = 41,\n        VertexIndex = 42,\n        InstanceIndex = 43,\n        SubgroupEqMaskKHR = 4416,\n        SubgroupGeMaskKHR = 4417,\n        SubgroupGtMaskKHR = 4418,\n        SubgroupLeMaskKHR = 4419,\n        SubgroupLtMaskKHR = 4420,\n        BaseVertex = 4424,\n        BaseInstance = 4425,\n        DrawIndex = 4426,\n        DeviceIndex = 4438,\n        ViewIndex = 4440,\n        BaryCoordNoPerspAMD = 4992,\n        BaryCoordNoPerspCentroidAMD = 4993,\n        BaryCoordNoPerspSampleAMD = 4994,\n        BaryCoordSmoothAMD = 4995,\n        BaryCoordSmoothCentroidAMD = 4996,\n        BaryCoordSmoothSampleAMD = 4997,\n        BaryCoordPullModelAMD = 4998,\n        FragStencilRefEXT = 5014,\n        ViewportMaskNV = 5253,\n        SecondaryPositionNV = 5257,\n        SecondaryViewportMaskNV = 5258,\n        PositionPerViewNV = 5261,\n        ViewportMaskPerViewNV = 5262,\n    }\n    public class BuiltInParameterFactory : ParameterFactory\n    {\n    }\n    public enum Scope : uint\n    {\n        CrossDevice = 0,\n        Device = 1,\n        Workgroup = 2,\n        Subgroup = 3,\n        Invocation = 4,\n    }\n    public class ScopeParameterFactory : ParameterFactory\n    {\n    }\n    public enum GroupOperation : uint\n    {\n        Reduce = 0,\n        InclusiveScan = 1,\n        ExclusiveScan = 2,\n    }\n    public class GroupOperationParameterFactory : ParameterFactory\n    {\n    }\n    public enum KernelEnqueueFlags : uint\n    {\n        NoWait = 0,\n        WaitKernel = 1,\n        WaitWorkGroup = 2,\n    }\n    public class KernelEnqueueFlagsParameterFactory : ParameterFactory\n    {\n    }\n    public enum Capability : uint\n    {\n        Matrix = 0,\n        Shader = 1,\n        Geometry = 2,\n        Tessellation = 3,\n        Addresses = 4,\n        Linkage = 5,\n        Kernel = 6,\n        Vector16 = 7,\n        Float16Buffer = 8,\n        Float16 = 9,\n        Float64 = 10,\n        Int64 = 11,\n        Int64Atomics = 12,\n        ImageBasic = 13,\n        ImageReadWrite = 14,\n        ImageMipmap = 15,\n        Pipes = 17,\n        Groups = 18,\n        DeviceEnqueue = 19,\n        LiteralSampler = 20,\n        AtomicStorage = 21,\n        Int16 = 22,\n        TessellationPointSize = 23,\n        GeometryPointSize = 24,\n        ImageGatherExtended = 25,\n        StorageImageMultisample = 27,\n        UniformBufferArrayDynamicIndexing = 28,\n        SampledImageArrayDynamicIndexing = 29,\n        StorageBufferArrayDynamicIndexing = 30,\n        StorageImageArrayDynamicIndexing = 31,\n        ClipDistance = 32,\n        CullDistance = 33,\n        ImageCubeArray = 34,\n        SampleRateShading = 35,\n        ImageRect = 36,\n        SampledRect = 37,\n        GenericPointer = 38,\n        Int8 = 39,\n        InputAttachment = 40,\n        SparseResidency = 41,\n        MinLod = 42,\n        Sampled1D = 43,\n        Image1D = 44,\n        SampledCubeArray = 45,\n        SampledBuffer = 46,\n        ImageBuffer = 47,\n        ImageMSArray = 48,\n        StorageImageExtendedFormats = 49,\n        ImageQuery = 50,\n        DerivativeControl = 51,\n        InterpolationFunction = 52,\n        TransformFeedback = 53,\n        GeometryStreams = 54,\n        StorageImageReadWithoutFormat = 55,\n        StorageImageWriteWithoutFormat = 56,\n        MultiViewport = 57,\n        SubgroupDispatch = 58,\n        NamedBarrier = 59,\n        PipeStorage = 60,\n        SubgroupBallotKHR = 4423,\n        DrawParameters = 4427,\n        SubgroupVoteKHR = 4431,\n        StorageBuffer16BitAccess = 4433,\n        StorageUniformBufferBlock16 = 4433,\n        UniformAndStorageBuffer16BitAccess = 4434,\n        StorageUniform16 = 4434,\n        StoragePushConstant16 = 4435,\n        StorageInputOutput16 = 4436,\n        DeviceGroup = 4437,\n        MultiView = 4439,\n        VariablePointersStorageBuffer = 4441,\n        VariablePointers = 4442,\n        AtomicStorageOps = 4445,\n        SampleMaskPostDepthCoverage = 4447,\n        ImageGatherBiasLodAMD = 5009,\n        FragmentMaskAMD = 5010,\n        StencilExportEXT = 5013,\n        ImageReadWriteLodAMD = 5015,\n        SampleMaskOverrideCoverageNV = 5249,\n        GeometryShaderPassthroughNV = 5251,\n        ShaderViewportIndexLayerEXT = 5254,\n        ShaderViewportIndexLayerNV = 5254,\n        ShaderViewportMaskNV = 5255,\n        ShaderStereoViewNV = 5259,\n        PerViewAttributesNV = 5260,\n        SubgroupShuffleINTEL = 5568,\n        SubgroupBufferBlockIOINTEL = 5569,\n        SubgroupImageBlockIOINTEL = 5570,\n    }\n    public class CapabilityParameterFactory : ParameterFactory\n    {\n    }\n    public class OpNop : Instruction\n    {\n        public OpNop() : base(\"OpNop\")\n        {\n        }\n    }\n    public class OpUndef : Instruction\n    {\n        public OpUndef() : base(\"OpUndef\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSourceContinued : Instruction\n    {\n        public OpSourceContinued() : base(\"OpSourceContinued\", new List<Operand>()\n    {new Operand(new LiteralString(), \"Continued Source\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSource : Instruction\n    {\n        public OpSource() : base(\"OpSource\", new List<Operand>()\n    {new Operand(new EnumType<SourceLanguage, SourceLanguageParameterFactory>(), null, OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Version\", OperandQuantifier.Default), new Operand(new IdRef(), \"File\", OperandQuantifier.Optional), new Operand(new LiteralString(), \"Source\", OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpSourceExtension : Instruction\n    {\n        public OpSourceExtension() : base(\"OpSourceExtension\", new List<Operand>()\n    {new Operand(new LiteralString(), \"Extension\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpName : Instruction\n    {\n        public OpName() : base(\"OpName\", new List<Operand>()\n    {new Operand(new IdRef(), \"Target\", OperandQuantifier.Default), new Operand(new LiteralString(), \"Name\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpMemberName : Instruction\n    {\n        public OpMemberName() : base(\"OpMemberName\", new List<Operand>()\n    {new Operand(new IdRef(), \"Type\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Member\", OperandQuantifier.Default), new Operand(new LiteralString(), \"Name\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpString : Instruction\n    {\n        public OpString() : base(\"OpString\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralString(), \"String\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLine : Instruction\n    {\n        public OpLine() : base(\"OpLine\", new List<Operand>()\n    {new Operand(new IdRef(), \"File\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Line\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Column\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpExtension : Instruction\n    {\n        public OpExtension() : base(\"OpExtension\", new List<Operand>()\n    {new Operand(new LiteralString(), \"Name\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpExtInstImport : Instruction\n    {\n        public OpExtInstImport() : base(\"OpExtInstImport\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralString(), \"Name\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpExtInst : Instruction\n    {\n        public OpExtInst() : base(\"OpExtInst\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Set\", OperandQuantifier.Default), new Operand(new LiteralExtInstInteger(), \"Instruction\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1, +Operand 2, +...\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpMemoryModel : Instruction\n    {\n        public OpMemoryModel() : base(\"OpMemoryModel\", new List<Operand>()\n    {new Operand(new EnumType<AddressingModel, AddressingModelParameterFactory>(), null, OperandQuantifier.Default), new Operand(new EnumType<MemoryModel, MemoryModelParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpEntryPoint : Instruction\n    {\n        public OpEntryPoint() : base(\"OpEntryPoint\", new List<Operand>()\n    {new Operand(new EnumType<ExecutionModel, ExecutionModelParameterFactory>(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Entry Point\", OperandQuantifier.Default), new Operand(new LiteralString(), \"Name\", OperandQuantifier.Default), new Operand(new IdRef(), \"Interface\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpExecutionMode : Instruction\n    {\n        public OpExecutionMode() : base(\"OpExecutionMode\", new List<Operand>()\n    {new Operand(new IdRef(), \"Entry Point\", OperandQuantifier.Default), new Operand(new EnumType<ExecutionMode, ExecutionModeParameterFactory>(), \"Mode\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpCapability : Instruction\n    {\n        public OpCapability() : base(\"OpCapability\", new List<Operand>()\n    {new Operand(new EnumType<Capability, CapabilityParameterFactory>(), \"Capability\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeVoid : Instruction\n    {\n        public OpTypeVoid() : base(\"OpTypeVoid\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeBool : Instruction\n    {\n        public OpTypeBool() : base(\"OpTypeBool\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeInt : Instruction\n    {\n        public OpTypeInt() : base(\"OpTypeInt\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Width\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Signedness\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeFloat : Instruction\n    {\n        public OpTypeFloat() : base(\"OpTypeFloat\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Width\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeVector : Instruction\n    {\n        public OpTypeVector() : base(\"OpTypeVector\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Component Type\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Component Count\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeMatrix : Instruction\n    {\n        public OpTypeMatrix() : base(\"OpTypeMatrix\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Column Type\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Column Count\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeImage : Instruction\n    {\n        public OpTypeImage() : base(\"OpTypeImage\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Type\", OperandQuantifier.Default), new Operand(new EnumType<Dim, DimParameterFactory>(), null, OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Depth\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Arrayed\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"MS\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Sampled\", OperandQuantifier.Default), new Operand(new EnumType<ImageFormat, ImageFormatParameterFactory>(), null, OperandQuantifier.Default), new Operand(new EnumType<AccessQualifier, AccessQualifierParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpTypeSampler : Instruction\n    {\n        public OpTypeSampler() : base(\"OpTypeSampler\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeSampledImage : Instruction\n    {\n        public OpTypeSampledImage() : base(\"OpTypeSampledImage\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image Type\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeArray : Instruction\n    {\n        public OpTypeArray() : base(\"OpTypeArray\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Element Type\", OperandQuantifier.Default), new Operand(new IdRef(), \"Length\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeRuntimeArray : Instruction\n    {\n        public OpTypeRuntimeArray() : base(\"OpTypeRuntimeArray\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Element Type\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeStruct : Instruction\n    {\n        public OpTypeStruct() : base(\"OpTypeStruct\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Member 0 type, +member 1 type, +...\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpTypeOpaque : Instruction\n    {\n        public OpTypeOpaque() : base(\"OpTypeOpaque\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralString(), \"The name of the opaque type.\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypePointer : Instruction\n    {\n        public OpTypePointer() : base(\"OpTypePointer\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new EnumType<StorageClass, StorageClassParameterFactory>(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Type\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeFunction : Instruction\n    {\n        public OpTypeFunction() : base(\"OpTypeFunction\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Return Type\", OperandQuantifier.Default), new Operand(new IdRef(), \"Parameter 0 Type, +Parameter 1 Type, +...\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpTypeEvent : Instruction\n    {\n        public OpTypeEvent() : base(\"OpTypeEvent\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeDeviceEvent : Instruction\n    {\n        public OpTypeDeviceEvent() : base(\"OpTypeDeviceEvent\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeReserveId : Instruction\n    {\n        public OpTypeReserveId() : base(\"OpTypeReserveId\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeQueue : Instruction\n    {\n        public OpTypeQueue() : base(\"OpTypeQueue\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypePipe : Instruction\n    {\n        public OpTypePipe() : base(\"OpTypePipe\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new EnumType<AccessQualifier, AccessQualifierParameterFactory>(), \"Qualifier\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeForwardPointer : Instruction\n    {\n        public OpTypeForwardPointer() : base(\"OpTypeForwardPointer\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pointer Type\", OperandQuantifier.Default), new Operand(new EnumType<StorageClass, StorageClassParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConstantTrue : Instruction\n    {\n        public OpConstantTrue() : base(\"OpConstantTrue\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConstantFalse : Instruction\n    {\n        public OpConstantFalse() : base(\"OpConstantFalse\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConstant : Instruction\n    {\n        public OpConstant() : base(\"OpConstant\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralContextDependentNumber(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConstantComposite : Instruction\n    {\n        public OpConstantComposite() : base(\"OpConstantComposite\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Constituents\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpConstantSampler : Instruction\n    {\n        public OpConstantSampler() : base(\"OpConstantSampler\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new EnumType<SamplerAddressingMode, SamplerAddressingModeParameterFactory>(), null, OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Param\", OperandQuantifier.Default), new Operand(new EnumType<SamplerFilterMode, SamplerFilterModeParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConstantNull : Instruction\n    {\n        public OpConstantNull() : base(\"OpConstantNull\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSpecConstantTrue : Instruction\n    {\n        public OpSpecConstantTrue() : base(\"OpSpecConstantTrue\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSpecConstantFalse : Instruction\n    {\n        public OpSpecConstantFalse() : base(\"OpSpecConstantFalse\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSpecConstant : Instruction\n    {\n        public OpSpecConstant() : base(\"OpSpecConstant\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralContextDependentNumber(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSpecConstantComposite : Instruction\n    {\n        public OpSpecConstantComposite() : base(\"OpSpecConstantComposite\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Constituents\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpSpecConstantOp : Instruction\n    {\n        public OpSpecConstantOp() : base(\"OpSpecConstantOp\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralSpecConstantOpInteger(), \"Opcode\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFunction : Instruction\n    {\n        public OpFunction() : base(\"OpFunction\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new EnumType<FunctionControl, FunctionControlParameterFactory>(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Function Type\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFunctionParameter : Instruction\n    {\n        public OpFunctionParameter() : base(\"OpFunctionParameter\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFunctionEnd : Instruction\n    {\n        public OpFunctionEnd() : base(\"OpFunctionEnd\")\n        {\n        }\n    }\n    public class OpFunctionCall : Instruction\n    {\n        public OpFunctionCall() : base(\"OpFunctionCall\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Function\", OperandQuantifier.Default), new Operand(new IdRef(), \"Argument 0, +Argument 1, +...\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpVariable : Instruction\n    {\n        public OpVariable() : base(\"OpVariable\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new EnumType<StorageClass, StorageClassParameterFactory>(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Initializer\", OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageTexelPointer : Instruction\n    {\n        public OpImageTexelPointer() : base(\"OpImageTexelPointer\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"Sample\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLoad : Instruction\n    {\n        public OpLoad() : base(\"OpLoad\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new EnumType<MemoryAccess, MemoryAccessParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpStore : Instruction\n    {\n        public OpStore() : base(\"OpStore\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdRef(), \"Object\", OperandQuantifier.Default), new Operand(new EnumType<MemoryAccess, MemoryAccessParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpCopyMemory : Instruction\n    {\n        public OpCopyMemory() : base(\"OpCopyMemory\", new List<Operand>()\n    {new Operand(new IdRef(), \"Target\", OperandQuantifier.Default), new Operand(new IdRef(), \"Source\", OperandQuantifier.Default), new Operand(new EnumType<MemoryAccess, MemoryAccessParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpCopyMemorySized : Instruction\n    {\n        public OpCopyMemorySized() : base(\"OpCopyMemorySized\", new List<Operand>()\n    {new Operand(new IdRef(), \"Target\", OperandQuantifier.Default), new Operand(new IdRef(), \"Source\", OperandQuantifier.Default), new Operand(new IdRef(), \"Size\", OperandQuantifier.Default), new Operand(new EnumType<MemoryAccess, MemoryAccessParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpAccessChain : Instruction\n    {\n        public OpAccessChain() : base(\"OpAccessChain\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Indexes\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpInBoundsAccessChain : Instruction\n    {\n        public OpInBoundsAccessChain() : base(\"OpInBoundsAccessChain\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Indexes\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpPtrAccessChain : Instruction\n    {\n        public OpPtrAccessChain() : base(\"OpPtrAccessChain\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Element\", OperandQuantifier.Default), new Operand(new IdRef(), \"Indexes\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpArrayLength : Instruction\n    {\n        public OpArrayLength() : base(\"OpArrayLength\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Structure\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Array member\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGenericPtrMemSemantics : Instruction\n    {\n        public OpGenericPtrMemSemantics() : base(\"OpGenericPtrMemSemantics\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpInBoundsPtrAccessChain : Instruction\n    {\n        public OpInBoundsPtrAccessChain() : base(\"OpInBoundsPtrAccessChain\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Element\", OperandQuantifier.Default), new Operand(new IdRef(), \"Indexes\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpDecorate : Instruction\n    {\n        public OpDecorate() : base(\"OpDecorate\", new List<Operand>()\n    {new Operand(new IdRef(), \"Target\", OperandQuantifier.Default), new Operand(new EnumType<Decoration, DecorationParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpMemberDecorate : Instruction\n    {\n        public OpMemberDecorate() : base(\"OpMemberDecorate\", new List<Operand>()\n    {new Operand(new IdRef(), \"Structure Type\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Member\", OperandQuantifier.Default), new Operand(new EnumType<Decoration, DecorationParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDecorationGroup : Instruction\n    {\n        public OpDecorationGroup() : base(\"OpDecorationGroup\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupDecorate : Instruction\n    {\n        public OpGroupDecorate() : base(\"OpGroupDecorate\", new List<Operand>()\n    {new Operand(new IdRef(), \"Decoration Group\", OperandQuantifier.Default), new Operand(new IdRef(), \"Targets\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpGroupMemberDecorate : Instruction\n    {\n        public OpGroupMemberDecorate() : base(\"OpGroupMemberDecorate\", new List<Operand>()\n    {new Operand(new IdRef(), \"Decoration Group\", OperandQuantifier.Default), new Operand(new PairIdRefLiteralInteger(), \"Targets\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpVectorExtractDynamic : Instruction\n    {\n        public OpVectorExtractDynamic() : base(\"OpVectorExtractDynamic\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector\", OperandQuantifier.Default), new Operand(new IdRef(), \"Index\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpVectorInsertDynamic : Instruction\n    {\n        public OpVectorInsertDynamic() : base(\"OpVectorInsertDynamic\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector\", OperandQuantifier.Default), new Operand(new IdRef(), \"Component\", OperandQuantifier.Default), new Operand(new IdRef(), \"Index\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpVectorShuffle : Instruction\n    {\n        public OpVectorShuffle() : base(\"OpVectorShuffle\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Vector 2\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Components\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpCompositeConstruct : Instruction\n    {\n        public OpCompositeConstruct() : base(\"OpCompositeConstruct\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Constituents\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpCompositeExtract : Instruction\n    {\n        public OpCompositeExtract() : base(\"OpCompositeExtract\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Composite\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Indexes\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpCompositeInsert : Instruction\n    {\n        public OpCompositeInsert() : base(\"OpCompositeInsert\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Object\", OperandQuantifier.Default), new Operand(new IdRef(), \"Composite\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Indexes\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpCopyObject : Instruction\n    {\n        public OpCopyObject() : base(\"OpCopyObject\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTranspose : Instruction\n    {\n        public OpTranspose() : base(\"OpTranspose\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Matrix\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSampledImage : Instruction\n    {\n        public OpSampledImage() : base(\"OpSampledImage\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Sampler\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSampleImplicitLod : Instruction\n    {\n        public OpImageSampleImplicitLod() : base(\"OpImageSampleImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSampleExplicitLod : Instruction\n    {\n        public OpImageSampleExplicitLod() : base(\"OpImageSampleExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSampleDrefImplicitLod : Instruction\n    {\n        public OpImageSampleDrefImplicitLod() : base(\"OpImageSampleDrefImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSampleDrefExplicitLod : Instruction\n    {\n        public OpImageSampleDrefExplicitLod() : base(\"OpImageSampleDrefExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSampleProjImplicitLod : Instruction\n    {\n        public OpImageSampleProjImplicitLod() : base(\"OpImageSampleProjImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSampleProjExplicitLod : Instruction\n    {\n        public OpImageSampleProjExplicitLod() : base(\"OpImageSampleProjExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSampleProjDrefImplicitLod : Instruction\n    {\n        public OpImageSampleProjDrefImplicitLod() : base(\"OpImageSampleProjDrefImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSampleProjDrefExplicitLod : Instruction\n    {\n        public OpImageSampleProjDrefExplicitLod() : base(\"OpImageSampleProjDrefExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageFetch : Instruction\n    {\n        public OpImageFetch() : base(\"OpImageFetch\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageGather : Instruction\n    {\n        public OpImageGather() : base(\"OpImageGather\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"Component\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageDrefGather : Instruction\n    {\n        public OpImageDrefGather() : base(\"OpImageDrefGather\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageRead : Instruction\n    {\n        public OpImageRead() : base(\"OpImageRead\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageWrite : Instruction\n    {\n        public OpImageWrite() : base(\"OpImageWrite\", new List<Operand>()\n    {new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"Texel\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImage : Instruction\n    {\n        public OpImage() : base(\"OpImage\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageQueryFormat : Instruction\n    {\n        public OpImageQueryFormat() : base(\"OpImageQueryFormat\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageQueryOrder : Instruction\n    {\n        public OpImageQueryOrder() : base(\"OpImageQueryOrder\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageQuerySizeLod : Instruction\n    {\n        public OpImageQuerySizeLod() : base(\"OpImageQuerySizeLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Level of Detail\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageQuerySize : Instruction\n    {\n        public OpImageQuerySize() : base(\"OpImageQuerySize\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageQueryLod : Instruction\n    {\n        public OpImageQueryLod() : base(\"OpImageQueryLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageQueryLevels : Instruction\n    {\n        public OpImageQueryLevels() : base(\"OpImageQueryLevels\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageQuerySamples : Instruction\n    {\n        public OpImageQuerySamples() : base(\"OpImageQuerySamples\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConvertFToU : Instruction\n    {\n        public OpConvertFToU() : base(\"OpConvertFToU\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Float Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConvertFToS : Instruction\n    {\n        public OpConvertFToS() : base(\"OpConvertFToS\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Float Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConvertSToF : Instruction\n    {\n        public OpConvertSToF() : base(\"OpConvertSToF\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Signed Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConvertUToF : Instruction\n    {\n        public OpConvertUToF() : base(\"OpConvertUToF\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Unsigned Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUConvert : Instruction\n    {\n        public OpUConvert() : base(\"OpUConvert\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Unsigned Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSConvert : Instruction\n    {\n        public OpSConvert() : base(\"OpSConvert\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Signed Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFConvert : Instruction\n    {\n        public OpFConvert() : base(\"OpFConvert\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Float Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpQuantizeToF16 : Instruction\n    {\n        public OpQuantizeToF16() : base(\"OpQuantizeToF16\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConvertPtrToU : Instruction\n    {\n        public OpConvertPtrToU() : base(\"OpConvertPtrToU\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSatConvertSToU : Instruction\n    {\n        public OpSatConvertSToU() : base(\"OpSatConvertSToU\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Signed Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSatConvertUToS : Instruction\n    {\n        public OpSatConvertUToS() : base(\"OpSatConvertUToS\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Unsigned Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConvertUToPtr : Instruction\n    {\n        public OpConvertUToPtr() : base(\"OpConvertUToPtr\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Integer Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpPtrCastToGeneric : Instruction\n    {\n        public OpPtrCastToGeneric() : base(\"OpPtrCastToGeneric\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGenericCastToPtr : Instruction\n    {\n        public OpGenericCastToPtr() : base(\"OpGenericCastToPtr\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGenericCastToPtrExplicit : Instruction\n    {\n        public OpGenericCastToPtrExplicit() : base(\"OpGenericCastToPtrExplicit\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new EnumType<StorageClass, StorageClassParameterFactory>(), \"Storage\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitcast : Instruction\n    {\n        public OpBitcast() : base(\"OpBitcast\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSNegate : Instruction\n    {\n        public OpSNegate() : base(\"OpSNegate\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFNegate : Instruction\n    {\n        public OpFNegate() : base(\"OpFNegate\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIAdd : Instruction\n    {\n        public OpIAdd() : base(\"OpIAdd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFAdd : Instruction\n    {\n        public OpFAdd() : base(\"OpFAdd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpISub : Instruction\n    {\n        public OpISub() : base(\"OpISub\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFSub : Instruction\n    {\n        public OpFSub() : base(\"OpFSub\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIMul : Instruction\n    {\n        public OpIMul() : base(\"OpIMul\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFMul : Instruction\n    {\n        public OpFMul() : base(\"OpFMul\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUDiv : Instruction\n    {\n        public OpUDiv() : base(\"OpUDiv\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSDiv : Instruction\n    {\n        public OpSDiv() : base(\"OpSDiv\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFDiv : Instruction\n    {\n        public OpFDiv() : base(\"OpFDiv\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUMod : Instruction\n    {\n        public OpUMod() : base(\"OpUMod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSRem : Instruction\n    {\n        public OpSRem() : base(\"OpSRem\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSMod : Instruction\n    {\n        public OpSMod() : base(\"OpSMod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFRem : Instruction\n    {\n        public OpFRem() : base(\"OpFRem\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFMod : Instruction\n    {\n        public OpFMod() : base(\"OpFMod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpVectorTimesScalar : Instruction\n    {\n        public OpVectorTimesScalar() : base(\"OpVectorTimesScalar\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector\", OperandQuantifier.Default), new Operand(new IdRef(), \"Scalar\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpMatrixTimesScalar : Instruction\n    {\n        public OpMatrixTimesScalar() : base(\"OpMatrixTimesScalar\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Matrix\", OperandQuantifier.Default), new Operand(new IdRef(), \"Scalar\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpVectorTimesMatrix : Instruction\n    {\n        public OpVectorTimesMatrix() : base(\"OpVectorTimesMatrix\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector\", OperandQuantifier.Default), new Operand(new IdRef(), \"Matrix\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpMatrixTimesVector : Instruction\n    {\n        public OpMatrixTimesVector() : base(\"OpMatrixTimesVector\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Matrix\", OperandQuantifier.Default), new Operand(new IdRef(), \"Vector\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpMatrixTimesMatrix : Instruction\n    {\n        public OpMatrixTimesMatrix() : base(\"OpMatrixTimesMatrix\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"LeftMatrix\", OperandQuantifier.Default), new Operand(new IdRef(), \"RightMatrix\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpOuterProduct : Instruction\n    {\n        public OpOuterProduct() : base(\"OpOuterProduct\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Vector 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDot : Instruction\n    {\n        public OpDot() : base(\"OpDot\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Vector 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIAddCarry : Instruction\n    {\n        public OpIAddCarry() : base(\"OpIAddCarry\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpISubBorrow : Instruction\n    {\n        public OpISubBorrow() : base(\"OpISubBorrow\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUMulExtended : Instruction\n    {\n        public OpUMulExtended() : base(\"OpUMulExtended\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSMulExtended : Instruction\n    {\n        public OpSMulExtended() : base(\"OpSMulExtended\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAny : Instruction\n    {\n        public OpAny() : base(\"OpAny\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAll : Instruction\n    {\n        public OpAll() : base(\"OpAll\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Vector\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIsNan : Instruction\n    {\n        public OpIsNan() : base(\"OpIsNan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIsInf : Instruction\n    {\n        public OpIsInf() : base(\"OpIsInf\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIsFinite : Instruction\n    {\n        public OpIsFinite() : base(\"OpIsFinite\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIsNormal : Instruction\n    {\n        public OpIsNormal() : base(\"OpIsNormal\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSignBitSet : Instruction\n    {\n        public OpSignBitSet() : base(\"OpSignBitSet\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLessOrGreater : Instruction\n    {\n        public OpLessOrGreater() : base(\"OpLessOrGreater\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), new Operand(new IdRef(), \"y\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpOrdered : Instruction\n    {\n        public OpOrdered() : base(\"OpOrdered\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), new Operand(new IdRef(), \"y\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUnordered : Instruction\n    {\n        public OpUnordered() : base(\"OpUnordered\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"x\", OperandQuantifier.Default), new Operand(new IdRef(), \"y\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLogicalEqual : Instruction\n    {\n        public OpLogicalEqual() : base(\"OpLogicalEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLogicalNotEqual : Instruction\n    {\n        public OpLogicalNotEqual() : base(\"OpLogicalNotEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLogicalOr : Instruction\n    {\n        public OpLogicalOr() : base(\"OpLogicalOr\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLogicalAnd : Instruction\n    {\n        public OpLogicalAnd() : base(\"OpLogicalAnd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLogicalNot : Instruction\n    {\n        public OpLogicalNot() : base(\"OpLogicalNot\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSelect : Instruction\n    {\n        public OpSelect() : base(\"OpSelect\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Condition\", OperandQuantifier.Default), new Operand(new IdRef(), \"Object 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Object 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIEqual : Instruction\n    {\n        public OpIEqual() : base(\"OpIEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpINotEqual : Instruction\n    {\n        public OpINotEqual() : base(\"OpINotEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUGreaterThan : Instruction\n    {\n        public OpUGreaterThan() : base(\"OpUGreaterThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSGreaterThan : Instruction\n    {\n        public OpSGreaterThan() : base(\"OpSGreaterThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUGreaterThanEqual : Instruction\n    {\n        public OpUGreaterThanEqual() : base(\"OpUGreaterThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSGreaterThanEqual : Instruction\n    {\n        public OpSGreaterThanEqual() : base(\"OpSGreaterThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpULessThan : Instruction\n    {\n        public OpULessThan() : base(\"OpULessThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSLessThan : Instruction\n    {\n        public OpSLessThan() : base(\"OpSLessThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpULessThanEqual : Instruction\n    {\n        public OpULessThanEqual() : base(\"OpULessThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSLessThanEqual : Instruction\n    {\n        public OpSLessThanEqual() : base(\"OpSLessThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFOrdEqual : Instruction\n    {\n        public OpFOrdEqual() : base(\"OpFOrdEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFUnordEqual : Instruction\n    {\n        public OpFUnordEqual() : base(\"OpFUnordEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFOrdNotEqual : Instruction\n    {\n        public OpFOrdNotEqual() : base(\"OpFOrdNotEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFUnordNotEqual : Instruction\n    {\n        public OpFUnordNotEqual() : base(\"OpFUnordNotEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFOrdLessThan : Instruction\n    {\n        public OpFOrdLessThan() : base(\"OpFOrdLessThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFUnordLessThan : Instruction\n    {\n        public OpFUnordLessThan() : base(\"OpFUnordLessThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFOrdGreaterThan : Instruction\n    {\n        public OpFOrdGreaterThan() : base(\"OpFOrdGreaterThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFUnordGreaterThan : Instruction\n    {\n        public OpFUnordGreaterThan() : base(\"OpFUnordGreaterThan\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFOrdLessThanEqual : Instruction\n    {\n        public OpFOrdLessThanEqual() : base(\"OpFOrdLessThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFUnordLessThanEqual : Instruction\n    {\n        public OpFUnordLessThanEqual() : base(\"OpFUnordLessThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFOrdGreaterThanEqual : Instruction\n    {\n        public OpFOrdGreaterThanEqual() : base(\"OpFOrdGreaterThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFUnordGreaterThanEqual : Instruction\n    {\n        public OpFUnordGreaterThanEqual() : base(\"OpFUnordGreaterThanEqual\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpShiftRightLogical : Instruction\n    {\n        public OpShiftRightLogical() : base(\"OpShiftRightLogical\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Shift\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpShiftRightArithmetic : Instruction\n    {\n        public OpShiftRightArithmetic() : base(\"OpShiftRightArithmetic\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Shift\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpShiftLeftLogical : Instruction\n    {\n        public OpShiftLeftLogical() : base(\"OpShiftLeftLogical\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Shift\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitwiseOr : Instruction\n    {\n        public OpBitwiseOr() : base(\"OpBitwiseOr\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitwiseXor : Instruction\n    {\n        public OpBitwiseXor() : base(\"OpBitwiseXor\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitwiseAnd : Instruction\n    {\n        public OpBitwiseAnd() : base(\"OpBitwiseAnd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 1\", OperandQuantifier.Default), new Operand(new IdRef(), \"Operand 2\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpNot : Instruction\n    {\n        public OpNot() : base(\"OpNot\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Operand\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitFieldInsert : Instruction\n    {\n        public OpBitFieldInsert() : base(\"OpBitFieldInsert\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Insert\", OperandQuantifier.Default), new Operand(new IdRef(), \"Offset\", OperandQuantifier.Default), new Operand(new IdRef(), \"Count\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitFieldSExtract : Instruction\n    {\n        public OpBitFieldSExtract() : base(\"OpBitFieldSExtract\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Offset\", OperandQuantifier.Default), new Operand(new IdRef(), \"Count\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitFieldUExtract : Instruction\n    {\n        public OpBitFieldUExtract() : base(\"OpBitFieldUExtract\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), new Operand(new IdRef(), \"Offset\", OperandQuantifier.Default), new Operand(new IdRef(), \"Count\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitReverse : Instruction\n    {\n        public OpBitReverse() : base(\"OpBitReverse\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBitCount : Instruction\n    {\n        public OpBitCount() : base(\"OpBitCount\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Base\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDPdx : Instruction\n    {\n        public OpDPdx() : base(\"OpDPdx\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDPdy : Instruction\n    {\n        public OpDPdy() : base(\"OpDPdy\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFwidth : Instruction\n    {\n        public OpFwidth() : base(\"OpFwidth\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDPdxFine : Instruction\n    {\n        public OpDPdxFine() : base(\"OpDPdxFine\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDPdyFine : Instruction\n    {\n        public OpDPdyFine() : base(\"OpDPdyFine\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFwidthFine : Instruction\n    {\n        public OpFwidthFine() : base(\"OpFwidthFine\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDPdxCoarse : Instruction\n    {\n        public OpDPdxCoarse() : base(\"OpDPdxCoarse\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDPdyCoarse : Instruction\n    {\n        public OpDPdyCoarse() : base(\"OpDPdyCoarse\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFwidthCoarse : Instruction\n    {\n        public OpFwidthCoarse() : base(\"OpFwidthCoarse\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"P\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpEmitVertex : Instruction\n    {\n        public OpEmitVertex() : base(\"OpEmitVertex\")\n        {\n        }\n    }\n    public class OpEndPrimitive : Instruction\n    {\n        public OpEndPrimitive() : base(\"OpEndPrimitive\")\n        {\n        }\n    }\n    public class OpEmitStreamVertex : Instruction\n    {\n        public OpEmitStreamVertex() : base(\"OpEmitStreamVertex\", new List<Operand>()\n    {new Operand(new IdRef(), \"Stream\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpEndStreamPrimitive : Instruction\n    {\n        public OpEndStreamPrimitive() : base(\"OpEndStreamPrimitive\", new List<Operand>()\n    {new Operand(new IdRef(), \"Stream\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpControlBarrier : Instruction\n    {\n        public OpControlBarrier() : base(\"OpControlBarrier\", new List<Operand>()\n    {new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdScope(), \"Memory\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpMemoryBarrier : Instruction\n    {\n        public OpMemoryBarrier() : base(\"OpMemoryBarrier\", new List<Operand>()\n    {new Operand(new IdScope(), \"Memory\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicLoad : Instruction\n    {\n        public OpAtomicLoad() : base(\"OpAtomicLoad\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicStore : Instruction\n    {\n        public OpAtomicStore() : base(\"OpAtomicStore\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicExchange : Instruction\n    {\n        public OpAtomicExchange() : base(\"OpAtomicExchange\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicCompareExchange : Instruction\n    {\n        public OpAtomicCompareExchange() : base(\"OpAtomicCompareExchange\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Equal\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Unequal\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), new Operand(new IdRef(), \"Comparator\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicCompareExchangeWeak : Instruction\n    {\n        public OpAtomicCompareExchangeWeak() : base(\"OpAtomicCompareExchangeWeak\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Equal\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Unequal\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), new Operand(new IdRef(), \"Comparator\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicIIncrement : Instruction\n    {\n        public OpAtomicIIncrement() : base(\"OpAtomicIIncrement\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicIDecrement : Instruction\n    {\n        public OpAtomicIDecrement() : base(\"OpAtomicIDecrement\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicIAdd : Instruction\n    {\n        public OpAtomicIAdd() : base(\"OpAtomicIAdd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicISub : Instruction\n    {\n        public OpAtomicISub() : base(\"OpAtomicISub\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicSMin : Instruction\n    {\n        public OpAtomicSMin() : base(\"OpAtomicSMin\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicUMin : Instruction\n    {\n        public OpAtomicUMin() : base(\"OpAtomicUMin\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicSMax : Instruction\n    {\n        public OpAtomicSMax() : base(\"OpAtomicSMax\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicUMax : Instruction\n    {\n        public OpAtomicUMax() : base(\"OpAtomicUMax\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicAnd : Instruction\n    {\n        public OpAtomicAnd() : base(\"OpAtomicAnd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicOr : Instruction\n    {\n        public OpAtomicOr() : base(\"OpAtomicOr\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicXor : Instruction\n    {\n        public OpAtomicXor() : base(\"OpAtomicXor\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpPhi : Instruction\n    {\n        public OpPhi() : base(\"OpPhi\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new PairIdRefIdRef(), \"Variable, Parent, ...\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpLoopMerge : Instruction\n    {\n        public OpLoopMerge() : base(\"OpLoopMerge\", new List<Operand>()\n    {new Operand(new IdRef(), \"Merge Block\", OperandQuantifier.Default), new Operand(new IdRef(), \"Continue Target\", OperandQuantifier.Default), new Operand(new EnumType<LoopControl, LoopControlParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSelectionMerge : Instruction\n    {\n        public OpSelectionMerge() : base(\"OpSelectionMerge\", new List<Operand>()\n    {new Operand(new IdRef(), \"Merge Block\", OperandQuantifier.Default), new Operand(new EnumType<SelectionControl, SelectionControlParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLabel : Instruction\n    {\n        public OpLabel() : base(\"OpLabel\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBranch : Instruction\n    {\n        public OpBranch() : base(\"OpBranch\", new List<Operand>()\n    {new Operand(new IdRef(), \"Target Label\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBranchConditional : Instruction\n    {\n        public OpBranchConditional() : base(\"OpBranchConditional\", new List<Operand>()\n    {new Operand(new IdRef(), \"Condition\", OperandQuantifier.Default), new Operand(new IdRef(), \"True Label\", OperandQuantifier.Default), new Operand(new IdRef(), \"False Label\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Branch weights\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpSwitch : Instruction\n    {\n        public OpSwitch() : base(\"OpSwitch\", new List<Operand>()\n    {new Operand(new IdRef(), \"Selector\", OperandQuantifier.Default), new Operand(new IdRef(), \"Default\", OperandQuantifier.Default), new Operand(new PairLiteralIntegerIdRef(), \"Target\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpKill : Instruction\n    {\n        public OpKill() : base(\"OpKill\")\n        {\n        }\n    }\n    public class OpReturn : Instruction\n    {\n        public OpReturn() : base(\"OpReturn\")\n        {\n        }\n    }\n    public class OpReturnValue : Instruction\n    {\n        public OpReturnValue() : base(\"OpReturnValue\", new List<Operand>()\n    {new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpUnreachable : Instruction\n    {\n        public OpUnreachable() : base(\"OpUnreachable\")\n        {\n        }\n    }\n    public class OpLifetimeStart : Instruction\n    {\n        public OpLifetimeStart() : base(\"OpLifetimeStart\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Size\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpLifetimeStop : Instruction\n    {\n        public OpLifetimeStop() : base(\"OpLifetimeStop\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Size\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupAsyncCopy : Instruction\n    {\n        public OpGroupAsyncCopy() : base(\"OpGroupAsyncCopy\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Destination\", OperandQuantifier.Default), new Operand(new IdRef(), \"Source\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Elements\", OperandQuantifier.Default), new Operand(new IdRef(), \"Stride\", OperandQuantifier.Default), new Operand(new IdRef(), \"Event\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupWaitEvents : Instruction\n    {\n        public OpGroupWaitEvents() : base(\"OpGroupWaitEvents\", new List<Operand>()\n    {new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Events\", OperandQuantifier.Default), new Operand(new IdRef(), \"Events List\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupAll : Instruction\n    {\n        public OpGroupAll() : base(\"OpGroupAll\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Predicate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupAny : Instruction\n    {\n        public OpGroupAny() : base(\"OpGroupAny\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Predicate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupBroadcast : Instruction\n    {\n        public OpGroupBroadcast() : base(\"OpGroupBroadcast\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), new Operand(new IdRef(), \"LocalId\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupIAdd : Instruction\n    {\n        public OpGroupIAdd() : base(\"OpGroupIAdd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupFAdd : Instruction\n    {\n        public OpGroupFAdd() : base(\"OpGroupFAdd\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupFMin : Instruction\n    {\n        public OpGroupFMin() : base(\"OpGroupFMin\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupUMin : Instruction\n    {\n        public OpGroupUMin() : base(\"OpGroupUMin\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupSMin : Instruction\n    {\n        public OpGroupSMin() : base(\"OpGroupSMin\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupFMax : Instruction\n    {\n        public OpGroupFMax() : base(\"OpGroupFMax\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupUMax : Instruction\n    {\n        public OpGroupUMax() : base(\"OpGroupUMax\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupSMax : Instruction\n    {\n        public OpGroupSMax() : base(\"OpGroupSMax\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpReadPipe : Instruction\n    {\n        public OpReadPipe() : base(\"OpReadPipe\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpWritePipe : Instruction\n    {\n        public OpWritePipe() : base(\"OpWritePipe\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpReservedReadPipe : Instruction\n    {\n        public OpReservedReadPipe() : base(\"OpReservedReadPipe\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Reserve Id\", OperandQuantifier.Default), new Operand(new IdRef(), \"Index\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpReservedWritePipe : Instruction\n    {\n        public OpReservedWritePipe() : base(\"OpReservedWritePipe\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Reserve Id\", OperandQuantifier.Default), new Operand(new IdRef(), \"Index\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpReserveReadPipePackets : Instruction\n    {\n        public OpReserveReadPipePackets() : base(\"OpReserveReadPipePackets\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Packets\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpReserveWritePipePackets : Instruction\n    {\n        public OpReserveWritePipePackets() : base(\"OpReserveWritePipePackets\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Packets\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpCommitReadPipe : Instruction\n    {\n        public OpCommitReadPipe() : base(\"OpCommitReadPipe\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Reserve Id\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpCommitWritePipe : Instruction\n    {\n        public OpCommitWritePipe() : base(\"OpCommitWritePipe\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Reserve Id\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIsValidReserveId : Instruction\n    {\n        public OpIsValidReserveId() : base(\"OpIsValidReserveId\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Reserve Id\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetNumPipePackets : Instruction\n    {\n        public OpGetNumPipePackets() : base(\"OpGetNumPipePackets\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetMaxPipePackets : Instruction\n    {\n        public OpGetMaxPipePackets() : base(\"OpGetMaxPipePackets\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupReserveReadPipePackets : Instruction\n    {\n        public OpGroupReserveReadPipePackets() : base(\"OpGroupReserveReadPipePackets\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Packets\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupReserveWritePipePackets : Instruction\n    {\n        public OpGroupReserveWritePipePackets() : base(\"OpGroupReserveWritePipePackets\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Packets\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupCommitReadPipe : Instruction\n    {\n        public OpGroupCommitReadPipe() : base(\"OpGroupCommitReadPipe\", new List<Operand>()\n    {new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Reserve Id\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupCommitWritePipe : Instruction\n    {\n        public OpGroupCommitWritePipe() : base(\"OpGroupCommitWritePipe\", new List<Operand>()\n    {new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe\", OperandQuantifier.Default), new Operand(new IdRef(), \"Reserve Id\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Packet Alignment\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpEnqueueMarker : Instruction\n    {\n        public OpEnqueueMarker() : base(\"OpEnqueueMarker\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Queue\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Events\", OperandQuantifier.Default), new Operand(new IdRef(), \"Wait Events\", OperandQuantifier.Default), new Operand(new IdRef(), \"Ret Event\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpEnqueueKernel : Instruction\n    {\n        public OpEnqueueKernel() : base(\"OpEnqueueKernel\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Queue\", OperandQuantifier.Default), new Operand(new IdRef(), \"Flags\", OperandQuantifier.Default), new Operand(new IdRef(), \"ND Range\", OperandQuantifier.Default), new Operand(new IdRef(), \"Num Events\", OperandQuantifier.Default), new Operand(new IdRef(), \"Wait Events\", OperandQuantifier.Default), new Operand(new IdRef(), \"Ret Event\", OperandQuantifier.Default), new Operand(new IdRef(), \"Invoke\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Align\", OperandQuantifier.Default), new Operand(new IdRef(), \"Local Size\", OperandQuantifier.Varying), })\n        {\n        }\n    }\n    public class OpGetKernelNDrangeSubGroupCount : Instruction\n    {\n        public OpGetKernelNDrangeSubGroupCount() : base(\"OpGetKernelNDrangeSubGroupCount\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"ND Range\", OperandQuantifier.Default), new Operand(new IdRef(), \"Invoke\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Align\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetKernelNDrangeMaxSubGroupSize : Instruction\n    {\n        public OpGetKernelNDrangeMaxSubGroupSize() : base(\"OpGetKernelNDrangeMaxSubGroupSize\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"ND Range\", OperandQuantifier.Default), new Operand(new IdRef(), \"Invoke\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Align\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetKernelWorkGroupSize : Instruction\n    {\n        public OpGetKernelWorkGroupSize() : base(\"OpGetKernelWorkGroupSize\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Invoke\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Align\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetKernelPreferredWorkGroupSizeMultiple : Instruction\n    {\n        public OpGetKernelPreferredWorkGroupSizeMultiple() : base(\"OpGetKernelPreferredWorkGroupSizeMultiple\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Invoke\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Align\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpRetainEvent : Instruction\n    {\n        public OpRetainEvent() : base(\"OpRetainEvent\", new List<Operand>()\n    {new Operand(new IdRef(), \"Event\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpReleaseEvent : Instruction\n    {\n        public OpReleaseEvent() : base(\"OpReleaseEvent\", new List<Operand>()\n    {new Operand(new IdRef(), \"Event\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpCreateUserEvent : Instruction\n    {\n        public OpCreateUserEvent() : base(\"OpCreateUserEvent\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpIsValidEvent : Instruction\n    {\n        public OpIsValidEvent() : base(\"OpIsValidEvent\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Event\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSetUserEventStatus : Instruction\n    {\n        public OpSetUserEventStatus() : base(\"OpSetUserEventStatus\", new List<Operand>()\n    {new Operand(new IdRef(), \"Event\", OperandQuantifier.Default), new Operand(new IdRef(), \"Status\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpCaptureEventProfilingInfo : Instruction\n    {\n        public OpCaptureEventProfilingInfo() : base(\"OpCaptureEventProfilingInfo\", new List<Operand>()\n    {new Operand(new IdRef(), \"Event\", OperandQuantifier.Default), new Operand(new IdRef(), \"Profiling Info\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetDefaultQueue : Instruction\n    {\n        public OpGetDefaultQueue() : base(\"OpGetDefaultQueue\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpBuildNDRange : Instruction\n    {\n        public OpBuildNDRange() : base(\"OpBuildNDRange\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"GlobalWorkSize\", OperandQuantifier.Default), new Operand(new IdRef(), \"LocalWorkSize\", OperandQuantifier.Default), new Operand(new IdRef(), \"GlobalWorkOffset\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSparseSampleImplicitLod : Instruction\n    {\n        public OpImageSparseSampleImplicitLod() : base(\"OpImageSparseSampleImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSparseSampleExplicitLod : Instruction\n    {\n        public OpImageSparseSampleExplicitLod() : base(\"OpImageSparseSampleExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSparseSampleDrefImplicitLod : Instruction\n    {\n        public OpImageSparseSampleDrefImplicitLod() : base(\"OpImageSparseSampleDrefImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSparseSampleDrefExplicitLod : Instruction\n    {\n        public OpImageSparseSampleDrefExplicitLod() : base(\"OpImageSparseSampleDrefExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSparseSampleProjImplicitLod : Instruction\n    {\n        public OpImageSparseSampleProjImplicitLod() : base(\"OpImageSparseSampleProjImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSparseSampleProjExplicitLod : Instruction\n    {\n        public OpImageSparseSampleProjExplicitLod() : base(\"OpImageSparseSampleProjExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSparseSampleProjDrefImplicitLod : Instruction\n    {\n        public OpImageSparseSampleProjDrefImplicitLod() : base(\"OpImageSparseSampleProjDrefImplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSparseSampleProjDrefExplicitLod : Instruction\n    {\n        public OpImageSparseSampleProjDrefExplicitLod() : base(\"OpImageSparseSampleProjDrefExplicitLod\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSparseFetch : Instruction\n    {\n        public OpImageSparseFetch() : base(\"OpImageSparseFetch\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSparseGather : Instruction\n    {\n        public OpImageSparseGather() : base(\"OpImageSparseGather\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"Component\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSparseDrefGather : Instruction\n    {\n        public OpImageSparseDrefGather() : base(\"OpImageSparseDrefGather\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Sampled Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"D~ref~\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpImageSparseTexelsResident : Instruction\n    {\n        public OpImageSparseTexelsResident() : base(\"OpImageSparseTexelsResident\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Resident Code\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpNoLine : Instruction\n    {\n        public OpNoLine() : base(\"OpNoLine\")\n        {\n        }\n    }\n    public class OpAtomicFlagTestAndSet : Instruction\n    {\n        public OpAtomicFlagTestAndSet() : base(\"OpAtomicFlagTestAndSet\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpAtomicFlagClear : Instruction\n    {\n        public OpAtomicFlagClear() : base(\"OpAtomicFlagClear\", new List<Operand>()\n    {new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), new Operand(new IdScope(), \"Scope\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpImageSparseRead : Instruction\n    {\n        public OpImageSparseRead() : base(\"OpImageSparseRead\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new EnumType<ImageOperands, ImageOperandsParameterFactory>(), null, OperandQuantifier.Optional), })\n        {\n        }\n    }\n    public class OpSizeOf : Instruction\n    {\n        public OpSizeOf() : base(\"OpSizeOf\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pointer\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypePipeStorage : Instruction\n    {\n        public OpTypePipeStorage() : base(\"OpTypePipeStorage\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpConstantPipeStorage : Instruction\n    {\n        public OpConstantPipeStorage() : base(\"OpConstantPipeStorage\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Packet Size\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Packet Alignment\", OperandQuantifier.Default), new Operand(new LiteralInteger(), \"Capacity\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpCreatePipeFromPipeStorage : Instruction\n    {\n        public OpCreatePipeFromPipeStorage() : base(\"OpCreatePipeFromPipeStorage\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Pipe Storage\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetKernelLocalSizeForSubgroupCount : Instruction\n    {\n        public OpGetKernelLocalSizeForSubgroupCount() : base(\"OpGetKernelLocalSizeForSubgroupCount\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Subgroup Count\", OperandQuantifier.Default), new Operand(new IdRef(), \"Invoke\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Align\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGetKernelMaxNumSubgroups : Instruction\n    {\n        public OpGetKernelMaxNumSubgroups() : base(\"OpGetKernelMaxNumSubgroups\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Invoke\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Size\", OperandQuantifier.Default), new Operand(new IdRef(), \"Param Align\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpTypeNamedBarrier : Instruction\n    {\n        public OpTypeNamedBarrier() : base(\"OpTypeNamedBarrier\", new List<Operand>()\n    {new Operand(new IdResult(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpNamedBarrierInitialize : Instruction\n    {\n        public OpNamedBarrierInitialize() : base(\"OpNamedBarrierInitialize\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Subgroup Count\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpMemoryNamedBarrier : Instruction\n    {\n        public OpMemoryNamedBarrier() : base(\"OpMemoryNamedBarrier\", new List<Operand>()\n    {new Operand(new IdRef(), \"Named Barrier\", OperandQuantifier.Default), new Operand(new IdScope(), \"Memory\", OperandQuantifier.Default), new Operand(new IdMemorySemantics(), \"Semantics\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpModuleProcessed : Instruction\n    {\n        public OpModuleProcessed() : base(\"OpModuleProcessed\", new List<Operand>()\n    {new Operand(new LiteralString(), \"Process\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpExecutionModeId : Instruction\n    {\n        public OpExecutionModeId() : base(\"OpExecutionModeId\", new List<Operand>()\n    {new Operand(new IdRef(), \"Entry Point\", OperandQuantifier.Default), new Operand(new EnumType<ExecutionMode, ExecutionModeParameterFactory>(), \"Mode\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpDecorateId : Instruction\n    {\n        public OpDecorateId() : base(\"OpDecorateId\", new List<Operand>()\n    {new Operand(new IdRef(), \"Target\", OperandQuantifier.Default), new Operand(new EnumType<Decoration, DecorationParameterFactory>(), null, OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupBallotKHR : Instruction\n    {\n        public OpSubgroupBallotKHR() : base(\"OpSubgroupBallotKHR\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Predicate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupFirstInvocationKHR : Instruction\n    {\n        public OpSubgroupFirstInvocationKHR() : base(\"OpSubgroupFirstInvocationKHR\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupAllKHR : Instruction\n    {\n        public OpSubgroupAllKHR() : base(\"OpSubgroupAllKHR\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Predicate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupAnyKHR : Instruction\n    {\n        public OpSubgroupAnyKHR() : base(\"OpSubgroupAnyKHR\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Predicate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupAllEqualKHR : Instruction\n    {\n        public OpSubgroupAllEqualKHR() : base(\"OpSubgroupAllEqualKHR\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Predicate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupReadInvocationKHR : Instruction\n    {\n        public OpSubgroupReadInvocationKHR() : base(\"OpSubgroupReadInvocationKHR\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), new Operand(new IdRef(), \"Index\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupIAddNonUniformAMD : Instruction\n    {\n        public OpGroupIAddNonUniformAMD() : base(\"OpGroupIAddNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupFAddNonUniformAMD : Instruction\n    {\n        public OpGroupFAddNonUniformAMD() : base(\"OpGroupFAddNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupFMinNonUniformAMD : Instruction\n    {\n        public OpGroupFMinNonUniformAMD() : base(\"OpGroupFMinNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupUMinNonUniformAMD : Instruction\n    {\n        public OpGroupUMinNonUniformAMD() : base(\"OpGroupUMinNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupSMinNonUniformAMD : Instruction\n    {\n        public OpGroupSMinNonUniformAMD() : base(\"OpGroupSMinNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupFMaxNonUniformAMD : Instruction\n    {\n        public OpGroupFMaxNonUniformAMD() : base(\"OpGroupFMaxNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupUMaxNonUniformAMD : Instruction\n    {\n        public OpGroupUMaxNonUniformAMD() : base(\"OpGroupUMaxNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpGroupSMaxNonUniformAMD : Instruction\n    {\n        public OpGroupSMaxNonUniformAMD() : base(\"OpGroupSMaxNonUniformAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdScope(), \"Execution\", OperandQuantifier.Default), new Operand(new EnumType<GroupOperation, GroupOperationParameterFactory>(), \"Operation\", OperandQuantifier.Default), new Operand(new IdRef(), \"X\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFragmentMaskFetchAMD : Instruction\n    {\n        public OpFragmentMaskFetchAMD() : base(\"OpFragmentMaskFetchAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpFragmentFetchAMD : Instruction\n    {\n        public OpFragmentFetchAMD() : base(\"OpFragmentFetchAMD\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"Fragment Index\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupShuffleINTEL : Instruction\n    {\n        public OpSubgroupShuffleINTEL() : base(\"OpSubgroupShuffleINTEL\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Data\", OperandQuantifier.Default), new Operand(new IdRef(), \"InvocationId\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupShuffleDownINTEL : Instruction\n    {\n        public OpSubgroupShuffleDownINTEL() : base(\"OpSubgroupShuffleDownINTEL\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Current\", OperandQuantifier.Default), new Operand(new IdRef(), \"Next\", OperandQuantifier.Default), new Operand(new IdRef(), \"Delta\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupShuffleUpINTEL : Instruction\n    {\n        public OpSubgroupShuffleUpINTEL() : base(\"OpSubgroupShuffleUpINTEL\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Previous\", OperandQuantifier.Default), new Operand(new IdRef(), \"Current\", OperandQuantifier.Default), new Operand(new IdRef(), \"Delta\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupShuffleXorINTEL : Instruction\n    {\n        public OpSubgroupShuffleXorINTEL() : base(\"OpSubgroupShuffleXorINTEL\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Data\", OperandQuantifier.Default), new Operand(new IdRef(), \"Value\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupBlockReadINTEL : Instruction\n    {\n        public OpSubgroupBlockReadINTEL() : base(\"OpSubgroupBlockReadINTEL\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Ptr\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupBlockWriteINTEL : Instruction\n    {\n        public OpSubgroupBlockWriteINTEL() : base(\"OpSubgroupBlockWriteINTEL\", new List<Operand>()\n    {new Operand(new IdRef(), \"Ptr\", OperandQuantifier.Default), new Operand(new IdRef(), \"Data\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupImageBlockReadINTEL : Instruction\n    {\n        public OpSubgroupImageBlockReadINTEL() : base(\"OpSubgroupImageBlockReadINTEL\", new List<Operand>()\n    {new Operand(new IdResultType(), null, OperandQuantifier.Default), new Operand(new IdResult(), null, OperandQuantifier.Default), new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public class OpSubgroupImageBlockWriteINTEL : Instruction\n    {\n        public OpSubgroupImageBlockWriteINTEL() : base(\"OpSubgroupImageBlockWriteINTEL\", new List<Operand>()\n    {new Operand(new IdRef(), \"Image\", OperandQuantifier.Default), new Operand(new IdRef(), \"Coordinate\", OperandQuantifier.Default), new Operand(new IdRef(), \"Data\", OperandQuantifier.Default), })\n        {\n        }\n    }\n    public static class Instructions\n    {\n        private static readonly Dictionary<int, Instruction> instructions_ = new Dictionary<int, Instruction> { { 0, new OpNop() }, { 1, new OpUndef() }, { 2, new OpSourceContinued() }, { 3, new OpSource() }, { 4, new OpSourceExtension() }, { 5, new OpName() }, { 6, new OpMemberName() }, { 7, new OpString() }, { 8, new OpLine() }, { 10, new OpExtension() }, { 11, new OpExtInstImport() }, { 12, new OpExtInst() }, { 14, new OpMemoryModel() }, { 15, new OpEntryPoint() }, { 16, new OpExecutionMode() }, { 17, new OpCapability() }, { 19, new OpTypeVoid() }, { 20, new OpTypeBool() }, { 21, new OpTypeInt() }, { 22, new OpTypeFloat() }, { 23, new OpTypeVector() }, { 24, new OpTypeMatrix() }, { 25, new OpTypeImage() }, { 26, new OpTypeSampler() }, { 27, new OpTypeSampledImage() }, { 28, new OpTypeArray() }, { 29, new OpTypeRuntimeArray() }, { 30, new OpTypeStruct() }, { 31, new OpTypeOpaque() }, { 32, new OpTypePointer() }, { 33, new OpTypeFunction() }, { 34, new OpTypeEvent() }, { 35, new OpTypeDeviceEvent() }, { 36, new OpTypeReserveId() }, { 37, new OpTypeQueue() }, { 38, new OpTypePipe() }, { 39, new OpTypeForwardPointer() }, { 41, new OpConstantTrue() }, { 42, new OpConstantFalse() }, { 43, new OpConstant() }, { 44, new OpConstantComposite() }, { 45, new OpConstantSampler() }, { 46, new OpConstantNull() }, { 48, new OpSpecConstantTrue() }, { 49, new OpSpecConstantFalse() }, { 50, new OpSpecConstant() }, { 51, new OpSpecConstantComposite() }, { 52, new OpSpecConstantOp() }, { 54, new OpFunction() }, { 55, new OpFunctionParameter() }, { 56, new OpFunctionEnd() }, { 57, new OpFunctionCall() }, { 59, new OpVariable() }, { 60, new OpImageTexelPointer() }, { 61, new OpLoad() }, { 62, new OpStore() }, { 63, new OpCopyMemory() }, { 64, new OpCopyMemorySized() }, { 65, new OpAccessChain() }, { 66, new OpInBoundsAccessChain() }, { 67, new OpPtrAccessChain() }, { 68, new OpArrayLength() }, { 69, new OpGenericPtrMemSemantics() }, { 70, new OpInBoundsPtrAccessChain() }, { 71, new OpDecorate() }, { 72, new OpMemberDecorate() }, { 73, new OpDecorationGroup() }, { 74, new OpGroupDecorate() }, { 75, new OpGroupMemberDecorate() }, { 77, new OpVectorExtractDynamic() }, { 78, new OpVectorInsertDynamic() }, { 79, new OpVectorShuffle() }, { 80, new OpCompositeConstruct() }, { 81, new OpCompositeExtract() }, { 82, new OpCompositeInsert() }, { 83, new OpCopyObject() }, { 84, new OpTranspose() }, { 86, new OpSampledImage() }, { 87, new OpImageSampleImplicitLod() }, { 88, new OpImageSampleExplicitLod() }, { 89, new OpImageSampleDrefImplicitLod() }, { 90, new OpImageSampleDrefExplicitLod() }, { 91, new OpImageSampleProjImplicitLod() }, { 92, new OpImageSampleProjExplicitLod() }, { 93, new OpImageSampleProjDrefImplicitLod() }, { 94, new OpImageSampleProjDrefExplicitLod() }, { 95, new OpImageFetch() }, { 96, new OpImageGather() }, { 97, new OpImageDrefGather() }, { 98, new OpImageRead() }, { 99, new OpImageWrite() }, { 100, new OpImage() }, { 101, new OpImageQueryFormat() }, { 102, new OpImageQueryOrder() }, { 103, new OpImageQuerySizeLod() }, { 104, new OpImageQuerySize() }, { 105, new OpImageQueryLod() }, { 106, new OpImageQueryLevels() }, { 107, new OpImageQuerySamples() }, { 109, new OpConvertFToU() }, { 110, new OpConvertFToS() }, { 111, new OpConvertSToF() }, { 112, new OpConvertUToF() }, { 113, new OpUConvert() }, { 114, new OpSConvert() }, { 115, new OpFConvert() }, { 116, new OpQuantizeToF16() }, { 117, new OpConvertPtrToU() }, { 118, new OpSatConvertSToU() }, { 119, new OpSatConvertUToS() }, { 120, new OpConvertUToPtr() }, { 121, new OpPtrCastToGeneric() }, { 122, new OpGenericCastToPtr() }, { 123, new OpGenericCastToPtrExplicit() }, { 124, new OpBitcast() }, { 126, new OpSNegate() }, { 127, new OpFNegate() }, { 128, new OpIAdd() }, { 129, new OpFAdd() }, { 130, new OpISub() }, { 131, new OpFSub() }, { 132, new OpIMul() }, { 133, new OpFMul() }, { 134, new OpUDiv() }, { 135, new OpSDiv() }, { 136, new OpFDiv() }, { 137, new OpUMod() }, { 138, new OpSRem() }, { 139, new OpSMod() }, { 140, new OpFRem() }, { 141, new OpFMod() }, { 142, new OpVectorTimesScalar() }, { 143, new OpMatrixTimesScalar() }, { 144, new OpVectorTimesMatrix() }, { 145, new OpMatrixTimesVector() }, { 146, new OpMatrixTimesMatrix() }, { 147, new OpOuterProduct() }, { 148, new OpDot() }, { 149, new OpIAddCarry() }, { 150, new OpISubBorrow() }, { 151, new OpUMulExtended() }, { 152, new OpSMulExtended() }, { 154, new OpAny() }, { 155, new OpAll() }, { 156, new OpIsNan() }, { 157, new OpIsInf() }, { 158, new OpIsFinite() }, { 159, new OpIsNormal() }, { 160, new OpSignBitSet() }, { 161, new OpLessOrGreater() }, { 162, new OpOrdered() }, { 163, new OpUnordered() }, { 164, new OpLogicalEqual() }, { 165, new OpLogicalNotEqual() }, { 166, new OpLogicalOr() }, { 167, new OpLogicalAnd() }, { 168, new OpLogicalNot() }, { 169, new OpSelect() }, { 170, new OpIEqual() }, { 171, new OpINotEqual() }, { 172, new OpUGreaterThan() }, { 173, new OpSGreaterThan() }, { 174, new OpUGreaterThanEqual() }, { 175, new OpSGreaterThanEqual() }, { 176, new OpULessThan() }, { 177, new OpSLessThan() }, { 178, new OpULessThanEqual() }, { 179, new OpSLessThanEqual() }, { 180, new OpFOrdEqual() }, { 181, new OpFUnordEqual() }, { 182, new OpFOrdNotEqual() }, { 183, new OpFUnordNotEqual() }, { 184, new OpFOrdLessThan() }, { 185, new OpFUnordLessThan() }, { 186, new OpFOrdGreaterThan() }, { 187, new OpFUnordGreaterThan() }, { 188, new OpFOrdLessThanEqual() }, { 189, new OpFUnordLessThanEqual() }, { 190, new OpFOrdGreaterThanEqual() }, { 191, new OpFUnordGreaterThanEqual() }, { 194, new OpShiftRightLogical() }, { 195, new OpShiftRightArithmetic() }, { 196, new OpShiftLeftLogical() }, { 197, new OpBitwiseOr() }, { 198, new OpBitwiseXor() }, { 199, new OpBitwiseAnd() }, { 200, new OpNot() }, { 201, new OpBitFieldInsert() }, { 202, new OpBitFieldSExtract() }, { 203, new OpBitFieldUExtract() }, { 204, new OpBitReverse() }, { 205, new OpBitCount() }, { 207, new OpDPdx() }, { 208, new OpDPdy() }, { 209, new OpFwidth() }, { 210, new OpDPdxFine() }, { 211, new OpDPdyFine() }, { 212, new OpFwidthFine() }, { 213, new OpDPdxCoarse() }, { 214, new OpDPdyCoarse() }, { 215, new OpFwidthCoarse() }, { 218, new OpEmitVertex() }, { 219, new OpEndPrimitive() }, { 220, new OpEmitStreamVertex() }, { 221, new OpEndStreamPrimitive() }, { 224, new OpControlBarrier() }, { 225, new OpMemoryBarrier() }, { 227, new OpAtomicLoad() }, { 228, new OpAtomicStore() }, { 229, new OpAtomicExchange() }, { 230, new OpAtomicCompareExchange() }, { 231, new OpAtomicCompareExchangeWeak() }, { 232, new OpAtomicIIncrement() }, { 233, new OpAtomicIDecrement() }, { 234, new OpAtomicIAdd() }, { 235, new OpAtomicISub() }, { 236, new OpAtomicSMin() }, { 237, new OpAtomicUMin() }, { 238, new OpAtomicSMax() }, { 239, new OpAtomicUMax() }, { 240, new OpAtomicAnd() }, { 241, new OpAtomicOr() }, { 242, new OpAtomicXor() }, { 245, new OpPhi() }, { 246, new OpLoopMerge() }, { 247, new OpSelectionMerge() }, { 248, new OpLabel() }, { 249, new OpBranch() }, { 250, new OpBranchConditional() }, { 251, new OpSwitch() }, { 252, new OpKill() }, { 253, new OpReturn() }, { 254, new OpReturnValue() }, { 255, new OpUnreachable() }, { 256, new OpLifetimeStart() }, { 257, new OpLifetimeStop() }, { 259, new OpGroupAsyncCopy() }, { 260, new OpGroupWaitEvents() }, { 261, new OpGroupAll() }, { 262, new OpGroupAny() }, { 263, new OpGroupBroadcast() }, { 264, new OpGroupIAdd() }, { 265, new OpGroupFAdd() }, { 266, new OpGroupFMin() }, { 267, new OpGroupUMin() }, { 268, new OpGroupSMin() }, { 269, new OpGroupFMax() }, { 270, new OpGroupUMax() }, { 271, new OpGroupSMax() }, { 274, new OpReadPipe() }, { 275, new OpWritePipe() }, { 276, new OpReservedReadPipe() }, { 277, new OpReservedWritePipe() }, { 278, new OpReserveReadPipePackets() }, { 279, new OpReserveWritePipePackets() }, { 280, new OpCommitReadPipe() }, { 281, new OpCommitWritePipe() }, { 282, new OpIsValidReserveId() }, { 283, new OpGetNumPipePackets() }, { 284, new OpGetMaxPipePackets() }, { 285, new OpGroupReserveReadPipePackets() }, { 286, new OpGroupReserveWritePipePackets() }, { 287, new OpGroupCommitReadPipe() }, { 288, new OpGroupCommitWritePipe() }, { 291, new OpEnqueueMarker() }, { 292, new OpEnqueueKernel() }, { 293, new OpGetKernelNDrangeSubGroupCount() }, { 294, new OpGetKernelNDrangeMaxSubGroupSize() }, { 295, new OpGetKernelWorkGroupSize() }, { 296, new OpGetKernelPreferredWorkGroupSizeMultiple() }, { 297, new OpRetainEvent() }, { 298, new OpReleaseEvent() }, { 299, new OpCreateUserEvent() }, { 300, new OpIsValidEvent() }, { 301, new OpSetUserEventStatus() }, { 302, new OpCaptureEventProfilingInfo() }, { 303, new OpGetDefaultQueue() }, { 304, new OpBuildNDRange() }, { 305, new OpImageSparseSampleImplicitLod() }, { 306, new OpImageSparseSampleExplicitLod() }, { 307, new OpImageSparseSampleDrefImplicitLod() }, { 308, new OpImageSparseSampleDrefExplicitLod() }, { 309, new OpImageSparseSampleProjImplicitLod() }, { 310, new OpImageSparseSampleProjExplicitLod() }, { 311, new OpImageSparseSampleProjDrefImplicitLod() }, { 312, new OpImageSparseSampleProjDrefExplicitLod() }, { 313, new OpImageSparseFetch() }, { 314, new OpImageSparseGather() }, { 315, new OpImageSparseDrefGather() }, { 316, new OpImageSparseTexelsResident() }, { 317, new OpNoLine() }, { 318, new OpAtomicFlagTestAndSet() }, { 319, new OpAtomicFlagClear() }, { 320, new OpImageSparseRead() }, { 321, new OpSizeOf() }, { 322, new OpTypePipeStorage() }, { 323, new OpConstantPipeStorage() }, { 324, new OpCreatePipeFromPipeStorage() }, { 325, new OpGetKernelLocalSizeForSubgroupCount() }, { 326, new OpGetKernelMaxNumSubgroups() }, { 327, new OpTypeNamedBarrier() }, { 328, new OpNamedBarrierInitialize() }, { 329, new OpMemoryNamedBarrier() }, { 330, new OpModuleProcessed() }, { 331, new OpExecutionModeId() }, { 332, new OpDecorateId() }, { 4421, new OpSubgroupBallotKHR() }, { 4422, new OpSubgroupFirstInvocationKHR() }, { 4428, new OpSubgroupAllKHR() }, { 4429, new OpSubgroupAnyKHR() }, { 4430, new OpSubgroupAllEqualKHR() }, { 4432, new OpSubgroupReadInvocationKHR() }, { 5000, new OpGroupIAddNonUniformAMD() }, { 5001, new OpGroupFAddNonUniformAMD() }, { 5002, new OpGroupFMinNonUniformAMD() }, { 5003, new OpGroupUMinNonUniformAMD() }, { 5004, new OpGroupSMinNonUniformAMD() }, { 5005, new OpGroupFMaxNonUniformAMD() }, { 5006, new OpGroupUMaxNonUniformAMD() }, { 5007, new OpGroupSMaxNonUniformAMD() }, { 5011, new OpFragmentMaskFetchAMD() }, { 5012, new OpFragmentFetchAMD() }, { 5571, new OpSubgroupShuffleINTEL() }, { 5572, new OpSubgroupShuffleDownINTEL() }, { 5573, new OpSubgroupShuffleUpINTEL() }, { 5574, new OpSubgroupShuffleXorINTEL() }, { 5575, new OpSubgroupBlockReadINTEL() }, { 5576, new OpSubgroupBlockWriteINTEL() }, { 5577, new OpSubgroupImageBlockReadINTEL() }, { 5578, new OpSubgroupImageBlockWriteINTEL() }, };\n        public static IReadOnlyDictionary<int, Instruction> OpcodeToInstruction\n        {\n            get => instructions_;\n        }\n    }\n}"
  },
  {
    "path": "AssetStudioUtility/CSspv/SpirV.Meta.cs",
    "content": "using System.Collections.Generic;\n\nnamespace SpirV\n{\n\tinternal class Meta\n    {\n        public class ToolInfo\n        {\n            public ToolInfo(string vendor)\n            {\n                Vendor = vendor;\n            }\n\n            public ToolInfo(string vendor, string name)\n            {\n                Vendor = vendor;\n                Name = name;\n            }\n\n            public string Name { get; }\n            public string Vendor { get; }\n        }\n\n\t\tpublic static uint MagicNumber => 119734787U;\n\t\tpublic static uint Version => 66048U;\n\t\tpublic static uint Revision => 2U;\n\t\tpublic static uint OpCodeMask => 65535U;\n\t\tpublic static uint WordCountShift => 16U;\n\n\t\tpublic static IReadOnlyDictionary<int, ToolInfo> Tools => toolInfos_;\n\n\t\tprivate readonly static Dictionary<int, ToolInfo> toolInfos_ = new Dictionary<int, ToolInfo>\n\t\t{\n\t\t\t{ 0, new ToolInfo(\"Khronos\") },\n\t\t\t{ 1, new ToolInfo(\"LunarG\") },\n\t\t\t{ 2, new ToolInfo(\"Valve\") },\n\t\t\t{ 3, new ToolInfo(\"Codeplay\") },\n\t\t\t{ 4, new ToolInfo(\"NVIDIA\") },\n\t\t\t{ 5, new ToolInfo(\"ARM\") },\n\t\t\t{ 6, new ToolInfo(\"Khronos\", \"LLVM/SPIR-V Translator\") },\n\t\t\t{ 7, new ToolInfo(\"Khronos\", \"SPIR-V Tools Assembler\") },\n\t\t\t{ 8, new ToolInfo(\"Khronos\", \"Glslang Reference Front End\") },\n\t\t\t{ 9, new ToolInfo(\"Qualcomm\") },\n\t\t\t{ 10, new ToolInfo(\"AMD\") },\n\t\t\t{ 11, new ToolInfo(\"Intel\") },\n\t\t\t{ 12, new ToolInfo(\"Imagination\") },\n\t\t\t{ 13, new ToolInfo(\"Google\", \"Shaderc over Glslang\") },\n\t\t\t{ 14, new ToolInfo(\"Google\", \"spiregg\") },\n\t\t\t{ 15, new ToolInfo(\"Google\", \"rspirv\") },\n\t\t\t{ 16, new ToolInfo(\"X-LEGEND\", \"Mesa-IR/SPIR-V Translator\") },\n\t\t\t{ 17, new ToolInfo(\"Khronos\", \"SPIR-V Tools Linker\") },\n\t\t};\n\t}\n}"
  },
  {
    "path": "AssetStudioUtility/CSspv/Types.cs",
    "content": "using System.Collections.Generic;\nusing System.Text;\n\nnamespace SpirV\n{\n\tpublic class Type\n\t{\n\t\tpublic virtual StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn sb;\n\t\t}\n\t}\n\n\tpublic class VoidType : Type\n\t{\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn \"void\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn sb.Append(\"void\");\n\t\t}\n\t}\n\n\tpublic class ScalarType : Type\n\t{\n\t}\n\n\tpublic class BoolType : ScalarType\n\t{\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn \"bool\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn sb.Append(\"bool\");\n\t\t}\n\t}\n\n\tpublic class IntegerType : ScalarType\n\t{\n\t\tpublic IntegerType (int width, bool signed)\n\t\t{\n\t\t\tWidth = width;\n\t\t\tSigned = signed;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\tif (Signed)\n\t\t\t{\n\t\t\t\treturn $\"i{Width}\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $\"u{Width}\";\n\t\t\t}\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\tif (Signed)\n\t\t\t{\n\t\t\t\tsb.Append('i').Append(Width);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsb.Append('u').Append(Width);\n\t\t\t}\n\t\t\treturn sb;\n\t\t}\n\n\t\tpublic int Width { get; }\n\t\tpublic bool Signed { get; }\n\t}\n\n\tpublic class FloatingPointType : ScalarType\n\t{\n\t\tpublic FloatingPointType (int width)\n\t\t{\n\t\t\tWidth = width;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn $\"f{Width}\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn sb.Append('f').Append(Width);\n\t\t}\n\n\t\tpublic int Width { get; }\n\t}\n\n\tpublic class VectorType : Type\n\t{\n\t\tpublic VectorType (ScalarType scalarType, int componentCount)\n\t\t{\n\t\t\tComponentType = scalarType;\n\t\t\tComponentCount = componentCount;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn $\"{ComponentType}_{ComponentCount}\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn ComponentType.ToString(sb).Append('_').Append(ComponentCount);\n\t\t}\n\n\t\tpublic ScalarType ComponentType { get; }\n\t\tpublic int ComponentCount { get; }\n\t}\n\n\tpublic class MatrixType : Type\n\t{\n\t\tpublic MatrixType (VectorType vectorType, int columnCount)\n\t\t{\n\t\t\tColumnType = vectorType;\n\t\t\tColumnCount = columnCount;\n\t\t}\n\n\t\tpublic override string ToString ()\n\t\t{\n\t\t\treturn $\"{ColumnType}x{ColumnCount}\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn sb.Append(ColumnType).Append('x').Append(ColumnCount);\n\t\t}\n\n\t\tpublic VectorType ColumnType { get; }\n\t\tpublic int ColumnCount { get; }\n\t\tpublic int RowCount => ColumnType.ComponentCount;\n\t}\n\n\tpublic class ImageType : Type\n\t{\n\t\tpublic ImageType (Type sampledType, Dim dim, int depth, bool isArray, bool isMultisampled, int sampleCount,\n\t\t\tImageFormat imageFormat, AccessQualifier accessQualifier)\n\t\t{\n\t\t\tSampledType = sampledType;\n\t\t\tDim = dim;\n\t\t\tDepth = depth;\n\t\t\tIsArray = isArray;\n\t\t\tIsMultisampled = isMultisampled;\n\t\t\tSampleCount = sampleCount;\n\t\t\tFormat = imageFormat;\n\t\t\tAccessQualifier = accessQualifier;\n\t\t}\n\n\t\tpublic override string ToString ()\n\t\t{\n\t\t\tStringBuilder sb = new StringBuilder ();\n\t\t\tToString(sb);\n\t\t\treturn sb.ToString();\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\tswitch (AccessQualifier)\n\t\t\t{\n\t\t\t\tcase AccessQualifier.ReadWrite:\n\t\t\t\t\tsb.Append(\"read_write \");\n\t\t\t\t\tbreak;\n\t\t\t\tcase AccessQualifier.WriteOnly:\n\t\t\t\t\tsb.Append(\"write_only \");\n\t\t\t\t\tbreak;\n\t\t\t\tcase AccessQualifier.ReadOnly:\n\t\t\t\t\tsb.Append(\"read_only \");\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tsb.Append(\"Texture\");\n\t\t\tswitch (Dim)\n\t\t\t{\n\t\t\t\tcase Dim.Dim1D:\n\t\t\t\t\tsb.Append(\"1D\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase Dim.Dim2D:\n\t\t\t\t\tsb.Append(\"2D\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase Dim.Dim3D:\n\t\t\t\t\tsb.Append(\"3D\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase Dim.Cube:\n\t\t\t\t\tsb.Append(\"Cube\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (IsMultisampled)\n\t\t\t{\n\t\t\t\tsb.Append(\"MS\");\n\t\t\t}\n\t\t\tif (IsArray)\n\t\t\t{\n\t\t\t\tsb.Append(\"Array\");\n\t\t\t}\n\t\t\treturn sb;\n\t\t}\n\n\t\tpublic Type SampledType { get; }\n\t\tpublic Dim Dim { get; }\n\t\tpublic int Depth { get; }\n\t\tpublic bool IsArray { get; }\n\t\tpublic bool IsMultisampled { get; }\n\t\tpublic int SampleCount { get; }\n\t\tpublic ImageFormat Format { get; }\n\t\tpublic AccessQualifier AccessQualifier { get; }\n\t}\n\n\tpublic class SamplerType : Type\n\t{\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn \"sampler\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn sb.Append(\"sampler\");\n\t\t}\n\t}\n\n\tpublic class SampledImageType : Type\n\t{\n\t\tpublic SampledImageType (ImageType imageType)\n\t\t{\n\t\t\tImageType = imageType;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn $\"{ImageType}Sampled\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn ImageType.ToString(sb).Append(\"Sampled\");\n\t\t}\n\n\t\tpublic ImageType ImageType { get; }\n\t}\n\n\tpublic class ArrayType : Type\n\t{\n\t\tpublic ArrayType (Type elementType, int elementCount)\n\t\t{\n\t\t\tElementType = elementType;\n\t\t\tElementCount = elementCount;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\treturn $\"{ElementType}[{ElementCount}]\";\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\treturn ElementType.ToString(sb).Append('[').Append(ElementCount).Append(']');\n\t\t}\n\n\t\tpublic int ElementCount { get; }\n\t\tpublic Type ElementType { get; }\n\t}\n\n\tpublic class RuntimeArrayType : Type\n\t{\n\t\tpublic RuntimeArrayType(Type elementType)\n\t\t{\n\t\t\tElementType = elementType;\n\t\t}\n\n\t\tpublic Type ElementType { get; }\n\t}\n\n\tpublic class StructType : Type\n\t{\n\t\tpublic StructType(IReadOnlyList<Type> memberTypes)\n\t\t{\n\t\t\tMemberTypes = memberTypes;\n\t\t\tmemberNames_ = new List<string>();\n\n\t\t\tfor (int i = 0; i < memberTypes.Count; ++i)\n\t\t\t{\n\t\t\t\tmemberNames_.Add(string.Empty);\n\t\t\t}\n\t\t}\n\n\t\tpublic void SetMemberName(uint member, string name)\n\t\t{\n\t\t\tmemberNames_[(int)member] = name;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\tToString(sb);\n\t\t\treturn sb.ToString();\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\tsb.Append(\"struct {\");\n\t\t\tfor (int i = 0; i < MemberTypes.Count; ++i)\n\t\t\t{\n\t\t\t\tType memberType = MemberTypes[i];\n\t\t\t\tmemberType.ToString(sb);\n\t\t\t\tif (!string.IsNullOrEmpty(memberNames_[i]))\n\t\t\t\t{\n\t\t\t\t\tsb.Append(' ');\n\t\t\t\t\tsb.Append(MemberNames[i]);\n\t\t\t\t}\n\n\t\t\t\tsb.Append(';');\n\t\t\t\tif (i < (MemberTypes.Count - 1))\n\t\t\t\t{\n\t\t\t\t\tsb.Append(' ');\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb.Append('}');\n\t\t\treturn sb;\n\t\t}\n\n\t\tpublic IReadOnlyList<Type> MemberTypes { get; }\n\t\tpublic IReadOnlyList<string> MemberNames => memberNames_;\n\n\t\tprivate List<string> memberNames_;\n\t}\n\n\tpublic class OpaqueType : Type\n\t{\n\t}\n\n\tpublic class PointerType : Type\n\t{\n\t\tpublic PointerType(StorageClass storageClass, Type type)\n\t\t{\n\t\t\tStorageClass = storageClass;\n\t\t\tType = type;\n\t\t}\n\n\t\tpublic PointerType(StorageClass storageClass)\n\t\t{\n\t\t\tStorageClass = storageClass;\n\t\t}\n\n\t\tpublic void ResolveForwardReference(Type t)\n\t\t{\n\t\t\tType = t;\n\t\t}\n\n\t\tpublic override string ToString()\n\t\t{\n\t\t\tif (Type == null)\n\t\t\t{\n\t\t\t\treturn $\"{StorageClass} *\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $\"{StorageClass} {Type}*\";\n\t\t\t}\n\t\t}\n\n\t\tpublic override StringBuilder ToString(StringBuilder sb)\n\t\t{\n\t\t\tsb.Append(StorageClass.ToString()).Append(' ');\n\t\t\tif (Type != null)\n\t\t\t{\n\t\t\t\tType.ToString(sb);\n\t\t\t}\n\t\t\tsb.Append('*');\n\t\t\treturn sb;\n\t\t}\n\n\t\tpublic StorageClass StorageClass { get; }\n\t\tpublic Type Type { get; private set; }\n\t}\n\n\tpublic class FunctionType : Type\n\t{\n\t\tpublic FunctionType(Type returnType, IReadOnlyList<Type> parameterTypes)\n\t\t{\n\t\t\tReturnType = returnType;\n\t\t\tParameterTypes = parameterTypes;\n\t\t}\n\n\t\tpublic Type ReturnType { get; }\n\t\tpublic IReadOnlyList<Type> ParameterTypes { get; }\n\t}\n\n\tpublic class EventType : Type\n\t{\n\t}\n\n\tpublic class DeviceEventType : Type\n\t{\n\t}\n\n\tpublic class ReserveIdType : Type\n\t{\n\t}\n\n\tpublic class QueueType : Type\n\t{\n\t}\n\n\tpublic class PipeType : Type\n\t{\n\t}\n\n\tpublic class PipeStorage : Type\n\t{\n\t}\n\n\tpublic class NamedBarrier : Type\n\t{\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/FMOD Studio API/fmod.cs",
    "content": "/* ========================================================================================== */\n/*                                                                                            */\n/* FMOD Studio - C# Wrapper . Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016.      */\n/*                                                                                            */\n/* ========================================================================================== */\n\nusing System;\nusing System.Text;\nusing System.Runtime.InteropServices;\nusing AssetStudio.PInvoke;\n\nnamespace FMOD\n{\n    /*\n        FMOD version number.  Check this against FMOD::System::getVersion / System_GetVersion\n        0xaaaabbcc -> aaaa = major version number.  bb = minor version number.  cc = development version number.\n    */\n    public class VERSION\n    {\n        public const int    number = 0x00010716;\n#if WIN64\n        public const string dll    = \"fmod64\";\n#else\n        public const string dll    = \"fmod\";\n#endif\n    }\n\n    public class CONSTANTS\n    {\n        public const int MAX_CHANNEL_WIDTH = 32;\n        public const int MAX_LISTENERS = 8;\n    }\n\n    /*\n        FMOD types\n    */\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        error codes.  Returned from every function.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n    ]\n    */\n    public enum RESULT : int\n    {\n        OK,                        /* No errors. */\n        ERR_BADCOMMAND,            /* Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound). */\n        ERR_CHANNEL_ALLOC,         /* Error trying to allocate a channel. */\n        ERR_CHANNEL_STOLEN,        /* The specified channel has been reused to play another sound. */\n        ERR_DMA,                   /* DMA Failure.  See debug output for more information. */\n        ERR_DSP_CONNECTION,        /* DSP connection error.  Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts. */\n        ERR_DSP_DONTPROCESS,       /* DSP return code from a DSP process query callback.  Tells mixer not to call the process callback and therefore not consume CPU.  Use this to optimize the DSP graph. */\n        ERR_DSP_FORMAT,            /* DSP Format error.  A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map. */\n        ERR_DSP_INUSE,             /* DSP is already in the mixer's DSP network. It must be removed before being reinserted or released. */\n        ERR_DSP_NOTFOUND,          /* DSP connection error.  Couldn't find the DSP unit specified. */\n        ERR_DSP_RESERVED,          /* DSP operation error.  Cannot perform operation on this DSP as it is reserved by the system. */\n        ERR_DSP_SILENCE,           /* DSP return code from a DSP process query callback.  Tells mixer silence would be produced from read, so go idle and not consume CPU.  Use this to optimize the DSP graph. */\n        ERR_DSP_TYPE,              /* DSP operation cannot be performed on a DSP of this type. */\n        ERR_FILE_BAD,              /* Error loading file. */\n        ERR_FILE_COULDNOTSEEK,     /* Couldn't perform seek operation.  This is a limitation of the medium (ie netstreams) or the file format. */\n        ERR_FILE_DISKEJECTED,      /* Media was ejected while reading. */\n        ERR_FILE_EOF,              /* End of file unexpectedly reached while trying to read essential data (truncated?). */\n        ERR_FILE_ENDOFDATA,        /* End of current chunk reached while trying to read data. */\n        ERR_FILE_NOTFOUND,         /* File not found. */\n        ERR_FORMAT,                /* Unsupported file or audio format. */\n        ERR_HEADER_MISMATCH,       /* There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library. */\n        ERR_HTTP,                  /* A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere. */\n        ERR_HTTP_ACCESS,           /* The specified resource requires authentication or is forbidden. */\n        ERR_HTTP_PROXY_AUTH,       /* Proxy authentication is required to access the specified resource. */\n        ERR_HTTP_SERVER_ERROR,     /* A HTTP server error occurred. */\n        ERR_HTTP_TIMEOUT,          /* The HTTP request timed out. */\n        ERR_INITIALIZATION,        /* FMOD was not initialized correctly to support this function. */\n        ERR_INITIALIZED,           /* Cannot call this command after System::init. */\n        ERR_INTERNAL,              /* An error occurred that wasn't supposed to.  Contact support. */\n        ERR_INVALID_FLOAT,         /* Value passed in was a NaN, Inf or denormalized float. */\n        ERR_INVALID_HANDLE,        /* An invalid object handle was used. */\n        ERR_INVALID_PARAM,         /* An invalid parameter was passed to this function. */\n        ERR_INVALID_POSITION,      /* An invalid seek position was passed to this function. */\n        ERR_INVALID_SPEAKER,       /* An invalid speaker was passed to this function based on the current speaker mode. */\n        ERR_INVALID_SYNCPOINT,     /* The syncpoint did not come from this sound handle. */\n        ERR_INVALID_THREAD,        /* Tried to call a function on a thread that is not supported. */\n        ERR_INVALID_VECTOR,        /* The vectors passed in are not unit length, or perpendicular. */\n        ERR_MAXAUDIBLE,            /* Reached maximum audible playback count for this sound's soundgroup. */\n        ERR_MEMORY,                /* Not enough memory or resources. */\n        ERR_MEMORY_CANTPOINT,      /* Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used. */\n        ERR_NEEDS3D,               /* Tried to call a command on a 2d sound when the command was meant for 3d sound. */\n        ERR_NEEDSHARDWARE,         /* Tried to use a feature that requires hardware support. */\n        ERR_NET_CONNECT,           /* Couldn't connect to the specified host. */\n        ERR_NET_SOCKET_ERROR,      /* A socket error occurred.  This is a catch-all for socket-related errors not listed elsewhere. */\n        ERR_NET_URL,               /* The specified URL couldn't be resolved. */\n        ERR_NET_WOULD_BLOCK,       /* Operation on a non-blocking socket could not complete immediately. */\n        ERR_NOTREADY,              /* Operation could not be performed because specified sound/DSP connection is not ready. */\n        ERR_OUTPUT_ALLOCATED,      /* Error initializing output device, but more specifically, the output device is already in use and cannot be reused. */\n        ERR_OUTPUT_CREATEBUFFER,   /* Error creating hardware sound buffer. */\n        ERR_OUTPUT_DRIVERCALL,     /* A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted. */\n        ERR_OUTPUT_FORMAT,         /* Soundcard does not support the specified format. */\n        ERR_OUTPUT_INIT,           /* Error initializing output device. */\n        ERR_OUTPUT_NODRIVERS,      /* The output device has no drivers installed.  If pre-init, FMOD_OUTPUT_NOSOUND is selected as the output mode.  If post-init, the function just fails. */\n        ERR_PLUGIN,                /* An unspecified error has been returned from a plugin. */\n        ERR_PLUGIN_MISSING,        /* A requested output, dsp unit type or codec was not available. */\n        ERR_PLUGIN_RESOURCE,       /* A resource that the plugin requires cannot be found. (ie the DLS file for MIDI playback) */\n        ERR_PLUGIN_VERSION,        /* A plugin was built with an unsupported SDK version. */\n        ERR_RECORD,                /* An error occurred trying to initialize the recording device. */\n        ERR_REVERB_CHANNELGROUP,   /* Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection. */\n        ERR_REVERB_INSTANCE,       /* Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist. */\n        ERR_SUBSOUNDS,             /* The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have.  The operation may also not be able to be performed on a parent sound. */\n        ERR_SUBSOUND_ALLOCATED,    /* This subsound is already being used by another sound, you cannot have more than one parent to a sound.  Null out the other parent's entry first. */\n        ERR_SUBSOUND_CANTMOVE,     /* Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file. */\n        ERR_TAGNOTFOUND,           /* The specified tag could not be found or there are no tags. */\n        ERR_TOOMANYCHANNELS,       /* The sound created exceeds the allowable input channel count.  This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat. */\n        ERR_TRUNCATED,             /* The retrieved string is too long to fit in the supplied buffer and has been truncated. */\n        ERR_UNIMPLEMENTED,         /* Something in FMOD hasn't been implemented when it should be! contact support! */\n        ERR_UNINITIALIZED,         /* This command failed because System::init or System::setDriver was not called. */\n        ERR_UNSUPPORTED,           /* A command issued was not supported by this object.  Possibly a plugin without certain callbacks specified. */\n        ERR_VERSION,               /* The version number of this file format is not supported. */\n        ERR_EVENT_ALREADY_LOADED,  /* The specified bank has already been loaded. */\n        ERR_EVENT_LIVEUPDATE_BUSY, /* The live update connection failed due to the game already being connected. */\n        ERR_EVENT_LIVEUPDATE_MISMATCH, /* The live update connection failed due to the game data being out of sync with the tool. */\n        ERR_EVENT_LIVEUPDATE_TIMEOUT, /* The live update connection timed out. */\n        ERR_EVENT_NOTFOUND,        /* The requested event, bus or vca could not be found. */\n        ERR_STUDIO_UNINITIALIZED,  /* The Studio::System object is not yet initialized. */\n        ERR_STUDIO_NOT_LOADED,     /* The specified resource is not loaded, so it can't be unloaded. */\n        ERR_INVALID_STRING,        /* An invalid string was passed to this function. */\n        ERR_ALREADY_LOCKED,        /* The specified resource is already locked. */\n        ERR_NOT_LOCKED,            /* The specified resource is not locked, so it can't be unlocked. */\n        ERR_RECORD_DISCONNECTED,   /* The specified recording driver has been disconnected. */\n        ERR_TOOMANYSAMPLES,        /* The length provided exceed the allowable limit. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Used to distinguish if a FMOD_CHANNELCONTROL parameter is actually a channel or a channelgroup.\n\n        [REMARKS]\n        Cast the FMOD_CHANNELCONTROL to an FMOD_CHANNEL/FMOD::Channel, or FMOD_CHANNELGROUP/FMOD::ChannelGroup if specific functionality is needed for either class.\n        Otherwise use as FMOD_CHANNELCONTROL/FMOD::ChannelControl and use that API.\n\n        [SEE_ALSO]\n        Channel::setCallback\n        ChannelGroup::setCallback\n    ]\n    */\n    public enum CHANNELCONTROL_TYPE : int\n    {\n        CHANNEL,\n        CHANNELGROUP\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure describing a point in 3D space.\n\n        [REMARKS]\n        FMOD uses a left handed co-ordinate system by default.\n        To use a right handed co-ordinate system specify FMOD_INIT_3D_RIGHTHANDED from FMOD_INITFLAGS in System::init.\n\n        [SEE_ALSO]\n        System::set3DListenerAttributes\n        System::get3DListenerAttributes\n        Channel::set3DAttributes\n        Channel::get3DAttributes\n        Geometry::addPolygon\n        Geometry::setPolygonVertex\n        Geometry::getPolygonVertex\n        Geometry::setRotation\n        Geometry::getRotation\n        Geometry::setPosition\n        Geometry::getPosition\n        Geometry::setScale\n        Geometry::getScale\n        FMOD_INITFLAGS\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct VECTOR\n    {\n        public float x;        /* X co-ordinate in 3D space. */\n        public float y;        /* Y co-ordinate in 3D space. */\n        public float z;        /* Z co-ordinate in 3D space. */\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure describing a position, velocity and orientation.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_VECTOR\n        FMOD_DSP_PARAMETER_3DATTRIBUTES\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct _3D_ATTRIBUTES\n    {\n        VECTOR position;\n        VECTOR velocity;\n        VECTOR forward;\n        VECTOR up;\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure that is passed into FMOD_FILE_ASYNCREAD_CALLBACK.  Use the information in this structure to perform\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.<br>\n        Members marked with [w] mean the variable can be written to.  The user can set the value.<br>\n        <br>\n        Instructions: write to 'buffer', and 'bytesread' <b>BEFORE</b> setting 'result'.<br>\n        As soon as result is set, FMOD will asynchronously continue internally using the data provided in this structure.<br>\n        <br>\n        Set 'result' to the result expected from a normal file read callback.<br>\n        If the read was successful, set it to FMOD_OK.<br>\n        If it read some data but hit the end of the file, set it to FMOD_ERR_FILE_EOF.<br>\n        If a bad error occurred, return FMOD_ERR_FILE_BAD<br>\n        If a disk was ejected, return FMOD_ERR_FILE_DISKEJECTED.<br>\n\n        [SEE_ALSO]\n        FMOD_FILE_ASYNCREAD_CALLBACK\n        FMOD_FILE_ASYNCCANCEL_CALLBACK\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ASYNCREADINFO\n    {\n        public IntPtr   handle;                     /* [r] The file handle that was filled out in the open callback. */\n        public uint     offset;                     /* [r] Seek position, make sure you read from this file offset. */\n        public uint     sizebytes;                  /* [r] how many bytes requested for read. */\n        public int      priority;                   /* [r] 0 = low importance.  100 = extremely important (ie 'must read now or stuttering may occur') */\n\n        public IntPtr   userdata;                   /* [r] User data pointer. */\n        public IntPtr   buffer;                     /* [w] Buffer to read file data into. */\n        public uint     bytesread;                  /* [w] Fill this in before setting result code to tell FMOD how many bytes were read. */\n        public ASYNCREADINFO_DONE_CALLBACK   done;  /* [r] FMOD file system wake up function.  Call this when user file read is finished.  Pass result of file read as a parameter. */\n\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These output types are used with System::setOutput / System::getOutput, to choose which output method to use.\n\n        [REMARKS]\n        To pass information to the driver when initializing fmod use the *extradriverdata* parameter in System::init for the following reasons.\n\n        - FMOD_OUTPUTTYPE_WAVWRITER     - extradriverdata is a pointer to a char * file name that the wav writer will output to.\n        - FMOD_OUTPUTTYPE_WAVWRITER_NRT - extradriverdata is a pointer to a char * file name that the wav writer will output to.\n        - FMOD_OUTPUTTYPE_DSOUND        - extradriverdata is cast to a HWND type, so that FMOD can set the focus on the audio for a particular window.\n        - FMOD_OUTPUTTYPE_PS3           - extradriverdata is a pointer to a FMOD_PS3_EXTRADRIVERDATA struct. This can be found in fmodps3.h.\n        - FMOD_OUTPUTTYPE_XBOX360       - extradriverdata is a pointer to a FMOD_360_EXTRADRIVERDATA struct. This can be found in fmodxbox360.h.\n\n        Currently these are the only FMOD drivers that take extra information.  Other unknown plugins may have different requirements.\n    \n        Note! If FMOD_OUTPUTTYPE_WAVWRITER_NRT or FMOD_OUTPUTTYPE_NOSOUND_NRT are used, and if the System::update function is being called\n        very quickly (ie for a non realtime decode) it may be being called too quickly for the FMOD streamer thread to respond to.\n        The result will be a skipping/stuttering output in the captured audio.\n    \n        To remedy this, disable the FMOD streamer thread, and use FMOD_INIT_STREAM_FROM_UPDATE to avoid skipping in the output stream,\n        as it will lock the mixer and the streamer together in the same thread.\n    \n        [SEE_ALSO]\n            System::setOutput\n            System::getOutput\n            System::setSoftwareFormat\n            System::getSoftwareFormat\n            System::init\n            System::update\n            FMOD_INITFLAGS\n    ]\n    */\n    public enum OUTPUTTYPE : int\n    {\n        AUTODETECT,      /* Picks the best output mode for the platform. This is the default. */\n\n        UNKNOWN,         /* All - 3rd party plugin, unknown. This is for use with System::getOutput only. */\n        NOSOUND,         /* All - Perform all mixing but discard the final output. */\n        WAVWRITER,       /* All - Writes output to a .wav file. */\n        NOSOUND_NRT,     /* All - Non-realtime version of FMOD_OUTPUTTYPE_NOSOUND. User can drive mixer with System::update at whatever rate they want. */\n        WAVWRITER_NRT,   /* All - Non-realtime version of FMOD_OUTPUTTYPE_WAVWRITER. User can drive mixer with System::update at whatever rate they want. */\n\n        DSOUND,          /* Win                  - Direct Sound.                        (Default on Windows XP and below) */\n        WINMM,           /* Win                  - Windows Multimedia. */\n        WASAPI,          /* Win/WinStore/XboxOne - Windows Audio Session API.           (Default on Windows Vista and above, Xbox One and Windows Store Applications) */\n        ASIO,            /* Win                  - Low latency ASIO 2.0. */\n        PULSEAUDIO,      /* Linux                - Pulse Audio.                         (Default on Linux if available) */\n        ALSA,            /* Linux                - Advanced Linux Sound Architecture.   (Default on Linux if PulseAudio isn't available) */\n        COREAUDIO,       /* Mac/iOS              - Core Audio.                          (Default on Mac and iOS) */\n        XBOX360,         /* Xbox 360             - XAudio.                              (Default on Xbox 360) */\n        PS3,             /* PS3                  - Audio Out.                           (Default on PS3) */\n        AUDIOTRACK,      /* Android              - Java Audio Track.                    (Default on Android 2.2 and below) */\n        OPENSL,          /* Android              - OpenSL ES.                           (Default on Android 2.3 and above) */\n        WIIU,            /* Wii U                - AX.                                  (Default on Wii U) */\n        AUDIOOUT,        /* PS4/PSVita           - Audio Out.                           (Default on PS4 and PS Vita) */\n\n        MAX,             /* Maximum number of output types supported. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Specify the destination of log output when using the logging version of FMOD.\n\n        [REMARKS]\n        TTY destination can vary depending on platform, common examples include the\n        Visual Studio / Xcode output window, stderr and LogCat.\n\n        [SEE_ALSO]\n        FMOD_Debug_Initialize\n    ]\n    */\n    public enum DEBUG_MODE : int\n    {\n        TTY,        /* Default log location per platform, i.e. Visual Studio output window, stderr, LogCat, etc */\n        FILE,       /* Write log to specified file path */\n        CALLBACK,   /* Call specified callback with log information */\n    }\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_DEBUG_FLAGS\n\n        [DESCRIPTION]\n        Specify the requested information to be output when using the logging version of FMOD.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_Debug_Initialize\n    ]\n    */\n    [Flags]\n    public enum DEBUG_FLAGS : uint\n    {\n        NONE                    = 0x00000000,   /* Disable all messages */\n        ERROR                   = 0x00000001,   /* Enable only error messages. */\n        WARNING                 = 0x00000002,   /* Enable warning and error messages. */\n        LOG                     = 0x00000004,   /* Enable informational, warning and error messages (default). */\n\n        TYPE_MEMORY             = 0x00000100,   /* Verbose logging for memory operations, only use this if you are debugging a memory related issue. */\n        TYPE_FILE               = 0x00000200,   /* Verbose logging for file access, only use this if you are debugging a file related issue. */\n        TYPE_CODEC              = 0x00000400,   /* Verbose logging for codec initialization, only use this if you are debugging a codec related issue. */\n        TYPE_TRACE              = 0x00000800,   /* Verbose logging for internal errors, use this for tracking the origin of error codes. */\n\n        DISPLAY_TIMESTAMPS      = 0x00010000,   /* Display the time stamp of the log message in milliseconds. */\n        DISPLAY_LINENUMBERS     = 0x00020000,   /* Display the source code file and line number for where the message originated. */\n        DISPLAY_THREAD          = 0x00040000,   /* Display the thread ID of the calling function that generated the message. */\n    }\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_MEMORY_TYPE\n\n        [DESCRIPTION]\n        Bit fields for memory allocation type being passed into FMOD memory callbacks.\n\n        [REMARKS]\n        Remember this is a bitfield.  You may get more than 1 bit set (ie physical + persistent) so do not simply switch on the types!  You must check each bit individually or clear out the bits that you do not want within the callback.<br>\n        Bits can be excluded if you want during Memory_Initialize so that you never get them.\n\n        [SEE_ALSO]\n        FMOD_MEMORY_ALLOC_CALLBACK\n        FMOD_MEMORY_REALLOC_CALLBACK\n        FMOD_MEMORY_FREE_CALLBACK\n        Memory_Initialize\n    ]\n    */\n    [Flags]\n    public enum MEMORY_TYPE : uint\n    {\n        NORMAL             = 0x00000000,       /* Standard memory. */\n        STREAM_FILE        = 0x00000001,       /* Stream file buffer, size controllable with System::setStreamBufferSize. */\n        STREAM_DECODE      = 0x00000002,       /* Stream decode buffer, size controllable with FMOD_CREATESOUNDEXINFO::decodebuffersize. */\n        SAMPLEDATA         = 0x00000004,       /* Sample data buffer.  Raw audio data, usually PCM/MPEG/ADPCM/XMA data. */\n        DSP_BUFFER         = 0x00000008,       /* DSP memory block allocated when more than 1 output exists on a DSP node. */\n        PLUGIN             = 0x00000010,       /* Memory allocated by a third party plugin. */\n        XBOX360_PHYSICAL   = 0x00100000,       /* Requires XPhysicalAlloc / XPhysicalFree. */\n        PERSISTENT         = 0x00200000,       /* Persistent memory. Memory will be freed when System::release is called. */\n        SECONDARY          = 0x00400000,       /* Secondary memory. Allocation should be in secondary memory. For example RSX on the PS3. */\n        ALL                = 0xFFFFFFFF\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These are speaker types defined for use with the System::setSoftwareFormat command.\n\n        [REMARKS]\n        Note below the phrase 'sound channels' is used.  These are the subchannels inside a sound, they are not related and\n        have nothing to do with the FMOD class \"Channel\".<br>\n        For example a mono sound has 1 sound channel, a stereo sound has 2 sound channels, and an AC3 or 6 channel wav file have 6 \"sound channels\".<br>\n        <br>\n        FMOD_SPEAKERMODE_RAW<br>\n        ---------------------<br>\n        This mode is for output devices that are not specifically mono/stereo/quad/surround/5.1 or 7.1, but are multichannel.<br>\n        Use System::setSoftwareFormat to specify the number of speakers you want to address, otherwise it will default to 2 (stereo).<br>\n        Sound channels map to speakers sequentially, so a mono sound maps to output speaker 0, stereo sound maps to output speaker 0 & 1.<br>\n        The user assumes knowledge of the speaker order.  FMOD_SPEAKER enumerations may not apply, so raw channel indices should be used.<br>\n        Multichannel sounds map input channels to output channels 1:1. <br>\n        Channel::setPan and Channel::setPanLevels do not work.<br>\n        Speaker levels must be manually set with Channel::setPanMatrix.<br>\n        <br>\n        FMOD_SPEAKERMODE_MONO<br>\n        ---------------------<br>\n        This mode is for a 1 speaker arrangement.<br>\n        Panning does not work in this speaker mode.<br>\n        Mono, stereo and multichannel sounds have each sound channel played on the one speaker unity.<br>\n        Mix behavior for multichannel sounds can be set with Channel::setPanMatrix.<br>\n        Channel::setPanLevels does not work.<br>\n        <br>\n        FMOD_SPEAKERMODE_STEREO<br>\n        -----------------------<br>\n        This mode is for 2 speaker arrangements that have a left and right speaker.<br>\n        <li>Mono sounds default to an even distribution between left and right.  They can be panned with Channel::setPan.<br>\n        <li>Stereo sounds default to the middle, or full left in the left speaker and full right in the right speaker.\n        <li>They can be cross faded with Channel::setPan.<br>\n        <li>Multichannel sounds have each sound channel played on each speaker at unity.<br>\n        <li>Mix behavior for multichannel sounds can be set with Channel::setPanMatrix.<br>\n        <li>Channel::setPanLevels works but only front left and right parameters are used, the rest are ignored.<br>\n        <br>\n        FMOD_SPEAKERMODE_QUAD<br>\n        ------------------------<br>\n        This mode is for 4 speaker arrangements that have a front left, front right, surround left and a surround right speaker.<br>\n        <li>Mono sounds default to an even distribution between front left and front right.  They can be panned with Channel::setPan.<br>\n        <li>Stereo sounds default to the left sound channel played on the front left, and the right sound channel played on the front right.<br>\n        <li>They can be cross faded with Channel::setPan.<br>\n        <li>Multichannel sounds default to all of their sound channels being played on each speaker in order of input.<br>\n        <li>Mix behavior for multichannel sounds can be set with Channel::setPanMatrix.<br>\n        <li>Channel::setPanLevels works but rear left, rear right, center and lfe are ignored.<br>\n        <br>\n        FMOD_SPEAKERMODE_SURROUND<br>\n        ------------------------<br>\n        This mode is for 5 speaker arrangements that have a left/right/center/surround left/surround right.<br>\n        <li>Mono sounds default to the center speaker.  They can be panned with Channel::setPan.<br>\n        <li>Stereo sounds default to the left sound channel played on the front left, and the right sound channel played on the front right.\n        <li>They can be cross faded with Channel::setPan.<br>\n        <li>Multichannel sounds default to all of their sound channels being played on each speaker in order of input.\n        <li>Mix behavior for multichannel sounds can be set with Channel::setPanMatrix.<br>\n        <li>Channel::setPanLevels works but rear left / rear right are ignored.<br>\n        <br>\n        FMOD_SPEAKERMODE_5POINT1<br>\n        ---------------------------------------------------------<br>\n        This mode is for 5.1 speaker arrangements that have a left/right/center/surround left/surround right and a subwoofer speaker.<br>\n        <li>Mono sounds default to the center speaker.  They can be panned with Channel::setPan.<br>\n        <li>Stereo sounds default to the left sound channel played on the front left, and the right sound channel played on the front right.\n        <li>They can be cross faded with Channel::setPan.<br>\n        <li>Multichannel sounds default to all of their sound channels being played on each speaker in order of input.\n        <li>Mix behavior for multichannel sounds can be set with Channel::setPanMatrix.<br>\n        <li>Channel::setPanLevels works but rear left / rear right are ignored.<br>\n        <br>\n        FMOD_SPEAKERMODE_7POINT1<br>\n        ------------------------<br>\n        This mode is for 7.1 speaker arrangements that have a left/right/center/surround left/surround right/rear left/rear right\n        and a subwoofer speaker.<br>\n        <li>Mono sounds default to the center speaker.  They can be panned with Channel::setPan.<br>\n        <li>Stereo sounds default to the left sound channel played on the front left, and the right sound channel played on the front right.\n        <li>They can be cross faded with Channel::setPan.<br>\n        <li>Multichannel sounds default to all of their sound channels being played on each speaker in order of input.\n        <li>Mix behavior for multichannel sounds can be set with Channel::setPanMatrix.<br>\n        <li>Channel::setPanLevels works and every parameter is used to set the balance of a sound in any speaker.<br>\n        <br>\n\n        [SEE_ALSO]\n        System::setSoftwareFormat\n        System::getSoftwareFormat\n        DSP::setChannelFormat\n    ]\n    */\n    public enum SPEAKERMODE : int\n    {\n        DEFAULT,          /* Default speaker mode based on operating system/output mode.  Windows = control panel setting, Xbox = 5.1, PS3 = 7.1 etc. */\n        RAW,              /* There is no specific speakermode.  Sound channels are mapped in order of input to output.  Use System::setSoftwareFormat to specify speaker count. See remarks for more information. */\n        MONO,             /* The speakers are monaural. */\n        STEREO,           /* The speakers are stereo. */\n        QUAD,             /* 4 speaker setup.  This includes front left, front right, surround left, surround right.  */\n        SURROUND,         /* 5 speaker setup.  This includes front left, front right, center, surround left, surround right. */\n        _5POINT1,         /* 5.1 speaker setup.  This includes front left, front right, center, surround left, surround right and an LFE speaker. */\n        _7POINT1,         /* 7.1 speaker setup.  This includes front left, front right, center, surround left, surround right, back left, back right and an LFE speaker. */\n\n        MAX,              /* Maximum number of speaker modes supported. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Assigns an enumeration for a speaker index.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        System::setSpeakerPosition\n        System::getSpeakerPosition\n    ]\n    */\n    public enum SPEAKER : int\n    {\n        FRONT_LEFT,\n        FRONT_RIGHT,\n        FRONT_CENTER,\n        LOW_FREQUENCY,\n        SURROUND_LEFT,\n        SURROUND_RIGHT,\n        BACK_LEFT,\n        BACK_RIGHT,\n\n        MAX,               /* Maximum number of speaker types supported. */\n    }\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_CHANNELMASK\n\n        [DESCRIPTION]\n        These are bitfields to describe for a certain number of channels in a signal, which channels are being represented.<br>\n        For example, a signal could be 1 channel, but contain the LFE channel only.<br>\n\n        [REMARKS]\n        FMOD_CHANNELMASK_BACK_CENTER is not represented as an output speaker in fmod - but it is encountered in input formats and is down or upmixed appropriately to the nearest speakers.<br>\n\n        [SEE_ALSO]\n        DSP::setChannelFormat\n        DSP::getChannelFormat\n        FMOD_SPEAKERMODE\n    ]\n    */\n    [Flags]\n    public enum CHANNELMASK : uint\n    {\n        FRONT_LEFT             = 0x00000001,\n        FRONT_RIGHT            = 0x00000002,\n        FRONT_CENTER           = 0x00000004,\n        LOW_FREQUENCY          = 0x00000008,\n        SURROUND_LEFT          = 0x00000010,\n        SURROUND_RIGHT         = 0x00000020,\n        BACK_LEFT              = 0x00000040,\n        BACK_RIGHT             = 0x00000080,\n        BACK_CENTER            = 0x00000100,\n\n        MONO                   = (FRONT_LEFT),\n        STEREO                 = (FRONT_LEFT | FRONT_RIGHT),\n        LRC                    = (FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER),\n        QUAD                   = (FRONT_LEFT | FRONT_RIGHT | SURROUND_LEFT | SURROUND_RIGHT),\n        SURROUND               = (FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | SURROUND_LEFT | SURROUND_RIGHT),\n        _5POINT1               = (FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | SURROUND_LEFT | SURROUND_RIGHT),\n        _5POINT1_REARS         = (FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | BACK_LEFT | BACK_RIGHT),\n        _7POINT0               = (FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | SURROUND_LEFT | SURROUND_RIGHT | BACK_LEFT | BACK_RIGHT),\n        _7POINT1               = (FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | SURROUND_LEFT | SURROUND_RIGHT | BACK_LEFT | BACK_RIGHT)\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        When creating a multichannel sound, FMOD will pan them to their default speaker locations, for example a 6 channel sound will default to one channel per 5.1 output speaker.<br>\n        Another example is a stereo sound.  It will default to left = front left, right = front right.<br>\n        <br>\n        This is for sounds that are not 'default'.  For example you might have a sound that is 6 channels but actually made up of 3 stereo pairs, that should all be located in front left, front right only.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_CREATESOUNDEXINFO\n    ]\n    */\n    public enum CHANNELORDER : int\n    {\n        DEFAULT,              /* Left, Right, Center, LFE, Surround Left, Surround Right, Back Left, Back Right (see FMOD_SPEAKER enumeration)   */\n        WAVEFORMAT,           /* Left, Right, Center, LFE, Back Left, Back Right, Surround Left, Surround Right (as per Microsoft .wav WAVEFORMAT structure master order) */\n        PROTOOLS,             /* Left, Center, Right, Surround Left, Surround Right, LFE */\n        ALLMONO,              /* Mono, Mono, Mono, Mono, Mono, Mono, ... (each channel all the way up to 32 channels are treated as if they were mono) */\n        ALLSTEREO,            /* Left, Right, Left, Right, Left, Right, ... (each pair of channels is treated as stereo all the way up to 32 channels) */\n        ALSA,                 /* Left, Right, Surround Left, Surround Right, Center, LFE (as per Linux ALSA channel order) */\n\n        MAX,                  /* Maximum number of channel orderings supported. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These are plugin types defined for use with the System::getNumPlugins,\n        System::getPluginInfo and System::unloadPlugin functions.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        System::getNumPlugins\n        System::getPluginInfo\n        System::unloadPlugin\n    ]\n    */\n    public enum PLUGINTYPE : int\n    {\n        OUTPUT,          /* The plugin type is an output module.  FMOD mixed audio will play through one of these devices */\n        CODEC,           /* The plugin type is a file format codec.  FMOD will use these codecs to load file formats for playback. */\n        DSP,             /* The plugin type is a DSP unit.  FMOD will use these plugins as part of its DSP network to apply effects to output or generate sound in realtime. */\n\n        MAX,             /* Maximum number of plugin types supported. */\n    }\n\n\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_INITFLAGS\n\n        [DESCRIPTION]\n        Initialization flags.  Use them with System::init in the *flags* parameter to change various behavior.\n\n        [REMARKS]\n        Use System::setAdvancedSettings to adjust settings for some of the features that are enabled by these flags.\n\n        [SEE_ALSO]\n        System::init\n        System::update\n        System::setAdvancedSettings\n        Channel::set3DOcclusion\n    ]\n    */\n    [Flags]\n    public enum INITFLAGS : uint\n    {\n        NORMAL                    = 0x00000000, /* Initialize normally */\n        STREAM_FROM_UPDATE        = 0x00000001, /* No stream thread is created internally.  Streams are driven from System::update.  Mainly used with non-realtime outputs. */\n        MIX_FROM_UPDATE           = 0x00000002, /* Win/Wii/PS3/Xbox/Xbox 360 Only - FMOD Mixer thread is woken up to do a mix when System::update is called rather than waking periodically on its own timer. */\n        _3D_RIGHTHANDED           = 0x00000004, /* FMOD will treat +X as right, +Y as up and +Z as backwards (towards you). */\n        CHANNEL_LOWPASS           = 0x00000100, /* All FMOD_3D based voices will add a software lowpass filter effect into the DSP chain which is automatically used when Channel::set3DOcclusion is used or the geometry API.   This also causes sounds to sound duller when the sound goes behind the listener, as a fake HRTF style effect.  Use System::setAdvancedSettings to disable or adjust cutoff frequency for this feature. */\n        CHANNEL_DISTANCEFILTER    = 0x00000200, /* All FMOD_3D based voices will add a software lowpass and highpass filter effect into the DSP chain which will act as a distance-automated bandpass filter. Use System::setAdvancedSettings to adjust the center frequency. */\n        PROFILE_ENABLE            = 0x00010000, /* Enable TCP/IP based host which allows FMOD Designer or FMOD Profiler to connect to it, and view memory, CPU and the DSP network graph in real-time. */\n        VOL0_BECOMES_VIRTUAL      = 0x00020000, /* Any sounds that are 0 volume will go virtual and not be processed except for having their positions updated virtually.  Use System::setAdvancedSettings to adjust what volume besides zero to switch to virtual at. */\n        GEOMETRY_USECLOSEST       = 0x00040000, /* With the geometry engine, only process the closest polygon rather than accumulating all polygons the sound to listener line intersects. */\n        PREFER_DOLBY_DOWNMIX      = 0x00080000, /* When using FMOD_SPEAKERMODE_5POINT1 with a stereo output device, use the Dolby Pro Logic II downmix algorithm instead of the SRS Circle Surround algorithm. */\n        THREAD_UNSAFE             = 0x00100000, /* Disables thread safety for API calls. Only use this if FMOD low level is being called from a single thread, and if Studio API is not being used! */\n        PROFILE_METER_ALL         = 0x00200000  /* Slower, but adds level metering for every single DSP unit in the graph.  Use DSP::setMeteringEnabled to turn meters off individually. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These definitions describe the type of song being played.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        Sound::getFormat\n    ]\n    */\n    public enum SOUND_TYPE\n    {\n        UNKNOWN,         /* 3rd party / unknown plugin format. */\n        AIFF,            /* AIFF. */\n        ASF,             /* Microsoft Advanced Systems Format (ie WMA/ASF/WMV). */\n        DLS,             /* Sound font / downloadable sound bank. */\n        FLAC,            /* FLAC lossless codec. */\n        FSB,             /* FMOD Sample Bank. */\n        IT,              /* Impulse Tracker. */\n        MIDI,            /* MIDI. extracodecdata is a pointer to an FMOD_MIDI_EXTRACODECDATA structure. */\n        MOD,             /* Protracker / Fasttracker MOD. */\n        MPEG,            /* MP2/MP3 MPEG. */\n        OGGVORBIS,       /* Ogg vorbis. */\n        PLAYLIST,        /* Information only from ASX/PLS/M3U/WAX playlists */\n        RAW,             /* Raw PCM data. */\n        S3M,             /* ScreamTracker 3. */\n        USER,            /* User created sound. */\n        WAV,             /* Microsoft WAV. */\n        XM,              /* FastTracker 2 XM. */\n        XMA,             /* Xbox360 XMA */\n        AUDIOQUEUE,      /* iPhone hardware decoder, supports AAC, ALAC and MP3. extracodecdata is a pointer to an FMOD_AUDIOQUEUE_EXTRACODECDATA structure. */\n        AT9,             /* PS4 / PSVita ATRAC 9 format */\n        VORBIS,          /* Vorbis */\n        MEDIA_FOUNDATION,/* Windows Store Application built in system codecs */\n        MEDIACODEC,      /* Android MediaCodec */\n        FADPCM,          /* FMOD Adaptive Differential Pulse Code Modulation */\n\n        MAX,             /* Maximum number of sound types supported. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These definitions describe the native format of the hardware or software buffer that will be used.\n\n        [REMARKS]\n        This is the format the native hardware or software buffer will be or is created in.\n\n        [SEE_ALSO]\n        System::createSoundEx\n        Sound::getFormat\n    ]\n    */\n    public enum SOUND_FORMAT : int\n    {\n        NONE,       /* Unitialized / unknown */\n        PCM8,       /* 8bit integer PCM data */\n        PCM16,      /* 16bit integer PCM data  */\n        PCM24,      /* 24bit integer PCM data  */\n        PCM32,      /* 32bit integer PCM data  */\n        PCMFLOAT,   /* 32bit floating point PCM data  */\n        BITSTREAM,  /* Sound data is in its native compressed format. */\n\n        MAX         /* Maximum number of sound formats supported. */\n    }\n\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_MODE\n\n        [DESCRIPTION]\n        Sound description bitfields, bitwise OR them together for loading and describing sounds.\n\n        [REMARKS]\n        By default a sound will open as a static sound that is decompressed fully into memory to PCM. (ie equivalent of FMOD_CREATESAMPLE)<br>\n        To have a sound stream instead, use FMOD_CREATESTREAM, or use the wrapper function System::createStream.<br>\n        Some opening modes (ie FMOD_OPENUSER, FMOD_OPENMEMORY, FMOD_OPENMEMORY_POINT, FMOD_OPENRAW) will need extra information.<br>\n        This can be provided using the FMOD_CREATESOUNDEXINFO structure.\n        <br>\n        Specifying FMOD_OPENMEMORY_POINT will POINT to your memory rather allocating its own sound buffers and duplicating it internally.<br>\n        <b><u>This means you cannot free the memory while FMOD is using it, until after Sound::release is called.</b></u>\n        With FMOD_OPENMEMORY_POINT, for PCM formats, only WAV, FSB, and RAW are supported.  For compressed formats, only those formats supported by FMOD_CREATECOMPRESSEDSAMPLE are supported.<br>\n        With FMOD_OPENMEMORY_POINT and FMOD_OPENRAW or PCM, if using them together, note that you must pad the data on each side by 16 bytes.  This is so fmod can modify the ends of the data for looping/interpolation/mixing purposes.  If a wav file, you will need to insert silence, and then reset loop points to stop the playback from playing that silence.<br>\n        <br>\n        <b>Xbox 360 memory</b> On Xbox 360 Specifying FMOD_OPENMEMORY_POINT to a virtual memory address will cause FMOD_ERR_INVALID_ADDRESS\n        to be returned.  Use physical memory only for this functionality.<br>\n        <br>\n        FMOD_LOWMEM is used on a sound if you want to minimize the memory overhead, by having FMOD not allocate memory for certain\n        features that are not likely to be used in a game environment.  These are :<br>\n        1. Sound::getName functionality is removed.  256 bytes per sound is saved.<br>\n\n        [SEE_ALSO]\n        System::createSound\n        System::createStream\n        Sound::setMode\n        Sound::getMode\n        Channel::setMode\n        Channel::getMode\n        Sound::set3DCustomRolloff\n        Channel::set3DCustomRolloff\n        Sound::getOpenState\n    ]\n    */\n    [Flags]\n    public enum MODE : uint\n    {\n        DEFAULT                = 0x00000000,  /* Default for all modes listed below. FMOD_LOOP_OFF, FMOD_2D, FMOD_3D_WORLDRELATIVE, FMOD_3D_INVERSEROLLOFF */\n        LOOP_OFF               = 0x00000001,  /* For non looping sounds. (default).  Overrides FMOD_LOOP_NORMAL / FMOD_LOOP_BIDI. */\n        LOOP_NORMAL            = 0x00000002,  /* For forward looping sounds. */\n        LOOP_BIDI              = 0x00000004,  /* For bidirectional looping sounds. (only works on software mixed static sounds). */\n        _2D                    = 0x00000008,  /* Ignores any 3d processing. (default). */\n        _3D                    = 0x00000010,  /* Makes the sound positionable in 3D.  Overrides FMOD_2D. */\n        CREATESTREAM           = 0x00000080,  /* Decompress at runtime, streaming from the source provided (standard stream).  Overrides FMOD_CREATESAMPLE. */\n        CREATESAMPLE           = 0x00000100,  /* Decompress at loadtime, decompressing or decoding whole file into memory as the target sample format. (standard sample). */\n        CREATECOMPRESSEDSAMPLE = 0x00000200,  /* Load MP2, MP3, IMAADPCM or XMA into memory and leave it compressed.  During playback the FMOD software mixer will decode it in realtime as a 'compressed sample'.  Can only be used in combination with FMOD_SOFTWARE. */\n        OPENUSER               = 0x00000400,  /* Opens a user created static sample or stream. Use FMOD_CREATESOUNDEXINFO to specify format and/or read callbacks.  If a user created 'sample' is created with no read callback, the sample will be empty.  Use FMOD_Sound_Lock and FMOD_Sound_Unlock to place sound data into the sound if this is the case. */\n        OPENMEMORY             = 0x00000800,  /* \"name_or_data\" will be interpreted as a pointer to memory instead of filename for creating sounds. */\n        OPENMEMORY_POINT       = 0x10000000,  /* \"name_or_data\" will be interpreted as a pointer to memory instead of filename for creating sounds.  Use FMOD_CREATESOUNDEXINFO to specify length.  This differs to FMOD_OPENMEMORY in that it uses the memory as is, without duplicating the memory into its own buffers.  Cannot be freed after open, only after Sound::release.   Will not work if the data is compressed and FMOD_CREATECOMPRESSEDSAMPLE is not used. */\n        OPENRAW                = 0x00001000,  /* Will ignore file format and treat as raw pcm.  User may need to declare if data is FMOD_SIGNED or FMOD_UNSIGNED */\n        OPENONLY               = 0x00002000,  /* Just open the file, dont prebuffer or read.  Good for fast opens for info, or when sound::readData is to be used. */\n        ACCURATETIME           = 0x00004000,  /* For FMOD_CreateSound - for accurate FMOD_Sound_GetLength / FMOD_Channel_SetPosition on VBR MP3, AAC and MOD/S3M/XM/IT/MIDI files.  Scans file first, so takes longer to open. FMOD_OPENONLY does not affect this. */\n        MPEGSEARCH             = 0x00008000,  /* For corrupted / bad MP3 files.  This will search all the way through the file until it hits a valid MPEG header.  Normally only searches for 4k. */\n        NONBLOCKING            = 0x00010000,  /* For opening sounds and getting streamed subsounds (seeking) asyncronously.  Use Sound::getOpenState to poll the state of the sound as it opens or retrieves the subsound in the background. */\n        UNIQUE                 = 0x00020000,  /* Unique sound, can only be played one at a time */\n        _3D_HEADRELATIVE       = 0x00040000,  /* Make the sound's position, velocity and orientation relative to the listener. */\n        _3D_WORLDRELATIVE      = 0x00080000,  /* Make the sound's position, velocity and orientation absolute (relative to the world). (DEFAULT) */\n        _3D_INVERSEROLLOFF     = 0x00100000,  /* This sound will follow the inverse rolloff model where mindistance = full volume, maxdistance = where sound stops attenuating, and rolloff is fixed according to the global rolloff factor.  (DEFAULT) */\n        _3D_LINEARROLLOFF      = 0x00200000,  /* This sound will follow a linear rolloff model where mindistance = full volume, maxdistance = silence.  */\n        _3D_LINEARSQUAREROLLOFF= 0x00400000,  /* This sound will follow a linear-square rolloff model where mindistance = full volume, maxdistance = silence.  Rolloffscale is ignored. */\n        _3D_INVERSETAPEREDROLLOFF = 0x00800000,  /* This sound will follow the inverse rolloff model at distances close to mindistance and a linear-square rolloff close to maxdistance. */\n        _3D_CUSTOMROLLOFF      = 0x04000000,  /* This sound will follow a rolloff model defined by Sound::set3DCustomRolloff / Channel::set3DCustomRolloff.  */\n        _3D_IGNOREGEOMETRY     = 0x40000000,  /* Is not affect by geometry occlusion.  If not specified in Sound::setMode, or Channel::setMode, the flag is cleared and it is affected by geometry again. */\n        IGNORETAGS             = 0x02000000,  /* Skips id3v2/asf/etc tag checks when opening a sound, to reduce seek/read overhead when opening files (helps with CD performance). */\n        LOWMEM                 = 0x08000000,  /* Removes some features from samples to give a lower memory overhead, like Sound::getName. */\n        LOADSECONDARYRAM       = 0x20000000,  /* Load sound into the secondary RAM of supported platform.  On PS3, sounds will be loaded into RSX/VRAM. */\n        VIRTUAL_PLAYFROMSTART  = 0x80000000   /* For sounds that start virtual (due to being quiet or low importance), instead of swapping back to audible, and playing at the correct offset according to time, this flag makes the sound play from the start. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These values describe what state a sound is in after FMOD_NONBLOCKING has been used to open it.\n\n        [REMARKS]\n        With streams, if you are using FMOD_NONBLOCKING, note that if the user calls Sound::getSubSound, a stream will go into FMOD_OPENSTATE_SEEKING state and sound related commands will return FMOD_ERR_NOTREADY.<br>\n        With streams, if you are using FMOD_NONBLOCKING, note that if the user calls Channel::getPosition, a stream will go into FMOD_OPENSTATE_SETPOSITION state and sound related commands will return FMOD_ERR_NOTREADY.<br>\n\n        [SEE_ALSO]\n        Sound::getOpenState\n        FMOD_MODE\n    ]\n    */\n    public enum OPENSTATE : int\n    {\n        READY = 0,       /* Opened and ready to play */\n        LOADING,         /* Initial load in progress */\n        ERROR,           /* Failed to open - file not found, out of memory etc.  See return value of Sound::getOpenState for what happened. */\n        CONNECTING,      /* Connecting to remote host (internet sounds only) */\n        BUFFERING,       /* Buffering data */\n        SEEKING,         /* Seeking to subsound and re-flushing stream buffer. */\n        PLAYING,         /* Ready and playing, but not possible to release at this time without stalling the main thread. */\n        SETPOSITION,     /* Seeking within a stream to a different position. */\n\n        MAX,             /* Maximum number of open state types. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These flags are used with SoundGroup::setMaxAudibleBehavior to determine what happens when more sounds\n        are played than are specified with SoundGroup::setMaxAudible.\n\n        [REMARKS]\n        When using FMOD_SOUNDGROUP_BEHAVIOR_MUTE, SoundGroup::setMuteFadeSpeed can be used to stop a sudden transition.\n        Instead, the time specified will be used to cross fade between the sounds that go silent and the ones that become audible.\n\n        [SEE_ALSO]\n        SoundGroup::setMaxAudibleBehavior\n        SoundGroup::getMaxAudibleBehavior\n        SoundGroup::setMaxAudible\n        SoundGroup::getMaxAudible\n        SoundGroup::setMuteFadeSpeed\n        SoundGroup::getMuteFadeSpeed\n    ]\n    */\n    public enum SOUNDGROUP_BEHAVIOR : int\n    {\n        BEHAVIOR_FAIL,              /* Any sound played that puts the sound count over the SoundGroup::setMaxAudible setting, will simply fail during System::playSound. */\n        BEHAVIOR_MUTE,              /* Any sound played that puts the sound count over the SoundGroup::setMaxAudible setting, will be silent, then if another sound in the group stops the sound that was silent before becomes audible again. */\n        BEHAVIOR_STEALLOWEST,       /* Any sound played that puts the sound count over the SoundGroup::setMaxAudible setting, will steal the quietest / least important sound playing in the group. */\n\n        MAX,               /* Maximum number of sound group behaviors. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These callback types are used with Channel::setCallback.\n\n        [REMARKS]\n        Each callback has commanddata parameters passed as int unique to the type of callback.<br>\n        See reference to FMOD_CHANNELCONTROL_CALLBACK to determine what they might mean for each type of callback.<br>\n        <br>\n        <b>Note!</b>  Currently the user must call System::update for these callbacks to trigger!\n\n        [SEE_ALSO]\n        Channel::setCallback\n        ChannelGroup::setCallback\n        FMOD_CHANNELCONTROL_CALLBACK\n        System::update\n    ]\n    */\n    public enum CHANNELCONTROL_CALLBACK_TYPE : int\n    {\n        END,                  /* Called when a sound ends. */\n        VIRTUALVOICE,         /* Called when a voice is swapped out or swapped in. */\n        SYNCPOINT,            /* Called when a syncpoint is encountered.  Can be from wav file markers. */\n        OCCLUSION,            /* Called when the channel has its geometry occlusion value calculated.  Can be used to clamp or change the value. */\n\n        MAX,                  /* Maximum number of callback types supported. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These enums denote special types of node within a DSP chain.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        Channel::getDSP\n        ChannelGroup::getDSP\n    ]\n    */\n    public struct CHANNELCONTROL_DSP_INDEX\n    {\n        public const int HEAD    = -1;         /* Head of the DSP chain. */\n        public const int FADER   = -2;         /* Built in fader DSP. */\n        public const int PANNER  = -3;         /* Built in panner DSP. */\n        public const int TAIL    = -4;         /* Tail of the DSP chain. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Used to distinguish the instance type passed into FMOD_ERROR_CALLBACK.\n\n        [REMARKS]\n        Cast the instance of FMOD_ERROR_CALLBACK to the appropriate class indicated by this enum.\n\n        [SEE_ALSO]\n    ]\n    */\n    public enum ERRORCALLBACK_INSTANCETYPE\n    {\n        NONE,\n        SYSTEM,\n        CHANNEL,\n        CHANNELGROUP,\n        CHANNELCONTROL,\n        SOUND,\n        SOUNDGROUP,\n        DSP,\n        DSPCONNECTION,\n        GEOMETRY,\n        REVERB3D,\n        STUDIO_SYSTEM,\n        STUDIO_EVENTDESCRIPTION,\n        STUDIO_EVENTINSTANCE,\n        STUDIO_PARAMETERINSTANCE,\n        STUDIO_CUEINSTANCE,\n        STUDIO_BUS,\n        STUDIO_VCA,\n        STUDIO_BANK,\n        STUDIO_COMMANDREPLAY\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure that is passed into FMOD_SYSTEM_CALLBACK for the FMOD_SYSTEM_CALLBACK_ERROR callback type.\n\n        [REMARKS]\n        The instance pointer will be a type corresponding to the instanceType enum.\n\n        [SEE_ALSO]\n        FMOD_ERRORCALLBACK_INSTANCETYPE\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ERRORCALLBACK_INFO\n    {\n        public  RESULT                      result;                     /* Error code result */\n        public  ERRORCALLBACK_INSTANCETYPE  instancetype;               /* Type of instance the error occurred on */\n        public  IntPtr                      instance;                   /* Instance pointer */\n        private IntPtr                      functionname_internal;      /* Function that the error occurred on */\n        private IntPtr                      functionparams_internal;    /* Function parameters that the error ocurred on */\n\n        public string functionname   { get { return Marshal.PtrToStringAnsi(functionname_internal); } }\n        public string functionparams { get { return Marshal.PtrToStringAnsi(functionparams_internal); } }\n    }\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_SYSTEM_CALLBACK_TYPE\n\n        [DESCRIPTION]\n        These callback types are used with System::setCallback.\n\n        [REMARKS]\n        Each callback has commanddata parameters passed as void* unique to the type of callback.<br>\n        See reference to FMOD_SYSTEM_CALLBACK to determine what they might mean for each type of callback.<br>\n        <br>\n        <b>Note!</b> Using FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED (on Mac only) requires the application to be running an event loop which will allow external changes to device list to be detected by FMOD.<br>\n        <br>\n        <b>Note!</b> The 'system' object pointer will be null for FMOD_SYSTEM_CALLBACK_THREADCREATED and FMOD_SYSTEM_CALLBACK_MEMORYALLOCATIONFAILED callbacks.\n\n        [SEE_ALSO]\n        System::setCallback\n        System::update\n        DSP::addInput\n    ]\n    */\n    [Flags]\n    public enum SYSTEM_CALLBACK_TYPE : uint\n    {\n        DEVICELISTCHANGED      = 0x00000001,  /* Called from System::update when the enumerated list of devices has changed. */\n        DEVICELOST             = 0x00000002,  /* Called from System::update when an output device has been lost due to control panel parameter changes and FMOD cannot automatically recover. */\n        MEMORYALLOCATIONFAILED = 0x00000004,  /* Called directly when a memory allocation fails somewhere in FMOD.  (NOTE - 'system' will be NULL in this callback type.)*/\n        THREADCREATED          = 0x00000008,  /* Called directly when a thread is created. (NOTE - 'system' will be NULL in this callback type.) */\n        BADDSPCONNECTION       = 0x00000010,  /* Called when a bad connection was made with DSP::addInput. Usually called from mixer thread because that is where the connections are made.  */\n        PREMIX                 = 0x00000020,  /* Called each tick before a mix update happens. */\n        POSTMIX                = 0x00000040,  /* Called each tick after a mix update happens. */\n        ERROR                  = 0x00000080,  /* Called when each API function returns an error code, including delayed async functions. */\n        MIDMIX                 = 0x00000100,  /* Called each tick in mix update after clocks have been updated before the main mix occurs. */\n        THREADDESTROYED        = 0x00000200,  /* Called directly when a thread is destroyed. */\n        PREUPDATE              = 0x00000400,  /* Called at start of System::update function. */\n        POSTUPDATE             = 0x00000800,  /* Called at end of System::update function. */\n        RECORDLISTCHANGED      = 0x00001000,  /* Called from System::update when the enumerated list of recording devices has changed. */\n        ALL                    = 0xFFFFFFFF,  /* Pass this mask to System::setCallback to receive all callback types.  */\n    }\n\t\n    #region wrapperinternal\n    [StructLayout(LayoutKind.Sequential)]\n    public struct StringWrapper\n    {\n        IntPtr nativeUtf8Ptr;\n\n        public static implicit operator string(StringWrapper fstring)\n        {\n            if (fstring.nativeUtf8Ptr == IntPtr.Zero)\n            {\n                return \"\";\n            }\n\n            int strlen = 0;\n            while (Marshal.ReadByte(fstring.nativeUtf8Ptr, strlen) != 0)\n            {\n                strlen++;\n            }\n            if (strlen > 0)\n            {\n                byte[] bytes = new byte[strlen];\n                Marshal.Copy(fstring.nativeUtf8Ptr, bytes, 0, strlen);\n                return Encoding.UTF8.GetString(bytes, 0, strlen);\n            }\n            else\n            {\n                return \"\";\n            }\n        }\n    }\n    #endregion\n\n    /*\n        FMOD Callbacks\n    */\n    public delegate RESULT ASYNCREADINFO_DONE_CALLBACK(IntPtr info, RESULT result);\n\n    public delegate RESULT DEBUG_CALLBACK           (DEBUG_FLAGS flags, string file, int line, string func, string message);\n\n    public delegate RESULT SYSTEM_CALLBACK          (IntPtr systemraw, SYSTEM_CALLBACK_TYPE type, IntPtr commanddata1, IntPtr commanddata2, IntPtr userdata);\n\n    public delegate RESULT CHANNEL_CALLBACK         (IntPtr channelraw, CHANNELCONTROL_TYPE controltype, CHANNELCONTROL_CALLBACK_TYPE type, IntPtr commanddata1, IntPtr commanddata2);\n\n    public delegate RESULT SOUND_NONBLOCKCALLBACK   (IntPtr soundraw, RESULT result);\n    public delegate RESULT SOUND_PCMREADCALLBACK    (IntPtr soundraw, IntPtr data, uint datalen);\n    public delegate RESULT SOUND_PCMSETPOSCALLBACK  (IntPtr soundraw, int subsound, uint position, TIMEUNIT postype);\n\n    public delegate RESULT FILE_OPENCALLBACK        (StringWrapper name, ref uint filesize, ref IntPtr handle, IntPtr userdata);\n    public delegate RESULT FILE_CLOSECALLBACK       (IntPtr handle, IntPtr userdata);\n    public delegate RESULT FILE_READCALLBACK        (IntPtr handle, IntPtr buffer, uint sizebytes, ref uint bytesread, IntPtr userdata);\n    public delegate RESULT FILE_SEEKCALLBACK        (IntPtr handle, uint pos, IntPtr userdata);\n    public delegate RESULT FILE_ASYNCREADCALLBACK   (IntPtr handle, IntPtr info, IntPtr userdata);\n    public delegate RESULT FILE_ASYNCCANCELCALLBACK (IntPtr handle, IntPtr userdata);\n\n    public delegate IntPtr MEMORY_ALLOC_CALLBACK    (uint size, MEMORY_TYPE type, StringWrapper sourcestr);\n    public delegate IntPtr MEMORY_REALLOC_CALLBACK  (IntPtr ptr, uint size, MEMORY_TYPE type, StringWrapper sourcestr);\n    public delegate void   MEMORY_FREE_CALLBACK     (IntPtr ptr, MEMORY_TYPE type, StringWrapper sourcestr);\n\n    public delegate float  CB_3D_ROLLOFFCALLBACK    (IntPtr channelraw, float distance);\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        List of interpolation types that the FMOD Ex software mixer supports.\n\n        [REMARKS]\n        The default resampler type is FMOD_DSP_RESAMPLER_LINEAR.<br>\n        Use System::setSoftwareFormat to tell FMOD the resampling quality you require for FMOD_SOFTWARE based sounds.\n\n        [SEE_ALSO]\n        System::setSoftwareFormat\n        System::getSoftwareFormat\n    ]\n    */\n    public enum DSP_RESAMPLER : int\n    {\n        DEFAULT,         /* Default interpolation method.  Currently equal to FMOD_DSP_RESAMPLER_LINEAR. */\n        NOINTERP,        /* No interpolation.  High frequency aliasing hiss will be audible depending on the sample rate of the sound. */\n        LINEAR,          /* Linear interpolation (default method).  Fast and good quality, causes very slight lowpass effect on low frequency sounds. */\n        CUBIC,           /* Cubic interpolation.  Slower than linear interpolation but better quality. */\n        SPLINE,          /* 5 point spline interpolation.  Slowest resampling method but best quality. */\n\n        MAX,             /* Maximum number of resample methods supported. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        List of connection types between 2 DSP nodes.\n\n        [REMARKS]\n        FMOD_DSP_CONNECTION_TYPE_STANDARD<br>\n        ----------------------------------<br>\n        Default DSPConnection type.  Audio is mixed from the input to the output DSP's audible buffer, meaning it will be part of the audible signal.  A standard connection will execute its input DSP if it has not been executed before.<br>\n        <br>\n        FMOD_DSP_CONNECTION_TYPE_SIDECHAIN<br>\n        ----------------------------------<br>\n        Sidechain DSPConnection type.  Audio is mixed from the input to the output DSP's sidechain buffer, meaning it will NOT be part of the audible signal.  A sidechain connection will execute its input DSP if it has not been executed before.<br>\n        The purpose of the seperate sidechain buffer in a DSP, is so that the DSP effect can privately access for analysis purposes.  An example of use in this case, could be a compressor which analyzes the signal, to control its own effect parameters (ie a compression level or gain).<br>\n        <br>\n        For the effect developer, to accept sidechain data, the sidechain data will appear in the FMOD_DSP_STATE struct which is passed into the read callback of a DSP unit.<br>\n        FMOD_DSP_STATE::sidechaindata and FMOD_DSP::sidechainchannels will hold the mixed result of any sidechain data flowing into it.<br>\n        <br>\n        FMOD_DSP_CONNECTION_TYPE_SEND<br>\n        -----------------------------<br>\n        Send DSPConnection type.  Audio is mixed from the input to the output DSP's audible buffer, meaning it will be part of the audible signal.  A send connection will NOT execute its input DSP if it has not been executed before.<br>\n        A send connection will only read what exists at the input's buffer at the time of executing the output DSP unit (which can be considered the 'return')<br>\n        <br>\n        FMOD_DSP_CONNECTION_TYPE_SEND_SIDECHAIN<br>\n        ---------------------------------------<br>\n        Send sidechain DSPConnection type.  Audio is mixed from the input to the output DSP's sidechain buffer, meaning it will NOT be part of the audible signal.  A send sidechain connection will NOT execute its input DSP if it has not been executed before.<br>\n        A send sidechain connection will only read what exists at the input's buffer at the time of executing the output DSP unit (which can be considered the 'sidechain return').\n        <br>\n        For the effect developer, to accept sidechain data, the sidechain data will appear in the FMOD_DSP_STATE struct which is passed into the read callback of a DSP unit.<br>\n        FMOD_DSP_STATE::sidechaindata and FMOD_DSP::sidechainchannels will hold the mixed result of any sidechain data flowing into it.\n\n        [SEE_ALSO]\n        DSP::addInput\n        DSPConnection::getType\n    ]\n    */\n    public enum DSPCONNECTION_TYPE : int\n    {\n        STANDARD,          /* Default connection type.         Audio is mixed from the input to the output DSP's audible buffer.  */\n        SIDECHAIN,         /* Sidechain connection type.       Audio is mixed from the input to the output DSP's sidechain buffer.  */\n        SEND,              /* Send connection type.            Audio is mixed from the input to the output DSP's audible buffer, but the input is NOT executed, only copied from.  A standard connection or sidechain needs to make an input execute to generate data. */\n        SEND_SIDECHAIN,    /* Send sidechain connection type.  Audio is mixed from the input to the output DSP's sidechain buffer, but the input is NOT executed, only copied from.  A standard connection or sidechain needs to make an input execute to generate data. */\n\n        MAX,               /* Maximum number of DSP connection types supported. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        List of tag types that could be stored within a sound.  These include id3 tags, metadata from netstreams and vorbis/asf data.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        Sound::getTag\n    ]\n    */\n    public enum TAGTYPE : int\n    {\n        UNKNOWN = 0,\n        ID3V1,\n        ID3V2,\n        VORBISCOMMENT,\n        SHOUTCAST,\n        ICECAST,\n        ASF,\n        MIDI,\n        PLAYLIST,\n        FMOD,\n        USER,\n\n        MAX                /* Maximum number of tag types supported. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        List of data types that can be returned by Sound::getTag\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        Sound::getTag\n    ]\n    */\n    public enum TAGDATATYPE : int\n    {\n        BINARY = 0,\n        INT,\n        FLOAT,\n        STRING,\n        STRING_UTF16,\n        STRING_UTF16BE,\n        STRING_UTF8,\n        CDTOC,\n\n        MAX                /* Maximum number of tag datatypes supported. */\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure describing a piece of tag data.\n\n        [REMARKS]\n        Members marked with [w] mean the user sets the value before passing it to the function.\n        Members marked with [r] mean FMOD sets the value to be used after the function exits.\n\n        [SEE_ALSO]\n        Sound::getTag\n        TAGTYPE\n        TAGDATATYPE\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct TAG\n    {\n        public  TAGTYPE           type;         /* [r] The type of this tag. */\n        public  TAGDATATYPE       datatype;     /* [r] The type of data that this tag contains */\n        private IntPtr            name_internal;/* [r] The name of this tag i.e. \"TITLE\", \"ARTIST\" etc. */\n        public  IntPtr            data;         /* [r] Pointer to the tag data - its format is determined by the datatype member */\n        public  uint              datalen;      /* [r] Length of the data contained in this tag */\n        public  bool              updated;      /* [r] True if this tag has been updated since last being accessed with Sound::getTag */\n\n        public string name { get { return Marshal.PtrToStringAnsi(name_internal); } }\n    }\n\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_TIMEUNIT\n\n        [DESCRIPTION]\n        List of time types that can be returned by Sound::getLength and used with Channel::setPosition or Channel::getPosition.\n\n        [REMARKS]\n        Do not combine flags except FMOD_TIMEUNIT_BUFFERED.\n\n        [SEE_ALSO]\n        Sound::getLength\n        Channel::setPosition\n        Channel::getPosition\n    ]\n    */\n    [Flags]\n    public enum TIMEUNIT : uint\n    {\n        MS                = 0x00000001,  /* Milliseconds. */\n        PCM               = 0x00000002,  /* PCM Samples, related to milliseconds * samplerate / 1000. */\n        PCMBYTES          = 0x00000004,  /* Bytes, related to PCM samples * channels * datawidth (ie 16bit = 2 bytes). */\n        RAWBYTES          = 0x00000008,  /* Raw file bytes of (compressed) sound data (does not include headers).  Only used by Sound::getLength and Channel::getPosition. */\n        PCMFRACTION       = 0x00000010,  /* Fractions of 1 PCM sample.  Unsigned int range 0 to 0xFFFFFFFF.  Used for sub-sample granularity for DSP purposes. */\n        MODORDER          = 0x00000100,  /* MOD/S3M/XM/IT.  Order in a sequenced module format.  Use Sound::getFormat to determine the format. */\n        MODROW            = 0x00000200,  /* MOD/S3M/XM/IT.  Current row in a sequenced module format.  Sound::getLength will return the number if rows in the currently playing or seeked to pattern. */\n        MODPATTERN        = 0x00000400,  /* MOD/S3M/XM/IT.  Current pattern in a sequenced module format.  Sound::getLength will return the number of patterns in the song and Channel::getPosition will return the currently playing pattern. */\n        BUFFERED          = 0x10000000,  /* Time value as seen by buffered stream.  This is always ahead of audible time, and is only used for processing. */\n    }\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_PORT_INDEX\n\n        [DESCRIPTION]\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        System::AttachChannelGroupToPort\n    ]\n    */\n    public struct PORT_INDEX\n    {\n        public const ulong NONE = 0xFFFFFFFFFFFFFFFF;\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Use this structure with System::createSound when more control is needed over loading.\n        The possible reasons to use this with System::createSound are:\n\n        - Loading a file from memory.\n        - Loading a file from within another larger (possibly wad/pak) file, by giving the loader an offset and length.\n        - To create a user created / non file based sound.\n        - To specify a starting subsound to seek to within a multi-sample sounds (ie FSB/DLS) when created as a stream.\n        - To specify which subsounds to load for multi-sample sounds (ie FSB/DLS) so that memory is saved and only a subset is actually loaded/read from disk.\n        - To specify 'piggyback' read and seek callbacks for capture of sound data as fmod reads and decodes it.  Useful for ripping decoded PCM data from sounds as they are loaded / played.\n        - To specify a MIDI DLS sample set file to load when opening a MIDI file.\n\n        See below on what members to fill for each of the above types of sound you want to create.\n\n        [REMARKS]\n        This structure is optional!  Specify 0 or NULL in System::createSound if you don't need it!\n\n        <u>Loading a file from memory.</u>\n\n        - Create the sound using the FMOD_OPENMEMORY flag.\n        - Mandatory.  Specify 'length' for the size of the memory block in bytes.\n        - Other flags are optional.\n\n        <u>Loading a file from within another larger (possibly wad/pak) file, by giving the loader an offset and length.</u>\n\n        - Mandatory.  Specify 'fileoffset' and 'length'.\n        - Other flags are optional.\n\n        <u>To create a user created / non file based sound.</u>\n\n        - Create the sound using the FMOD_OPENUSER flag.\n        - Mandatory.  Specify 'defaultfrequency, 'numchannels' and 'format'.\n        - Other flags are optional.\n\n        <u>To specify a starting subsound to seek to and flush with, within a multi-sample stream (ie FSB/DLS).</u>\n\n        - Mandatory.  Specify 'initialsubsound'.\n\n        <u>To specify which subsounds to load for multi-sample sounds (ie FSB/DLS) so that memory is saved and only a subset is actually loaded/read from disk.</u>\n\n        - Mandatory.  Specify 'inclusionlist' and 'inclusionlistnum'.\n\n        <u>To specify 'piggyback' read and seek callbacks for capture of sound data as fmod reads and decodes it.  Useful for ripping decoded PCM data from sounds as they are loaded / played.</u>\n\n        - Mandatory.  Specify 'pcmreadcallback' and 'pcmseekcallback'.\n\n        <u>To specify a MIDI DLS sample set file to load when opening a MIDI file.</u>\n\n        - Mandatory.  Specify 'dlsname'.\n\n        Setting the 'decodebuffersize' is for cpu intensive codecs that may be causing stuttering, not file intensive codecs (ie those from CD or netstreams) which are normally\n        altered with System::setStreamBufferSize.  As an example of cpu intensive codecs, an mp3 file will take more cpu to decode than a PCM wav file.\n\n        If you have a stuttering effect, then it is using more cpu than the decode buffer playback rate can keep up with.  Increasing the decode buffersize will most likely solve this problem.\n\n        FSB codec.  If inclusionlist and numsubsounds are used together, this will trigger a special mode where subsounds are shuffled down to save memory.  (useful for large FSB\n        files where you only want to load 1 sound).  There will be no gaps, ie no null subsounds.  As an example, if there are 10,000 subsounds and there is an inclusionlist with only 1 entry,\n        and numsubsounds = 1, then subsound 0 will be that entry, and there will only be the memory allocated for 1 subsound.  Previously there would still be 10,000 subsound pointers and other\n        associated codec entries allocated along with it multiplied by 10,000.\n\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.<br>\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        System::createSound\n        System::setStreamBufferSize\n        FMOD_MODE\n        FMOD_SOUND_FORMAT\n        FMOD_SOUND_TYPE\n        FMOD_CHANNELMASK\n        FMOD_CHANNELORDER\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct CREATESOUNDEXINFO\n    {\n        public int                         cbsize;                 /* [w] Size of this structure.  This is used so the structure can be expanded in the future and still work on older versions of FMOD Ex. */\n        public uint                        length;                 /* [w] Optional. Specify 0 to ignore. Size in bytes of file to load, or sound to create (in this case only if FMOD_OPENUSER is used).  Required if loading from memory.  If 0 is specified, then it will use the size of the file (unless loading from memory then an error will be returned). */\n        public uint                        fileoffset;             /* [w] Optional. Specify 0 to ignore. Offset from start of the file to start loading from.  This is useful for loading files from inside big data files. */\n        public int                         numchannels;            /* [w] Optional. Specify 0 to ignore. Number of channels in a sound specified only if OPENUSER is used. */\n        public int                         defaultfrequency;       /* [w] Optional. Specify 0 to ignore. Default frequency of sound in a sound specified only if OPENUSER is used.  Other formats use the frequency determined by the file format. */\n        public SOUND_FORMAT                format;                 /* [w] Optional. Specify 0 or SOUND_FORMAT_NONE to ignore. Format of the sound specified only if OPENUSER is used.  Other formats use the format determined by the file format.   */\n        public uint                        decodebuffersize;       /* [w] Optional. Specify 0 to ignore. For streams.  This determines the size of the double buffer (in PCM samples) that a stream uses.  Use this for user created streams if you want to determine the size of the callback buffer passed to you.  Specify 0 to use FMOD's default size which is currently equivalent to 400ms of the sound format created/loaded. */\n        public int                         initialsubsound;        /* [w] Optional. Specify 0 to ignore. In a multi-sample file format such as .FSB/.DLS/.SF2, specify the initial subsound to seek to, only if CREATESTREAM is used. */\n        public int                         numsubsounds;           /* [w] Optional. Specify 0 to ignore or have no subsounds.  In a user created multi-sample sound, specify the number of subsounds within the sound that are accessable with Sound::getSubSound / SoundGetSubSound. */\n        public IntPtr                      inclusionlist;          /* [w] Optional. Specify 0 to ignore. In a multi-sample format such as .FSB/.DLS/.SF2 it may be desirable to specify only a subset of sounds to be loaded out of the whole file.  This is an array of subsound indicies to load into memory when created. */\n        public int                         inclusionlistnum;       /* [w] Optional. Specify 0 to ignore. This is the number of integers contained within the */\n        public SOUND_PCMREADCALLBACK       pcmreadcallback;        /* [w] Optional. Specify 0 to ignore. Callback to 'piggyback' on FMOD's read functions and accept or even write PCM data while FMOD is opening the sound.  Used for user sounds created with OPENUSER or for capturing decoded data as FMOD reads it. */\n        public SOUND_PCMSETPOSCALLBACK     pcmsetposcallback;      /* [w] Optional. Specify 0 to ignore. Callback for when the user calls a seeking function such as Channel::setPosition within a multi-sample sound, and for when it is opened.*/\n        public SOUND_NONBLOCKCALLBACK      nonblockcallback;       /* [w] Optional. Specify 0 to ignore. Callback for successful completion, or error while loading a sound that used the FMOD_NONBLOCKING flag.*/\n        public IntPtr                      dlsname;                /* [w] Optional. Specify 0 to ignore. Filename for a DLS or SF2 sample set when loading a MIDI file.   If not specified, on windows it will attempt to open /windows/system32/drivers/gm.dls, otherwise the MIDI will fail to open.  */\n        public IntPtr                      encryptionkey;          /* [w] Optional. Specify 0 to ignore. Key for encrypted FSB file.  Without this key an encrypted FSB file will not load. */\n        public int                         maxpolyphony;           /* [w] Optional. Specify 0 to ingore. For sequenced formats with dynamic channel allocation such as .MID and .IT, this specifies the maximum voice count allowed while playing.  .IT defaults to 64.  .MID defaults to 32. */\n        public IntPtr                      userdata;               /* [w] Optional. Specify 0 to ignore. This is user data to be attached to the sound during creation.  Access via Sound::getUserData. */\n        public SOUND_TYPE                  suggestedsoundtype;     /* [w] Optional. Specify 0 or FMOD_SOUND_TYPE_UNKNOWN to ignore.  Instead of scanning all codec types, use this to speed up loading by making it jump straight to this codec. */\n        public FILE_OPENCALLBACK           fileuseropen;           /* [w] Optional. Specify 0 to ignore. Callback for opening this file. */\n        public FILE_CLOSECALLBACK          fileuserclose;          /* [w] Optional. Specify 0 to ignore. Callback for closing this file. */\n        public FILE_READCALLBACK           fileuserread;           /* [w] Optional. Specify 0 to ignore. Callback for reading from this file. */\n        public FILE_SEEKCALLBACK           fileuserseek;           /* [w] Optional. Specify 0 to ignore. Callback for seeking within this file. */\n        public FILE_ASYNCREADCALLBACK      fileuserasyncread;      /* [w] Optional. Specify 0 to ignore. Callback for asyncronously reading from this file. */\n        public FILE_ASYNCCANCELCALLBACK    fileuserasynccancel;    /* [w] Optional. Specify 0 to ignore. Callback for cancelling an asyncronous read. */\n        public IntPtr                      fileuserdata;           /* [w] Optional. Specify 0 to ignore. User data to be passed into the file callbacks. */\n        public CHANNELORDER                channelorder;           /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers.  See FMOD_CHANNELORDER for more. */\n        public CHANNELMASK                 channelmask;            /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers.  See FMOD_CHANNELMASK for more. */\n        public IntPtr                      initialsoundgroup;      /* [w] Optional. Specify 0 to ignore. Specify a sound group if required, to put sound in as it is created. */\n        public uint                        initialseekposition;    /* [w] Optional. Specify 0 to ignore. For streams. Specify an initial position to seek the stream to. */\n        public TIMEUNIT                    initialseekpostype;     /* [w] Optional. Specify 0 to ignore. For streams. Specify the time unit for the position set in initialseekposition. */\n        public int                         ignoresetfilesystem;    /* [w] Optional. Specify 0 to ignore. Set to 1 to use fmod's built in file system. Ignores setFileSystem callbacks and also FMOD_CREATESOUNEXINFO file callbacks.  Useful for specific cases where you don't want to use your own file system but want to use fmod's file system (ie net streaming). */\n        public uint                        audioqueuepolicy;       /* [w] Optional. Specify 0 or FMOD_AUDIOQUEUE_CODECPOLICY_DEFAULT to ignore. Policy used to determine whether hardware or software is used for decoding, see FMOD_AUDIOQUEUE_CODECPOLICY for options (iOS >= 3.0 required, otherwise only hardware is available) */\n        public uint                        minmidigranularity;     /* [w] Optional. Specify 0 to ignore. Allows you to set a minimum desired MIDI mixer granularity. Values smaller than 512 give greater than default accuracy at the cost of more CPU and vise versa. Specify 0 for default (512 samples). */\n        public int                         nonblockthreadid;       /* [w] Optional. Specify 0 to ignore. Specifies a thread index to execute non blocking load on.  Allows for up to 5 threads to be used for loading at once.  This is to avoid one load blocking another.  Maximum value = 4. */\n    }\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure defining a reverb environment for FMOD_SOFTWARE based sounds only.<br>\n\n        [REMARKS]\n        Note the default reverb properties are the same as the FMOD_PRESET_GENERIC preset.<br>\n        Note that integer values that typically range from -10,000 to 1000 are represented in decibels,\n        and are of a logarithmic scale, not linear, wheras float values are always linear.<br>\n        <br>\n        The numerical values listed below are the maximum, minimum and default values for each variable respectively.<br>\n        <br>\n        Hardware voice / Platform Specific reverb support.<br>\n        WII   See FMODWII.H for hardware specific reverb functionality.<br>\n        3DS   See FMOD3DS.H for hardware specific reverb functionality.<br>\n        PSP   See FMODWII.H for hardware specific reverb functionality.<br>\n        <br>\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.<br>\n        Members marked with [w] mean the variable can be written to.  The user can set the value.<br>\n        Members marked with [r/w] are either read or write depending on if you are using System::setReverbProperties (w) or System::getReverbProperties (r).\n\n        [SEE_ALSO]\n        System::setReverbProperties\n        System::getReverbProperties\n        FMOD_REVERB_PRESETS\n    ]\n    */\n#pragma warning disable 414\n    [StructLayout(LayoutKind.Sequential)]\n    public struct REVERB_PROPERTIES\n    {                            /*        MIN     MAX    DEFAULT   DESCRIPTION */\n        public float DecayTime;         /* [r/w]  0.0    20000.0 1500.0  Reverberation decay time in ms                                        */\n        public float EarlyDelay;        /* [r/w]  0.0    300.0   7.0     Initial reflection delay time                                         */\n        public float LateDelay;         /* [r/w]  0.0    100     11.0    Late reverberation delay time relative to initial reflection          */\n        public float HFReference;       /* [r/w]  20.0   20000.0 5000    Reference high frequency (hz)                                         */\n        public float HFDecayRatio;      /* [r/w]  10.0   100.0   50.0    High-frequency to mid-frequency decay time ratio                      */\n        public float Diffusion;         /* [r/w]  0.0    100.0   100.0   Value that controls the echo density in the late reverberation decay. */\n        public float Density;           /* [r/w]  0.0    100.0   100.0   Value that controls the modal density in the late reverberation decay */\n        public float LowShelfFrequency; /* [r/w]  20.0   1000.0  250.0   Reference low frequency (hz)                                          */\n        public float LowShelfGain;      /* [r/w]  -36.0  12.0    0.0     Relative room effect level at low frequencies                         */\n        public float HighCut;           /* [r/w]  20.0   20000.0 20000.0 Relative room effect level at high frequencies                        */\n        public float EarlyLateMix;      /* [r/w]  0.0    100.0   50.0    Early reflections level relative to room effect                       */\n        public float WetLevel;          /* [r/w]  -80.0  20.0    -6.0    Room effect level (at mid frequencies)\n                                  * */\n        #region wrapperinternal\n        public REVERB_PROPERTIES(float decayTime, float earlyDelay, float lateDelay, float hfReference,\n            float hfDecayRatio, float diffusion, float density, float lowShelfFrequency, float lowShelfGain,\n            float highCut, float earlyLateMix, float wetLevel)\n        {\n            DecayTime = decayTime;\n            EarlyDelay = earlyDelay;\n            LateDelay = lateDelay;\n            HFReference = hfReference;\n            HFDecayRatio = hfDecayRatio;\n            Diffusion = diffusion;\n            Density = density;\n            LowShelfFrequency = lowShelfFrequency;\n            LowShelfGain = lowShelfGain;\n            HighCut = highCut;\n            EarlyLateMix = earlyLateMix;\n            WetLevel = wetLevel;\n        }\n        #endregion\n    }\n#pragma warning restore 414\n\n    /*\n    [DEFINE]\n    [\n    [NAME]\n    FMOD_REVERB_PRESETS\n\n    [DESCRIPTION]\n    A set of predefined environment PARAMETERS, created by Creative Labs\n    These are used to initialize an FMOD_REVERB_PROPERTIES structure statically.\n    ie\n    FMOD_REVERB_PROPERTIES prop = FMOD_PRESET_GENERIC;\n\n    [SEE_ALSO]\n    System::setReverbProperties\n    ]\n    */\n    public class PRESET\n    {\n        /*                                                                                  Instance  Env   Diffus  Room   RoomHF  RmLF DecTm   DecHF  DecLF   Refl  RefDel   Revb  RevDel  ModTm  ModDp   HFRef    LFRef   Diffus  Densty  FLAGS */\n        public static REVERB_PROPERTIES OFF()                 { return new REVERB_PROPERTIES(  1000,    7,  11, 5000, 100, 100, 100, 250, 0,    20,  96, -80.0f );}\n        public static REVERB_PROPERTIES GENERIC()             { return new REVERB_PROPERTIES(  1500,    7,  11, 5000,  83, 100, 100, 250, 0, 14500,  96,  -8.0f );}\n        public static REVERB_PROPERTIES PADDEDCELL()          { return new REVERB_PROPERTIES(   170,    1,   2, 5000,  10, 100, 100, 250, 0,   160,  84,  -7.8f );}\n        public static REVERB_PROPERTIES ROOM()                { return new REVERB_PROPERTIES(   400,    2,   3, 5000,  83, 100, 100, 250, 0,  6050,  88,  -9.4f );}\n        public static REVERB_PROPERTIES BATHROOM()            { return new REVERB_PROPERTIES(  1500,    7,  11, 5000,  54, 100,  60, 250, 0,  2900,  83,   0.5f );}\n        public static REVERB_PROPERTIES LIVINGROOM()          { return new REVERB_PROPERTIES(   500,    3,   4, 5000,  10, 100, 100, 250, 0,   160,  58, -19.0f );}\n        public static REVERB_PROPERTIES STONEROOM()           { return new REVERB_PROPERTIES(  2300,   12,  17, 5000,  64, 100, 100, 250, 0,  7800,  71,  -8.5f );}\n        public static REVERB_PROPERTIES AUDITORIUM()          { return new REVERB_PROPERTIES(  4300,   20,  30, 5000,  59, 100, 100, 250, 0,  5850,  64, -11.7f );}\n        public static REVERB_PROPERTIES CONCERTHALL()         { return new REVERB_PROPERTIES(  3900,   20,  29, 5000,  70, 100, 100, 250, 0,  5650,  80,  -9.8f );}\n        public static REVERB_PROPERTIES CAVE()                { return new REVERB_PROPERTIES(  2900,   15,  22, 5000, 100, 100, 100, 250, 0, 20000,  59, -11.3f );}\n        public static REVERB_PROPERTIES ARENA()               { return new REVERB_PROPERTIES(  7200,   20,  30, 5000,  33, 100, 100, 250, 0,  4500,  80,  -9.6f );}\n        public static REVERB_PROPERTIES HANGAR()              { return new REVERB_PROPERTIES( 10000,   20,  30, 5000,  23, 100, 100, 250, 0,  3400,  72,  -7.4f );}\n        public static REVERB_PROPERTIES CARPETTEDHALLWAY()    { return new REVERB_PROPERTIES(   300,    2,  30, 5000,  10, 100, 100, 250, 0,   500,  56, -24.0f );}\n        public static REVERB_PROPERTIES HALLWAY()             { return new REVERB_PROPERTIES(  1500,    7,  11, 5000,  59, 100, 100, 250, 0,  7800,  87,  -5.5f );}\n        public static REVERB_PROPERTIES STONECORRIDOR()       { return new REVERB_PROPERTIES(   270,   13,  20, 5000,  79, 100, 100, 250, 0,  9000,  86,  -6.0f );}\n        public static REVERB_PROPERTIES ALLEY()               { return new REVERB_PROPERTIES(  1500,    7,  11, 5000,  86, 100, 100, 250, 0,  8300,  80,  -9.8f );}\n        public static REVERB_PROPERTIES FOREST()              { return new REVERB_PROPERTIES(  1500,  162,  88, 5000,  54,  79, 100, 250, 0,   760,  94, -12.3f );}\n        public static REVERB_PROPERTIES CITY()                { return new REVERB_PROPERTIES(  1500,    7,  11, 5000,  67,  50, 100, 250, 0,  4050,  66, -26.0f );}\n        public static REVERB_PROPERTIES MOUNTAINS()           { return new REVERB_PROPERTIES(  1500,  300, 100, 5000,  21,  27, 100, 250, 0,  1220,  82, -24.0f );}\n        public static REVERB_PROPERTIES QUARRY()              { return new REVERB_PROPERTIES(  1500,   61,  25, 5000,  83, 100, 100, 250, 0,  3400, 100,  -5.0f );}\n        public static REVERB_PROPERTIES PLAIN()               { return new REVERB_PROPERTIES(  1500,  179, 100, 5000,  50,  21, 100, 250, 0,  1670,  65, -28.0f );}\n        public static REVERB_PROPERTIES PARKINGLOT()          { return new REVERB_PROPERTIES(  1700,    8,  12, 5000, 100, 100, 100, 250, 0, 20000,  56, -19.5f );}\n        public static REVERB_PROPERTIES SEWERPIPE()           { return new REVERB_PROPERTIES(  2800,   14,  21, 5000,  14,  80,  60, 250, 0,  3400,  66,   1.2f );}\n        public static REVERB_PROPERTIES UNDERWATER()          { return new REVERB_PROPERTIES(  1500,    7,  11, 5000,  10, 100, 100, 250, 0,   500,  92,   7.0f );}\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Settings for advanced features like configuring memory and cpu usage for the FMOD_CREATECOMPRESSEDSAMPLE feature.\n\n        [REMARKS]\n        maxMPEGCodecs / maxADPCMCodecs / maxXMACodecs will determine the maximum cpu usage of playing realtime samples.  Use this to lower potential excess cpu usage and also control memory usage.<br>\n\n        [SEE_ALSO]\n        System::setAdvancedSettings\n        System::getAdvancedSettings\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ADVANCEDSETTINGS\n    {\n        public int                 cbSize;                     /* [w]   Size of this structure.  Use sizeof(FMOD_ADVANCEDSETTINGS) */\n        public int                 maxMPEGCodecs;              /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only.  MPEG   codecs consume 30,528 bytes per instance and this number will determine how many MPEG   channels can be played simultaneously. Default = 32. */\n        public int                 maxADPCMCodecs;             /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only.  ADPCM  codecs consume  3,128 bytes per instance and this number will determine how many ADPCM  channels can be played simultaneously. Default = 32. */\n        public int                 maxXMACodecs;               /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only.  XMA    codecs consume 14,836 bytes per instance and this number will determine how many XMA    channels can be played simultaneously. Default = 32. */\n        public int                 maxVorbisCodecs;            /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only.  Vorbis codecs consume 23,256 bytes per instance and this number will determine how many Vorbis channels can be played simultaneously. Default = 32. */    \n        public int                 maxAT9Codecs;               /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only.  AT9    codecs consume  8,720 bytes per instance and this number will determine how many AT9    channels can be played simultaneously. Default = 32. */    \n        public int                 maxFADPCMCodecs;            /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only.  This number will determine how many FADPCM channels can be played simultaneously. Default = 32. */\n        public int                 maxPCMCodecs;               /* [r/w] Optional. Specify 0 to ignore. For use with PS3 only.                          PCM    codecs consume 12,672 bytes per instance and this number will determine how many streams and PCM voices can be played simultaneously. Default = 16. */\n        public int                 ASIONumChannels;            /* [r/w] Optional. Specify 0 to ignore. Number of channels available on the ASIO device. */\n        public IntPtr              ASIOChannelList;            /* [r/w] Optional. Specify 0 to ignore. Pointer to an array of strings (number of entries defined by ASIONumChannels) with ASIO channel names. */\n        public IntPtr              ASIOSpeakerList;            /* [r/w] Optional. Specify 0 to ignore. Pointer to a list of speakers that the ASIO channels map to.  This can be called after System::init to remap ASIO output. */\n        public float               HRTFMinAngle;               /* [r/w] Optional.                      For use with FMOD_INIT_HRTF_LOWPASS.  The angle range (0-360) of a 3D sound in relation to the listener, at which the HRTF function begins to have an effect. 0 = in front of the listener. 180 = from 90 degrees to the left of the listener to 90 degrees to the right. 360 = behind the listener. Default = 180.0. */\n        public float               HRTFMaxAngle;               /* [r/w] Optional.                      For use with FMOD_INIT_HRTF_LOWPASS.  The angle range (0-360) of a 3D sound in relation to the listener, at which the HRTF function has maximum effect. 0 = front of the listener. 180 = from 90 degrees to the left of the listener to 90 degrees to the right. 360 = behind the listener. Default = 360.0. */\n        public float               HRTFFreq;                   /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_HRTF_LOWPASS.  The cutoff frequency of the HRTF's lowpass filter function when at maximum effect. (i.e. at HRTFMaxAngle).  Default = 4000.0. */\n        public float               vol0virtualvol;             /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_VOL0_BECOMES_VIRTUAL.  If this flag is used, and the volume is below this, then the sound will become virtual.  Use this value to raise the threshold to a different point where a sound goes virtual. */\n        public uint                defaultDecodeBufferSize;    /* [r/w] Optional. Specify 0 to ignore. For streams. This determines the default size of the double buffer (in milliseconds) that a stream uses.  Default = 400ms */\n        public ushort              profilePort;                /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_PROFILE_ENABLE.  Specify the port to listen on for connections by the profiler application. */\n        public uint                geometryMaxFadeTime;        /* [r/w] Optional. Specify 0 to ignore. The maximum time in miliseconds it takes for a channel to fade to the new level when its occlusion changes. */\n        public float               distanceFilterCenterFreq;   /* [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_DISTANCE_FILTERING.  The default center frequency in Hz for the distance filtering effect. Default = 1500.0. */\n        public int                 reverb3Dinstance;           /* [r/w] Optional. Specify 0 to ignore. Out of 0 to 3, 3d reverb spheres will create a phyical reverb unit on this instance slot.  See FMOD_REVERB_PROPERTIES. */\n        public int                 DSPBufferPoolSize;          /* [r/w] Optional. Specify 0 to ignore. Number of buffers in DSP buffer pool.  Each buffer will be DSPBlockSize * sizeof(float) * SpeakerModeChannelCount.  ie 7.1 @ 1024 DSP block size = 8 * 1024 * 4 = 32kb.  Default = 8. */\n        public uint                stackSizeStream;            /* [r/w] Optional. Specify 0 to ignore. Specify the stack size for the FMOD Stream thread in bytes.  Useful for custom codecs that use excess stack.  Default 49,152 (48kb) */\n        public uint                stackSizeNonBlocking;       /* [r/w] Optional. Specify 0 to ignore. Specify the stack size for the FMOD_NONBLOCKING loading thread.  Useful for custom codecs that use excess stack.  Default 65,536 (64kb) */\n        public uint                stackSizeMixer;             /* [r/w] Optional. Specify 0 to ignore. Specify the stack size for the FMOD mixer thread.  Useful for custom dsps that use excess stack.  Default 49,152 (48kb) */\n        public DSP_RESAMPLER       resamplerMethod;            /* [r/w] Optional. Specify 0 to ignore. Resampling method used with fmod's software mixer.  See FMOD_DSP_RESAMPLER for details on methods. */\n        public uint                commandQueueSize;           /* [r/w] Optional. Specify 0 to ignore. Specify the command queue size for thread safe processing.  Default 2048 (2kb) */\n        public uint                randomSeed;                 /* [r/w] Optional. Specify 0 to ignore. Seed value that FMOD will use to initialize its internal random number generators. */\n    }\n\n    /*\n    [DEFINE]\n    [\n        [NAME]\n        FMOD_DRIVER_STATE\n\n        [DESCRIPTION]\n        Flags that provide additional information about a particular driver.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        System::getRecordDriverInfo\n    ]\n    */\n    [Flags]\n    public enum DRIVER_STATE : uint\n    {\n        CONNECTED = 0x00000001, /* Device is currently plugged in. */\n        DEFAULT   = 0x00000002, /* Device is the users preferred choice. */\n    }\n\n    /*\n        FMOD System factory functions.  Use this to create an FMOD System Instance.  below you will see System init/close to get started.\n    */\n    public class Factory\n    {\n\n        static Factory()\n        {\n            DllLoader.PreloadDll(VERSION.dll);\n        }\n\n        public static RESULT System_Create(out System system)\n        {\n            system = null;\n\n            RESULT result   = RESULT.OK;\n            IntPtr rawPtr   = new IntPtr();\n\n            result = FMOD_System_Create(out rawPtr);\n            if (result != RESULT.OK)\n            {\n                return result;\n            }\n\n            system = new System(rawPtr);\n\n            return result;\n        }\n\n\n        #region importfunctions\n\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Create                      (out IntPtr system);\n\n        #endregion\n    }\n\n    public class Memory\n    {\n        public static RESULT Initialize(IntPtr poolmem, int poollen, MEMORY_ALLOC_CALLBACK useralloc, MEMORY_REALLOC_CALLBACK userrealloc, MEMORY_FREE_CALLBACK userfree, MEMORY_TYPE memtypeflags)\n        {\n            return FMOD_Memory_Initialize(poolmem, poollen, useralloc, userrealloc, userfree, memtypeflags);\n        }\n\n        public static RESULT GetStats(out int currentalloced, out int maxalloced)\n        {\n            return GetStats(out currentalloced, out maxalloced, false);\n        }\n\n        public static RESULT GetStats(out int currentalloced, out int maxalloced, bool blocking)\n        {\n            return FMOD_Memory_GetStats(out currentalloced, out maxalloced, blocking);\n        }\n\n\n        #region importfunctions\n\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Memory_Initialize(IntPtr poolmem, int poollen, MEMORY_ALLOC_CALLBACK useralloc, MEMORY_REALLOC_CALLBACK userrealloc, MEMORY_FREE_CALLBACK userfree, MEMORY_TYPE memtypeflags);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Memory_GetStats(out int currentalloced, out int maxalloced, bool blocking);\n\n        #endregion\n    }\n\n    public class Debug\n    {\n        public static RESULT Initialize(DEBUG_FLAGS flags, DEBUG_MODE mode, DEBUG_CALLBACK callback, string filename)\n        {\n            return FMOD_Debug_Initialize(flags, mode, callback, filename);\n        }\n\n\n        #region importfunctions\n\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Debug_Initialize(DEBUG_FLAGS flags, DEBUG_MODE mode, DEBUG_CALLBACK callback, string filename);\n\n        #endregion\n    }\n\n    public class HandleBase\n    {\n        public HandleBase(IntPtr newPtr)\n        {\n            rawPtr = newPtr;\n        }\n\n        public bool isValid()\n        {\n            return rawPtr != IntPtr.Zero;\n        }\n\n        public IntPtr getRaw()\n        {\n            return rawPtr;\n        }\n\n        protected IntPtr rawPtr;\n\n        #region equality\n\n        public override bool Equals(Object obj)\n        {\n            return Equals(obj as HandleBase);\n        }\n        public bool Equals(HandleBase p)\n        {\n            // Equals if p not null and handle is the same\n            return ((object)p != null && rawPtr == p.rawPtr);\n        }\n        public override int GetHashCode()\n        {\n            return rawPtr.ToInt32();\n        }\n        public static bool operator ==(HandleBase a, HandleBase b)\n        {\n            // If both are null, or both are same instance, return true.\n            if (Object.ReferenceEquals(a, b))\n            {\n                return true;\n            }\n            // If one is null, but not both, return false.\n            if (((object)a == null) || ((object)b == null))\n            {\n                return false;\n            }\n            // Return true if the handle matches\n            return (a.rawPtr == b.rawPtr);\n        }\n        public static bool operator !=(HandleBase a, HandleBase b)\n        {\n            return !(a == b);\n        }\n        #endregion\n\n    }\n\n    /*\n        'System' API.\n    */\n    public class System : HandleBase\n    {\n        public RESULT release                ()\n        {\n            RESULT result = FMOD_System_Release(rawPtr);\n            if (result == RESULT.OK)\n            {\n                rawPtr = IntPtr.Zero;\n            }\n            return result;\n        }\n\n\n        // Pre-init functions.\n        public RESULT setOutput              (OUTPUTTYPE output)\n        {\n            return FMOD_System_SetOutput(rawPtr, output);\n        }\n        public RESULT getOutput              (out OUTPUTTYPE output)\n        {\n            return FMOD_System_GetOutput(rawPtr, out output);\n        }\n        public RESULT getNumDrivers          (out int numdrivers)\n        {\n            return FMOD_System_GetNumDrivers(rawPtr, out numdrivers);\n        }\n        public RESULT getDriverInfo          (int id, StringBuilder name, int namelen, out Guid guid, out int systemrate, out SPEAKERMODE speakermode, out int speakermodechannels)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(name.Capacity);\n\n            RESULT result = FMOD_System_GetDriverInfo(rawPtr, id, stringMem, namelen, out guid, out systemrate, out speakermode, out speakermodechannels);\n\n            StringMarshalHelper.NativeToBuilder(name, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT setDriver              (int driver)\n        {\n            return FMOD_System_SetDriver(rawPtr, driver);\n        }\n        public RESULT getDriver              (out int driver)\n        {\n            return FMOD_System_GetDriver(rawPtr, out driver);\n        }\n        public RESULT setSoftwareChannels    (int numsoftwarechannels)\n        {\n            return FMOD_System_SetSoftwareChannels(rawPtr, numsoftwarechannels);\n        }\n        public RESULT getSoftwareChannels    (out int numsoftwarechannels)\n        {\n            return FMOD_System_GetSoftwareChannels(rawPtr, out numsoftwarechannels);\n        }\n        public RESULT setSoftwareFormat      (int samplerate, SPEAKERMODE speakermode, int numrawspeakers)\n        {\n            return FMOD_System_SetSoftwareFormat(rawPtr, samplerate, speakermode, numrawspeakers);\n        }\n        public RESULT getSoftwareFormat      (out int samplerate, out SPEAKERMODE speakermode, out int numrawspeakers)\n        {\n            return FMOD_System_GetSoftwareFormat(rawPtr, out samplerate, out speakermode, out numrawspeakers);\n        }\n        public RESULT setDSPBufferSize       (uint bufferlength, int numbuffers)\n        {\n            return FMOD_System_SetDSPBufferSize(rawPtr, bufferlength, numbuffers);\n        }\n        public RESULT getDSPBufferSize       (out uint bufferlength, out int numbuffers)\n        {\n            return FMOD_System_GetDSPBufferSize(rawPtr, out bufferlength, out numbuffers);\n        }\n        public RESULT setFileSystem          (FILE_OPENCALLBACK useropen, FILE_CLOSECALLBACK userclose, FILE_READCALLBACK userread, FILE_SEEKCALLBACK userseek, FILE_ASYNCREADCALLBACK userasyncread, FILE_ASYNCCANCELCALLBACK userasynccancel, int blockalign)\n        {\n            return FMOD_System_SetFileSystem(rawPtr, useropen, userclose, userread, userseek, userasyncread, userasynccancel, blockalign);\n        }\n        public RESULT attachFileSystem       (FILE_OPENCALLBACK useropen, FILE_CLOSECALLBACK userclose, FILE_READCALLBACK userread, FILE_SEEKCALLBACK userseek)\n        {\n            return FMOD_System_AttachFileSystem(rawPtr, useropen, userclose, userread, userseek);\n        }\n        public RESULT setAdvancedSettings    (ref ADVANCEDSETTINGS settings)\n        {\n            settings.cbSize = Marshal.SizeOf(settings);\n            return FMOD_System_SetAdvancedSettings(rawPtr, ref settings);\n        }\n        public RESULT getAdvancedSettings    (ref ADVANCEDSETTINGS settings)\n        {\n            settings.cbSize = Marshal.SizeOf(settings);\n            return FMOD_System_GetAdvancedSettings(rawPtr, ref settings);\n        }\n        public RESULT setCallback            (SYSTEM_CALLBACK callback, SYSTEM_CALLBACK_TYPE callbackmask)\n        {\n            return FMOD_System_SetCallback(rawPtr, callback, callbackmask);\n        }\n\n        // Plug-in support.\n        public RESULT setPluginPath          (string path)\n        {\n            return FMOD_System_SetPluginPath(rawPtr, Encoding.UTF8.GetBytes(path + Char.MinValue));\n        }\n        public RESULT loadPlugin             (string filename, out uint handle, uint priority)\n        {\n            return FMOD_System_LoadPlugin(rawPtr, Encoding.UTF8.GetBytes(filename + Char.MinValue), out handle, priority);\n        }\n        public RESULT loadPlugin             (string filename, out uint handle)\n        {\n            return loadPlugin(filename, out handle, 0);\n        }\n        public RESULT unloadPlugin           (uint handle)\n        {\n            return FMOD_System_UnloadPlugin(rawPtr, handle);\n        }\n        public RESULT getNumPlugins          (PLUGINTYPE plugintype, out int numplugins)\n        {\n            return FMOD_System_GetNumPlugins(rawPtr, plugintype, out numplugins);\n        }\n        public RESULT getPluginHandle        (PLUGINTYPE plugintype, int index, out uint handle)\n        {\n            return FMOD_System_GetPluginHandle(rawPtr, plugintype, index, out handle);\n        }\n        public RESULT getPluginInfo          (uint handle, out PLUGINTYPE plugintype, StringBuilder name, int namelen, out uint version)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(name.Capacity);\n\n            RESULT result = FMOD_System_GetPluginInfo(rawPtr, handle, out plugintype, stringMem, namelen, out version);\n\n            StringMarshalHelper.NativeToBuilder(name, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT setOutputByPlugin      (uint handle)\n        {\n            return FMOD_System_SetOutputByPlugin(rawPtr, handle);\n        }\n        public RESULT getOutputByPlugin      (out uint handle)\n        {\n            return FMOD_System_GetOutputByPlugin(rawPtr, out handle);\n        }\n        public RESULT createDSPByPlugin(uint handle, out DSP dsp)\n        {\n            dsp = null;\n\n            IntPtr dspraw;\n            RESULT result = FMOD_System_CreateDSPByPlugin(rawPtr, handle, out dspraw);\n            dsp = new DSP(dspraw);\n\n            return result;\n        }\n        public RESULT getDSPInfoByPlugin(uint handle, out IntPtr description)\n        {\n            return FMOD_System_GetDSPInfoByPlugin(rawPtr, handle, out description);\n        }\n        /*\n        public RESULT registerCodec(ref CODEC_DESCRIPTION description, out uint handle, uint priority)\n        {\n            return FMOD_System_RegisterCodec(rawPtr, ref description, out handle, priority);\n        }\n        */\n        public RESULT registerDSP(ref DSP_DESCRIPTION description, out uint handle)\n        {\n            return FMOD_System_RegisterDSP(rawPtr, ref description, out handle);\n        }\n        /*\n        public RESULT registerOutput(ref OUTPUT_DESCRIPTION description, out uint handle)\n        {\n            return FMOD_System_RegisterOutput(rawPtr, ref description, out handle);\n        }\n        */\n\n        // Init/Close.\n        public RESULT init                   (int maxchannels, INITFLAGS flags, IntPtr extradriverdata)\n        {\n            return FMOD_System_Init(rawPtr, maxchannels, flags, extradriverdata);\n        }\n        public RESULT close                  ()\n        {\n            return FMOD_System_Close(rawPtr);\n        }\n\n\n        // General post-init system functions.\n        public RESULT update                 ()\n        {\n            return FMOD_System_Update(rawPtr);\n        }\n\n        public RESULT setSpeakerPosition(SPEAKER speaker, float x, float y, bool active)\n        {\n            return FMOD_System_SetSpeakerPosition(rawPtr, speaker, x, y, active);\n        }\n        public RESULT getSpeakerPosition(SPEAKER speaker, out float x, out float y, out bool active)\n        {\n            return FMOD_System_GetSpeakerPosition(rawPtr, speaker, out x, out y, out active);\n        }\n        public RESULT setStreamBufferSize(uint filebuffersize, TIMEUNIT filebuffersizetype)\n        {\n            return FMOD_System_SetStreamBufferSize(rawPtr, filebuffersize, filebuffersizetype);\n        }\n        public RESULT getStreamBufferSize(out uint filebuffersize, out TIMEUNIT filebuffersizetype)\n        {\n            return FMOD_System_GetStreamBufferSize(rawPtr, out filebuffersize, out filebuffersizetype);\n        }\n        public RESULT set3DSettings          (float dopplerscale, float distancefactor, float rolloffscale)\n        {\n            return FMOD_System_Set3DSettings(rawPtr, dopplerscale, distancefactor, rolloffscale);\n        }\n        public RESULT get3DSettings          (out float dopplerscale, out float distancefactor, out float rolloffscale)\n        {\n            return FMOD_System_Get3DSettings(rawPtr, out dopplerscale, out distancefactor, out rolloffscale);\n        }\n        public RESULT set3DNumListeners      (int numlisteners)\n        {\n            return FMOD_System_Set3DNumListeners(rawPtr, numlisteners);\n        }\n        public RESULT get3DNumListeners      (out int numlisteners)\n        {\n            return FMOD_System_Get3DNumListeners(rawPtr, out numlisteners);\n        }\n        public RESULT set3DListenerAttributes(int listener, ref VECTOR pos, ref VECTOR vel, ref VECTOR forward, ref VECTOR up)\n        {\n            return FMOD_System_Set3DListenerAttributes(rawPtr, listener, ref pos, ref vel, ref forward, ref up);\n        }\n        public RESULT get3DListenerAttributes(int listener, out VECTOR pos, out VECTOR vel, out VECTOR forward, out VECTOR up)\n        {\n            return FMOD_System_Get3DListenerAttributes(rawPtr, listener, out pos, out vel, out forward, out up);\n        }\n        public RESULT set3DRolloffCallback   (CB_3D_ROLLOFFCALLBACK callback)\n        {\n            return FMOD_System_Set3DRolloffCallback   (rawPtr, callback);\n        }\n        public RESULT mixerSuspend           ()\n        {\n            return FMOD_System_MixerSuspend(rawPtr);\n        }\n        public RESULT mixerResume            ()\n        {\n            return FMOD_System_MixerResume(rawPtr);\n        }\n        public RESULT getDefaultMixMatrix    (SPEAKERMODE sourcespeakermode, SPEAKERMODE targetspeakermode, float[] matrix, int matrixhop)\n        {\n            return FMOD_System_GetDefaultMixMatrix(rawPtr, sourcespeakermode, targetspeakermode, matrix, matrixhop);\n        }\n        public RESULT getSpeakerModeChannels (SPEAKERMODE mode, out int channels)\n        {\n            return FMOD_System_GetSpeakerModeChannels(rawPtr, mode, out channels);\n        }\n\n        // System information functions.\n        public RESULT getVersion             (out uint version)\n        {\n            return FMOD_System_GetVersion(rawPtr, out version);\n        }\n        public RESULT getOutputHandle        (out IntPtr handle)\n        {\n            return FMOD_System_GetOutputHandle(rawPtr, out handle);\n        }\n        public RESULT getChannelsPlaying     (out int channels)\n        {\n            return FMOD_System_GetChannelsPlaying(rawPtr, out channels);\n        }\n        public RESULT getChannelsReal        (out int channels)\n        {\n            return FMOD_System_GetChannelsReal(rawPtr, out channels);\n        }\n        public RESULT getCPUUsage            (out float dsp, out float stream, out float geometry, out float update, out float total)\n        {\n            return FMOD_System_GetCPUUsage(rawPtr, out dsp, out stream, out geometry, out update, out total);\n        }\n        public RESULT getSoundRAM            (out int currentalloced, out int maxalloced, out int total)\n        {\n            return FMOD_System_GetSoundRAM(rawPtr, out currentalloced, out maxalloced, out total);\n        }\n\n        // Sound/DSP/Channel/FX creation and retrieval.\n        public RESULT createSound            (string name, MODE mode, ref CREATESOUNDEXINFO exinfo, out Sound sound)\n        {\n            sound = null;\n\n            byte[] stringData;\n            stringData = Encoding.UTF8.GetBytes(name + Char.MinValue);\n            \n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n\n            IntPtr soundraw;\n            RESULT result = FMOD_System_CreateSound(rawPtr, stringData, mode, ref exinfo, out soundraw);\n            sound = new Sound(soundraw);\n\n            return result;\n        }\n        public RESULT createSound            (byte[] data, MODE mode, ref CREATESOUNDEXINFO exinfo, out Sound sound)\n        {\n            sound = null;\n\n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n\n            IntPtr soundraw;\n            RESULT result = FMOD_System_CreateSound(rawPtr, data, mode, ref exinfo, out soundraw);\n            sound = new Sound(soundraw);\n\n            return result;\n        }\n        public RESULT createSound            (string name, MODE mode, out Sound sound)\n        {\n            CREATESOUNDEXINFO exinfo = new CREATESOUNDEXINFO();\n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n\n            return createSound(name, mode, ref exinfo, out sound);\n        }\n        public RESULT createStream            (string name, MODE mode, ref CREATESOUNDEXINFO exinfo, out Sound sound)\n        {\n            sound = null;\n\n            byte[] stringData;\n            stringData = Encoding.UTF8.GetBytes(name + Char.MinValue);\n            \n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n\n            IntPtr soundraw;\n            RESULT result = FMOD_System_CreateStream(rawPtr, stringData, mode, ref exinfo, out soundraw);\n            sound = new Sound(soundraw);\n\n            return result;\n        }\n        public RESULT createStream            (byte[] data, MODE mode, ref CREATESOUNDEXINFO exinfo, out Sound sound)\n        {\n            sound = null;\n\n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n\n            IntPtr soundraw;\n            RESULT result = FMOD_System_CreateStream(rawPtr, data, mode, ref exinfo, out soundraw);\n            sound = new Sound(soundraw);\n\n            return result;\n        }\n        public RESULT createStream            (string name, MODE mode, out Sound sound)\n        {\n            CREATESOUNDEXINFO exinfo = new CREATESOUNDEXINFO();\n            exinfo.cbsize = Marshal.SizeOf(exinfo);\n\n            return createStream(name, mode, ref exinfo, out sound);\n        }\n        public RESULT createDSP              (ref DSP_DESCRIPTION description, out DSP dsp)\n        {\n            dsp = null;\n\n            IntPtr dspraw;\n            RESULT result = FMOD_System_CreateDSP(rawPtr, ref description, out dspraw);\n            dsp = new DSP(dspraw);\n\n            return result;\n        }\n        public RESULT createDSPByType          (DSP_TYPE type, out DSP dsp)\n        {\n            dsp = null;\n\n            IntPtr dspraw;\n            RESULT result = FMOD_System_CreateDSPByType(rawPtr, type, out dspraw);\n            dsp = new DSP(dspraw);\n\n            return result;\n        }\n        public RESULT createChannelGroup     (string name, out ChannelGroup channelgroup)\n        {\n            channelgroup = null;\n\n            byte[] stringData = Encoding.UTF8.GetBytes(name + Char.MinValue);\n\n            IntPtr channelgroupraw;\n            RESULT result = FMOD_System_CreateChannelGroup(rawPtr, stringData, out channelgroupraw);\n            channelgroup = new ChannelGroup(channelgroupraw);\n\n            return result;\n        }\n        public RESULT createSoundGroup       (string name, out SoundGroup soundgroup)\n        {\n            soundgroup = null;\n\n            byte[] stringData = Encoding.UTF8.GetBytes(name + Char.MinValue);\n\n            IntPtr soundgroupraw;\n            RESULT result = FMOD_System_CreateSoundGroup(rawPtr, stringData, out soundgroupraw);\n            soundgroup = new SoundGroup(soundgroupraw);\n\n            return result;\n        }\n        public RESULT createReverb3D         (out Reverb3D reverb)\n        {\n            IntPtr reverbraw;\n            RESULT result = FMOD_System_CreateReverb3D(rawPtr, out reverbraw);\n            reverb = new Reverb3D(reverbraw);\n\n            return result;\n        }\n        public RESULT playSound              (Sound sound, ChannelGroup channelGroup, bool paused, out Channel channel)\n        {\n            channel = null;\n\n            IntPtr channelGroupRaw = (channelGroup != null) ? channelGroup.getRaw() : IntPtr.Zero;\n\n            IntPtr channelraw;\n            RESULT result = FMOD_System_PlaySound(rawPtr, sound.getRaw(), channelGroupRaw, paused, out channelraw);\n            channel = new Channel(channelraw);\n\n            return result;\n        }\n        public RESULT playDSP                (DSP dsp, ChannelGroup channelGroup, bool paused, out Channel channel)\n        {\n            channel = null;\n\n            IntPtr channelGroupRaw = (channelGroup != null) ? channelGroup.getRaw() : IntPtr.Zero;\n\n            IntPtr channelraw;\n            RESULT result = FMOD_System_PlayDSP(rawPtr, dsp.getRaw(), channelGroupRaw, paused, out channelraw);\n            channel = new Channel(channelraw);\n\n            return result;\n        }\n        public RESULT getChannel             (int channelid, out Channel channel)\n        {\n            channel = null;\n\n            IntPtr channelraw;\n            RESULT result = FMOD_System_GetChannel(rawPtr, channelid, out channelraw);\n            channel = new Channel(channelraw);\n\n            return result;\n        }\n        public RESULT getMasterChannelGroup  (out ChannelGroup channelgroup)\n        {\n            channelgroup = null;\n\n            IntPtr channelgroupraw;\n            RESULT result = FMOD_System_GetMasterChannelGroup(rawPtr, out channelgroupraw);\n            channelgroup = new ChannelGroup(channelgroupraw);\n\n            return result;\n        }\n        public RESULT getMasterSoundGroup    (out SoundGroup soundgroup)\n        {\n            soundgroup = null;\n\n            IntPtr soundgroupraw;\n            RESULT result = FMOD_System_GetMasterSoundGroup(rawPtr, out soundgroupraw);\n            soundgroup = new SoundGroup(soundgroupraw);\n\n            return result;\n        }\n\n        // Routing to ports.\n        public RESULT attachChannelGroupToPort(uint portType, ulong portIndex, ChannelGroup channelgroup, bool passThru = false)\n        {\n            return FMOD_System_AttachChannelGroupToPort(rawPtr, portType, portIndex, channelgroup.getRaw(), passThru);\n        }\n        public RESULT detachChannelGroupFromPort(ChannelGroup channelgroup)\n        {\n            return FMOD_System_DetachChannelGroupFromPort(rawPtr, channelgroup.getRaw());\n        }\n\n        // Reverb api.\n        public RESULT setReverbProperties    (int instance, ref REVERB_PROPERTIES prop)\n        {\n            return FMOD_System_SetReverbProperties(rawPtr, instance, ref prop);\n        }\n        public RESULT getReverbProperties    (int instance, out REVERB_PROPERTIES prop)\n        {\n            return FMOD_System_GetReverbProperties(rawPtr, instance, out prop);\n        }\n\n        // System level DSP functionality.\n        public RESULT lockDSP            ()\n        {\n            return FMOD_System_LockDSP(rawPtr);\n        }\n        public RESULT unlockDSP          ()\n        {\n            return FMOD_System_UnlockDSP(rawPtr);\n        }\n\n        // Recording api\n        public RESULT getRecordNumDrivers    (out int numdrivers, out int numconnected)\n        {\n            return FMOD_System_GetRecordNumDrivers(rawPtr, out numdrivers, out numconnected);\n        }\n        public RESULT getRecordDriverInfo(int id, StringBuilder name, int namelen, out Guid guid, out int systemrate, out SPEAKERMODE speakermode, out int speakermodechannels, out DRIVER_STATE state)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(name.Capacity);\n\n            RESULT result = FMOD_System_GetRecordDriverInfo(rawPtr, id, stringMem, namelen, out guid, out systemrate, out speakermode, out speakermodechannels, out state);\n\n            StringMarshalHelper.NativeToBuilder(name, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT getRecordPosition      (int id, out uint position)\n        {\n            return FMOD_System_GetRecordPosition(rawPtr, id, out position);\n        }\n        public RESULT recordStart            (int id, Sound sound, bool loop)\n        {\n            return FMOD_System_RecordStart(rawPtr, id, sound.getRaw(), loop);\n        }\n        public RESULT recordStop             (int id)\n        {\n            return FMOD_System_RecordStop(rawPtr, id);\n        }\n        public RESULT isRecording            (int id, out bool recording)\n        {\n            return FMOD_System_IsRecording(rawPtr, id, out recording);\n        }\n\n        // Geometry api\n        public RESULT createGeometry         (int maxpolygons, int maxvertices, out Geometry geometry)\n        {\n            geometry = null;\n\n            IntPtr geometryraw;\n            RESULT result = FMOD_System_CreateGeometry(rawPtr, maxpolygons, maxvertices, out geometryraw);\n            geometry = new Geometry(geometryraw);\n\n            return result;\n        }\n        public RESULT setGeometrySettings    (float maxworldsize)\n        {\n            return FMOD_System_SetGeometrySettings(rawPtr, maxworldsize);\n        }\n        public RESULT getGeometrySettings    (out float maxworldsize)\n        {\n            return FMOD_System_GetGeometrySettings(rawPtr, out maxworldsize);\n        }\n        public RESULT loadGeometry(IntPtr data, int datasize, out Geometry geometry)\n        {\n            geometry = null;\n\n            IntPtr geometryraw;\n            RESULT result = FMOD_System_LoadGeometry(rawPtr, data, datasize, out geometryraw);\n            geometry = new Geometry(geometryraw);\n\n            return result;\n        }\n        public RESULT getGeometryOcclusion    (ref VECTOR listener, ref VECTOR source, out float direct, out float reverb)\n        {\n            return FMOD_System_GetGeometryOcclusion(rawPtr, ref listener, ref source, out direct, out reverb);\n        }\n\n        // Network functions\n        public RESULT setNetworkProxy               (string proxy)\n        {\n            return FMOD_System_SetNetworkProxy(rawPtr, Encoding.UTF8.GetBytes(proxy + Char.MinValue));\n        }\n        public RESULT getNetworkProxy               (StringBuilder proxy, int proxylen)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(proxy.Capacity);\n\n            RESULT result = FMOD_System_GetNetworkProxy(rawPtr, stringMem, proxylen);\n\n            StringMarshalHelper.NativeToBuilder(proxy, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT setNetworkTimeout      (int timeout)\n        {\n            return FMOD_System_SetNetworkTimeout(rawPtr, timeout);\n        }\n        public RESULT getNetworkTimeout(out int timeout)\n        {\n            return FMOD_System_GetNetworkTimeout(rawPtr, out timeout);\n        }\n\n        // Userdata set/get\n        public RESULT setUserData            (IntPtr userdata)\n        {\n            return FMOD_System_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData            (out IntPtr userdata)\n        {\n            return FMOD_System_GetUserData(rawPtr, out userdata);\n        }\n\n\n        #region importfunctions\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Release                (IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetOutput              (IntPtr system, OUTPUTTYPE output);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetOutput              (IntPtr system, out OUTPUTTYPE output);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetNumDrivers          (IntPtr system, out int numdrivers);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetDriverInfo          (IntPtr system, int id, IntPtr name, int namelen, out Guid guid, out int systemrate, out SPEAKERMODE speakermode, out int speakermodechannels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetDriver              (IntPtr system, int driver);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetDriver              (IntPtr system, out int driver);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetSoftwareChannels    (IntPtr system, int numsoftwarechannels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetSoftwareChannels    (IntPtr system, out int numsoftwarechannels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetSoftwareFormat      (IntPtr system, int samplerate, SPEAKERMODE speakermode, int numrawspeakers);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetSoftwareFormat      (IntPtr system, out int samplerate, out SPEAKERMODE speakermode, out int numrawspeakers);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetDSPBufferSize       (IntPtr system, uint bufferlength, int numbuffers);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetDSPBufferSize       (IntPtr system, out uint bufferlength, out int numbuffers);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetFileSystem          (IntPtr system, FILE_OPENCALLBACK useropen, FILE_CLOSECALLBACK userclose, FILE_READCALLBACK userread, FILE_SEEKCALLBACK userseek, FILE_ASYNCREADCALLBACK userasyncread, FILE_ASYNCCANCELCALLBACK userasynccancel, int blockalign);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_AttachFileSystem       (IntPtr system, FILE_OPENCALLBACK useropen, FILE_CLOSECALLBACK userclose, FILE_READCALLBACK userread, FILE_SEEKCALLBACK userseek);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetPluginPath          (IntPtr system, byte[] path);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_LoadPlugin             (IntPtr system, byte[] filename, out uint handle, uint priority);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_UnloadPlugin           (IntPtr system, uint handle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetNumPlugins          (IntPtr system, PLUGINTYPE plugintype, out int numplugins);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetPluginHandle        (IntPtr system, PLUGINTYPE plugintype, int index, out uint handle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetPluginInfo          (IntPtr system, uint handle, out PLUGINTYPE plugintype, IntPtr name, int namelen, out uint version);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateDSPByPlugin      (IntPtr system, uint handle, out IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetOutputByPlugin      (IntPtr system, uint handle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetOutputByPlugin      (IntPtr system, out uint handle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetDSPInfoByPlugin     (IntPtr system, uint handle, out IntPtr description);\n        [DllImport(VERSION.dll)]\n        //private static extern RESULT FMOD_System_RegisterCodec          (IntPtr system, out CODEC_DESCRIPTION description, out uint handle, uint priority);\n        //[DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_RegisterDSP            (IntPtr system, ref DSP_DESCRIPTION description, out uint handle);\n        [DllImport(VERSION.dll)]\n        //private static extern RESULT FMOD_System_RegisterOutput         (IntPtr system, ref OUTPUT_DESCRIPTION description, out uint handle);\n        //[DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Init                   (IntPtr system, int maxchannels, INITFLAGS flags, IntPtr extradriverdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Close                  (IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Update                 (IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetAdvancedSettings    (IntPtr system, ref ADVANCEDSETTINGS settings);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetAdvancedSettings    (IntPtr system, ref ADVANCEDSETTINGS settings);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Set3DRolloffCallback   (IntPtr system, CB_3D_ROLLOFFCALLBACK callback);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_MixerSuspend           (IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_MixerResume            (IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetDefaultMixMatrix    (IntPtr system, SPEAKERMODE sourcespeakermode, SPEAKERMODE targetspeakermode, float[] matrix, int matrixhop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetSpeakerModeChannels (IntPtr system, SPEAKERMODE mode, out int channels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetCallback            (IntPtr system, SYSTEM_CALLBACK callback, SYSTEM_CALLBACK_TYPE callbackmask);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetSpeakerPosition     (IntPtr system, SPEAKER speaker, float x, float y, bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetSpeakerPosition     (IntPtr system, SPEAKER speaker, out float x, out float y, out bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Set3DSettings          (IntPtr system, float dopplerscale, float distancefactor, float rolloffscale);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Get3DSettings          (IntPtr system, out float dopplerscale, out float distancefactor, out float rolloffscale);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Set3DNumListeners      (IntPtr system, int numlisteners);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Get3DNumListeners      (IntPtr system, out int numlisteners);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Set3DListenerAttributes(IntPtr system, int listener, ref VECTOR pos, ref VECTOR vel, ref VECTOR forward, ref VECTOR up);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_Get3DListenerAttributes(IntPtr system, int listener, out VECTOR pos, out VECTOR vel, out VECTOR forward, out VECTOR up);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetStreamBufferSize    (IntPtr system, uint filebuffersize, TIMEUNIT filebuffersizetype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetStreamBufferSize    (IntPtr system, out uint filebuffersize, out TIMEUNIT filebuffersizetype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetVersion             (IntPtr system, out uint version);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetOutputHandle        (IntPtr system, out IntPtr handle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetChannelsPlaying     (IntPtr system, out int channels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetChannelsReal        (IntPtr system, out int channels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetCPUUsage            (IntPtr system, out float dsp, out float stream, out float geometry, out float update, out float total);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetSoundRAM            (IntPtr system, out int currentalloced, out int maxalloced, out int total);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateSound            (IntPtr system, byte[] name_or_data, MODE mode, ref CREATESOUNDEXINFO exinfo, out IntPtr sound);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateStream           (IntPtr system, byte[] name_or_data, MODE mode, ref CREATESOUNDEXINFO exinfo, out IntPtr sound);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateDSP              (IntPtr system, ref DSP_DESCRIPTION description, out IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateDSPByType        (IntPtr system, DSP_TYPE type, out IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateChannelGroup     (IntPtr system, byte[] name, out IntPtr channelgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateSoundGroup       (IntPtr system, byte[] name, out IntPtr soundgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateReverb3D         (IntPtr system, out IntPtr reverb);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_PlaySound              (IntPtr system, IntPtr sound, IntPtr channelGroup, bool paused, out IntPtr channel);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_PlayDSP                (IntPtr system, IntPtr dsp, IntPtr channelGroup, bool paused, out IntPtr channel);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetChannel             (IntPtr system, int channelid, out IntPtr channel);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetMasterChannelGroup  (IntPtr system, out IntPtr channelgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetMasterSoundGroup    (IntPtr system, out IntPtr soundgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_AttachChannelGroupToPort  (IntPtr system, uint portType, ulong portIndex, IntPtr channelgroup, bool passThru);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_DetachChannelGroupFromPort(IntPtr system, IntPtr channelgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetReverbProperties    (IntPtr system, int instance, ref REVERB_PROPERTIES prop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetReverbProperties    (IntPtr system, int instance, out REVERB_PROPERTIES prop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_LockDSP                (IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_UnlockDSP              (IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetRecordNumDrivers    (IntPtr system, out int numdrivers, out int numconnected);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetRecordDriverInfo    (IntPtr system, int id, IntPtr name, int namelen, out Guid guid, out int systemrate, out SPEAKERMODE speakermode, out int speakermodechannels, out DRIVER_STATE state);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetRecordPosition      (IntPtr system, int id, out uint position);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_RecordStart            (IntPtr system, int id, IntPtr sound, bool loop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_RecordStop             (IntPtr system, int id);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_IsRecording            (IntPtr system, int id, out bool recording);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_CreateGeometry         (IntPtr system, int maxpolygons, int maxvertices, out IntPtr geometry);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetGeometrySettings    (IntPtr system, float maxworldsize);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetGeometrySettings    (IntPtr system, out float maxworldsize);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_LoadGeometry           (IntPtr system, IntPtr data, int datasize, out IntPtr geometry);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetGeometryOcclusion   (IntPtr system, ref VECTOR listener, ref VECTOR source, out float direct, out float reverb);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetNetworkProxy        (IntPtr system, byte[] proxy);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetNetworkProxy        (IntPtr system, IntPtr proxy, int proxylen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetNetworkTimeout      (IntPtr system, int timeout);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetNetworkTimeout      (IntPtr system, out int timeout);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_SetUserData            (IntPtr system, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_System_GetUserData            (IntPtr system, out IntPtr userdata);\n        #endregion\n\n        #region wrapperinternal\n\n        public System(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'Sound' API.\n    */\n    public class Sound : HandleBase\n    {\n        public RESULT release                 ()\n        {\n            RESULT result = FMOD_Sound_Release(rawPtr);\n            if (result == RESULT.OK)\n            {\n                rawPtr = IntPtr.Zero;\n            }\n            return result;\n        }\n        public RESULT getSystemObject         (out System system)\n        {\n            system = null;\n\n            IntPtr systemraw;\n            RESULT result = FMOD_Sound_GetSystemObject(rawPtr, out systemraw);\n            system = new System(systemraw);\n\n            return result;\n        }\n\n        // Standard sound manipulation functions.\n        public RESULT @lock                   (uint offset, uint length, out IntPtr ptr1, out IntPtr ptr2, out uint len1, out uint len2)\n        {\n            return FMOD_Sound_Lock(rawPtr, offset, length, out ptr1, out ptr2, out len1, out len2);\n        }\n        public RESULT unlock                  (IntPtr ptr1,  IntPtr ptr2, uint len1, uint len2)\n        {\n            return FMOD_Sound_Unlock(rawPtr, ptr1, ptr2, len1, len2);\n        }\n        public RESULT setDefaults             (float frequency, int priority)\n        {\n            return FMOD_Sound_SetDefaults(rawPtr, frequency, priority);\n        }\n        public RESULT getDefaults             (out float frequency, out int priority)\n        {\n            return FMOD_Sound_GetDefaults(rawPtr, out frequency, out priority);\n        }\n        public RESULT set3DMinMaxDistance     (float min, float max)\n        {\n            return FMOD_Sound_Set3DMinMaxDistance(rawPtr, min, max);\n        }\n        public RESULT get3DMinMaxDistance     (out float min, out float max)\n        {\n            return FMOD_Sound_Get3DMinMaxDistance(rawPtr, out min, out max);\n        }\n        public RESULT set3DConeSettings       (float insideconeangle, float outsideconeangle, float outsidevolume)\n        {\n            return FMOD_Sound_Set3DConeSettings(rawPtr, insideconeangle, outsideconeangle, outsidevolume);\n        }\n        public RESULT get3DConeSettings       (out float insideconeangle, out float outsideconeangle, out float outsidevolume)\n        {\n            return FMOD_Sound_Get3DConeSettings(rawPtr, out insideconeangle, out outsideconeangle, out outsidevolume);\n        }\n        public RESULT set3DCustomRolloff      (ref VECTOR points, int numpoints)\n        {\n            return FMOD_Sound_Set3DCustomRolloff(rawPtr, ref points, numpoints);\n        }\n        public RESULT get3DCustomRolloff      (out IntPtr points, out int numpoints)\n        {\n            return FMOD_Sound_Get3DCustomRolloff(rawPtr, out points, out numpoints);\n        }\n        public RESULT getSubSound             (int index, out Sound subsound)\n        {\n            subsound = null;\n\n            IntPtr subsoundraw;\n            RESULT result = FMOD_Sound_GetSubSound(rawPtr, index, out subsoundraw);\n            subsound = new Sound(subsoundraw);\n\n            return result;\n        }\n        public RESULT getSubSoundParent(out Sound parentsound)\n        {\n            parentsound = null;\n\n            IntPtr subsoundraw;\n            RESULT result = FMOD_Sound_GetSubSoundParent(rawPtr, out subsoundraw);\n            parentsound = new Sound(subsoundraw);\n\n            return result;\n        }\n        public RESULT getName                 (StringBuilder name, int namelen)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(name.Capacity);\n\n            RESULT result = FMOD_Sound_GetName(rawPtr, stringMem, namelen);\n\n            StringMarshalHelper.NativeToBuilder(name, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT getLength               (out uint length, TIMEUNIT lengthtype)\n        {\n            return FMOD_Sound_GetLength(rawPtr, out length, lengthtype);\n        }\n        public RESULT getFormat               (out SOUND_TYPE type, out SOUND_FORMAT format, out int channels, out int bits)\n        {\n            return FMOD_Sound_GetFormat(rawPtr, out type, out format, out channels, out bits);\n        }\n        public RESULT getNumSubSounds         (out int numsubsounds)\n        {\n            return FMOD_Sound_GetNumSubSounds(rawPtr, out numsubsounds);\n        }\n        public RESULT getNumTags              (out int numtags, out int numtagsupdated)\n        {\n            return FMOD_Sound_GetNumTags(rawPtr, out numtags, out numtagsupdated);\n        }\n        public RESULT getTag                  (string name, int index, out TAG tag)\n        {\n            return FMOD_Sound_GetTag(rawPtr, name, index, out tag);\n        }\n        public RESULT getOpenState            (out OPENSTATE openstate, out uint percentbuffered, out bool starving, out bool diskbusy)\n        {\n            return FMOD_Sound_GetOpenState(rawPtr, out openstate, out percentbuffered, out starving, out diskbusy);\n        }\n        public RESULT readData                (IntPtr buffer, uint lenbytes, out uint read)\n        {\n            return FMOD_Sound_ReadData(rawPtr, buffer, lenbytes, out read);\n        }\n        public RESULT seekData                (uint pcm)\n        {\n            return FMOD_Sound_SeekData(rawPtr, pcm);\n        }\n        public RESULT setSoundGroup           (SoundGroup soundgroup)\n        {\n            return FMOD_Sound_SetSoundGroup(rawPtr, soundgroup.getRaw());\n        }\n        public RESULT getSoundGroup           (out SoundGroup soundgroup)\n        {\n            soundgroup = null;\n\n            IntPtr soundgroupraw;\n            RESULT result = FMOD_Sound_GetSoundGroup(rawPtr, out soundgroupraw);\n            soundgroup = new SoundGroup(soundgroupraw);\n\n            return result;\n        }\n\n        // Synchronization point API.  These points can come from markers embedded in wav files, and can also generate channel callbacks.\n        public RESULT getNumSyncPoints        (out int numsyncpoints)\n        {\n            return FMOD_Sound_GetNumSyncPoints(rawPtr, out numsyncpoints);\n        }\n        public RESULT getSyncPoint            (int index, out IntPtr point)\n        {\n            return FMOD_Sound_GetSyncPoint(rawPtr, index, out point);\n        }\n        public RESULT getSyncPointInfo        (IntPtr point, StringBuilder name, int namelen, out uint offset, TIMEUNIT offsettype)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(name.Capacity);\n\n            RESULT result = FMOD_Sound_GetSyncPointInfo(rawPtr, point, stringMem, namelen, out offset, offsettype);\n\n            StringMarshalHelper.NativeToBuilder(name, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT addSyncPoint            (uint offset, TIMEUNIT offsettype, string name, out IntPtr point)\n        {\n            return FMOD_Sound_AddSyncPoint(rawPtr, offset, offsettype, name, out point);\n        }\n        public RESULT deleteSyncPoint         (IntPtr point)\n        {\n            return FMOD_Sound_DeleteSyncPoint(rawPtr, point);\n        }\n\n        // Functions also in Channel class but here they are the 'default' to save having to change it in Channel all the time.\n        public RESULT setMode                 (MODE mode)\n        {\n            return FMOD_Sound_SetMode(rawPtr, mode);\n        }\n        public RESULT getMode                 (out MODE mode)\n        {\n            return FMOD_Sound_GetMode(rawPtr, out mode);\n        }\n        public RESULT setLoopCount            (int loopcount)\n        {\n            return FMOD_Sound_SetLoopCount(rawPtr, loopcount);\n        }\n        public RESULT getLoopCount            (out int loopcount)\n        {\n            return FMOD_Sound_GetLoopCount(rawPtr, out loopcount);\n        }\n        public RESULT setLoopPoints           (uint loopstart, TIMEUNIT loopstarttype, uint loopend, TIMEUNIT loopendtype)\n        {\n            return FMOD_Sound_SetLoopPoints(rawPtr, loopstart, loopstarttype, loopend, loopendtype);\n        }\n        public RESULT getLoopPoints           (out uint loopstart, TIMEUNIT loopstarttype, out uint loopend, TIMEUNIT loopendtype)\n        {\n            return FMOD_Sound_GetLoopPoints(rawPtr, out loopstart, loopstarttype, out loopend, loopendtype);\n        }\n\n        // For MOD/S3M/XM/IT/MID sequenced formats only.\n        public RESULT getMusicNumChannels     (out int numchannels)\n        {\n            return FMOD_Sound_GetMusicNumChannels(rawPtr, out numchannels);\n        }\n        public RESULT setMusicChannelVolume   (int channel, float volume)\n        {\n            return FMOD_Sound_SetMusicChannelVolume(rawPtr, channel, volume);\n        }\n        public RESULT getMusicChannelVolume   (int channel, out float volume)\n        {\n            return FMOD_Sound_GetMusicChannelVolume(rawPtr, channel, out volume);\n        }\n        public RESULT setMusicSpeed(float speed)\n        {\n            return FMOD_Sound_SetMusicSpeed(rawPtr, speed);\n        }\n        public RESULT getMusicSpeed(out float speed)\n        {\n            return FMOD_Sound_GetMusicSpeed(rawPtr, out speed);\n        }\n\n        // Userdata set/get.\n        public RESULT setUserData             (IntPtr userdata)\n        {\n            return FMOD_Sound_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData             (out IntPtr userdata)\n        {\n            return FMOD_Sound_GetUserData(rawPtr, out userdata);\n        }\n\n\n        #region importfunctions\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Release                 (IntPtr sound);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetSystemObject         (IntPtr sound, out IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Lock                   (IntPtr sound, uint offset, uint length, out IntPtr ptr1, out IntPtr ptr2, out uint len1, out uint len2);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Unlock                  (IntPtr sound, IntPtr ptr1,  IntPtr ptr2, uint len1, uint len2);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetDefaults             (IntPtr sound, float frequency, int priority);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetDefaults             (IntPtr sound, out float frequency, out int priority);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Set3DMinMaxDistance     (IntPtr sound, float min, float max);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Get3DMinMaxDistance     (IntPtr sound, out float min, out float max);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Set3DConeSettings       (IntPtr sound, float insideconeangle, float outsideconeangle, float outsidevolume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Get3DConeSettings       (IntPtr sound, out float insideconeangle, out float outsideconeangle, out float outsidevolume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Set3DCustomRolloff      (IntPtr sound, ref VECTOR points, int numpoints);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_Get3DCustomRolloff      (IntPtr sound, out IntPtr points, out int numpoints);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetSubSound             (IntPtr sound, int index, out IntPtr subsound);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetSubSoundParent       (IntPtr sound, out IntPtr parentsound);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetName                 (IntPtr sound, IntPtr name, int namelen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetLength               (IntPtr sound, out uint length, TIMEUNIT lengthtype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetFormat               (IntPtr sound, out SOUND_TYPE type, out SOUND_FORMAT format, out int channels, out int bits);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetNumSubSounds         (IntPtr sound, out int numsubsounds);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetNumTags              (IntPtr sound, out int numtags, out int numtagsupdated);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetTag                  (IntPtr sound, string name, int index, out TAG tag);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetOpenState            (IntPtr sound, out OPENSTATE openstate, out uint percentbuffered, out bool starving, out bool diskbusy);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_ReadData                (IntPtr sound, IntPtr buffer, uint lenbytes, out uint read);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SeekData                (IntPtr sound, uint pcm);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetSoundGroup           (IntPtr sound, IntPtr soundgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetSoundGroup           (IntPtr sound, out IntPtr soundgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetNumSyncPoints        (IntPtr sound, out int numsyncpoints);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetSyncPoint            (IntPtr sound, int index, out IntPtr point);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetSyncPointInfo        (IntPtr sound, IntPtr point, IntPtr name, int namelen, out uint offset, TIMEUNIT offsettype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_AddSyncPoint            (IntPtr sound, uint offset, TIMEUNIT offsettype, string name, out IntPtr point);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_DeleteSyncPoint         (IntPtr sound, IntPtr point);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetMode                 (IntPtr sound, MODE mode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetMode                 (IntPtr sound, out MODE mode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetLoopCount            (IntPtr sound, int loopcount);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetLoopCount            (IntPtr sound, out int loopcount);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetLoopPoints           (IntPtr sound, uint loopstart, TIMEUNIT loopstarttype, uint loopend, TIMEUNIT loopendtype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetLoopPoints           (IntPtr sound, out uint loopstart, TIMEUNIT loopstarttype, out uint loopend, TIMEUNIT loopendtype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetMusicNumChannels     (IntPtr sound, out int numchannels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetMusicChannelVolume   (IntPtr sound, int channel, float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetMusicChannelVolume   (IntPtr sound, int channel, out float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetMusicSpeed           (IntPtr sound, float speed);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetMusicSpeed           (IntPtr sound, out float speed);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_SetUserData             (IntPtr sound, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Sound_GetUserData             (IntPtr sound, out IntPtr userdata);\n        #endregion\n\n        #region wrapperinternal\n\n        public Sound(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'ChannelControl' API\n    */\n    public class ChannelControl : HandleBase\n    {\n        public RESULT getSystemObject(out System system)\n        {\n            system = null;\n\n            IntPtr systemraw;\n            RESULT result = FMOD_ChannelGroup_GetSystemObject(rawPtr, out systemraw);\n            system = new System(systemraw);\n\n            return result;\n        }\n\n        // General control functionality for Channels and ChannelGroups.\n        public RESULT stop()\n        {\n            return FMOD_ChannelGroup_Stop(rawPtr);\n        }\n        public RESULT setPaused(bool paused)\n        {\n            return FMOD_ChannelGroup_SetPaused(rawPtr, paused);\n        }\n        public RESULT getPaused(out bool paused)\n        {\n            return FMOD_ChannelGroup_GetPaused(rawPtr, out paused);\n        }\n        public RESULT setVolume(float volume)\n        {\n            return FMOD_ChannelGroup_SetVolume(rawPtr, volume);\n        }\n        public RESULT getVolume(out float volume)\n        {\n            return FMOD_ChannelGroup_GetVolume(rawPtr, out volume);\n        }\n        public RESULT setVolumeRamp(bool ramp)\n        {\n            return FMOD_ChannelGroup_SetVolumeRamp(rawPtr, ramp);\n        }\n        public RESULT getVolumeRamp(out bool ramp)\n        {\n            return FMOD_ChannelGroup_GetVolumeRamp(rawPtr, out ramp);\n        }\n        public RESULT getAudibility(out float audibility)\n        {\n            return FMOD_ChannelGroup_GetAudibility(rawPtr, out audibility);\n        }\n        public RESULT setPitch(float pitch)\n        {\n            return FMOD_ChannelGroup_SetPitch(rawPtr, pitch);\n        }\n        public RESULT getPitch(out float pitch)\n        {\n            return FMOD_ChannelGroup_GetPitch(rawPtr, out pitch);\n        }\n        public RESULT setMute(bool mute)\n        {\n            return FMOD_ChannelGroup_SetMute(rawPtr, mute);\n        }\n        public RESULT getMute(out bool mute)\n        {\n            return FMOD_ChannelGroup_GetMute(rawPtr, out mute);\n        }\n        public RESULT setReverbProperties(int instance, float wet)\n        {\n            return FMOD_ChannelGroup_SetReverbProperties(rawPtr, instance, wet);\n        }\n        public RESULT getReverbProperties(int instance, out float wet)\n        {\n            return FMOD_ChannelGroup_GetReverbProperties(rawPtr, instance, out wet);\n        }\n        public RESULT setLowPassGain(float gain)\n        {\n            return FMOD_ChannelGroup_SetLowPassGain(rawPtr, gain);\n        }\n        public RESULT getLowPassGain(out float gain)\n        {\n            return FMOD_ChannelGroup_GetLowPassGain(rawPtr, out gain);\n        }\n        public RESULT setMode(MODE mode)\n        {\n            return FMOD_ChannelGroup_SetMode(rawPtr, mode);\n        }\n        public RESULT getMode(out MODE mode)\n        {\n            return FMOD_ChannelGroup_GetMode(rawPtr, out mode);\n        }\n        public RESULT setCallback(CHANNEL_CALLBACK callback)\n        {\n            return FMOD_ChannelGroup_SetCallback(rawPtr, callback);\n        }\n        public RESULT isPlaying(out bool isplaying)\n        {\n            return FMOD_ChannelGroup_IsPlaying(rawPtr, out isplaying);\n        }\n\n        // Panning and level adjustment.\n        public RESULT setPan(float pan)\n        {\n            return FMOD_ChannelGroup_SetPan(rawPtr, pan);\n        }\n        public RESULT setMixLevelsOutput(float frontleft, float frontright, float center, float lfe, float surroundleft, float surroundright, float backleft, float backright)\n        {\n            return FMOD_ChannelGroup_SetMixLevelsOutput(rawPtr, frontleft, frontright, center, lfe,\n                surroundleft, surroundright, backleft, backright);\n        }\n        public RESULT setMixLevelsInput(float[] levels, int numlevels)\n        {\n            return FMOD_ChannelGroup_SetMixLevelsInput(rawPtr, levels, numlevels);\n        }\n        public RESULT setMixMatrix(float[] matrix, int outchannels, int inchannels, int inchannel_hop)\n        {\n            return FMOD_ChannelGroup_SetMixMatrix(rawPtr, matrix, outchannels, inchannels, inchannel_hop);\n        }\n        public RESULT getMixMatrix(float[] matrix, out int outchannels, out int inchannels, int inchannel_hop)\n        {\n            return FMOD_ChannelGroup_GetMixMatrix(rawPtr, matrix, out outchannels, out inchannels, inchannel_hop);\n        }\n\n        // Clock based functionality.\n        public RESULT getDSPClock(out ulong dspclock, out ulong parentclock)\n        {\n            return FMOD_ChannelGroup_GetDSPClock(rawPtr, out dspclock, out parentclock);\n        }\n        public RESULT setDelay(ulong dspclock_start, ulong dspclock_end, bool stopchannels)\n        {\n            return FMOD_ChannelGroup_SetDelay(rawPtr, dspclock_start, dspclock_end, stopchannels);\n        }\n        public RESULT getDelay(out ulong dspclock_start, out ulong dspclock_end, out bool stopchannels)\n        {\n            return FMOD_ChannelGroup_GetDelay(rawPtr, out dspclock_start, out dspclock_end, out stopchannels);\n        }\n        public RESULT addFadePoint(ulong dspclock, float volume)\n        {\n            return FMOD_ChannelGroup_AddFadePoint(rawPtr, dspclock, volume);\n        }\n        public RESULT setFadePointRamp(ulong dspclock, float volume)\n        {\n            return FMOD_ChannelGroup_SetFadePointRamp(rawPtr, dspclock, volume);\n        }\n        public RESULT removeFadePoints(ulong dspclock_start, ulong dspclock_end)\n        {\n            return FMOD_ChannelGroup_RemoveFadePoints(rawPtr, dspclock_start, dspclock_end);\n        }\n        public RESULT getFadePoints(ref uint numpoints, ulong[] point_dspclock, float[] point_volume)\n        {\n            return FMOD_ChannelGroup_GetFadePoints(rawPtr, ref numpoints, point_dspclock, point_volume);\n        }\n\n        // DSP effects.\n        public RESULT getDSP(int index, out DSP dsp)\n        {\n            dsp = null;\n\n            IntPtr dspraw;\n            RESULT result = FMOD_ChannelGroup_GetDSP(rawPtr, index, out dspraw);\n            dsp = new DSP(dspraw);\n\n            return result;\n        }\n        public RESULT addDSP(int index, DSP dsp)\n        {\n            return FMOD_ChannelGroup_AddDSP(rawPtr, index, dsp.getRaw());\n        }\n        public RESULT removeDSP(DSP dsp)\n        {\n            return FMOD_ChannelGroup_RemoveDSP(rawPtr, dsp.getRaw());\n        }\n        public RESULT getNumDSPs(out int numdsps)\n        {\n            return FMOD_ChannelGroup_GetNumDSPs(rawPtr, out numdsps);\n        }\n        public RESULT setDSPIndex(DSP dsp, int index)\n        {\n            return FMOD_ChannelGroup_SetDSPIndex(rawPtr, dsp.getRaw(), index);\n        }\n        public RESULT getDSPIndex(DSP dsp, out int index)\n        {\n            return FMOD_ChannelGroup_GetDSPIndex(rawPtr, dsp.getRaw(), out index);\n        }\n        public RESULT overridePanDSP(DSP pan)\n        {\n            return FMOD_ChannelGroup_OverridePanDSP(rawPtr, pan.getRaw());\n        }\n\n        // 3D functionality.\n        public RESULT set3DAttributes(ref VECTOR pos, ref VECTOR vel, ref VECTOR alt_pan_pos)\n        {\n            return FMOD_ChannelGroup_Set3DAttributes(rawPtr, ref pos, ref vel, ref alt_pan_pos);\n        }\n        public RESULT get3DAttributes(out VECTOR pos, out VECTOR vel, out VECTOR alt_pan_pos)\n        {\n            return FMOD_ChannelGroup_Get3DAttributes(rawPtr, out pos, out vel, out alt_pan_pos);\n        }\n        public RESULT set3DMinMaxDistance(float mindistance, float maxdistance)\n        {\n            return FMOD_ChannelGroup_Set3DMinMaxDistance(rawPtr, mindistance, maxdistance);\n        }\n        public RESULT get3DMinMaxDistance(out float mindistance, out float maxdistance)\n        {\n            return FMOD_ChannelGroup_Get3DMinMaxDistance(rawPtr, out mindistance, out maxdistance);\n        }\n        public RESULT set3DConeSettings(float insideconeangle, float outsideconeangle, float outsidevolume)\n        {\n            return FMOD_ChannelGroup_Set3DConeSettings(rawPtr, insideconeangle, outsideconeangle, outsidevolume);\n        }\n        public RESULT get3DConeSettings(out float insideconeangle, out float outsideconeangle, out float outsidevolume)\n        {\n            return FMOD_ChannelGroup_Get3DConeSettings(rawPtr, out insideconeangle, out outsideconeangle, out outsidevolume);\n        }\n        public RESULT set3DConeOrientation(ref VECTOR orientation)\n        {\n            return FMOD_ChannelGroup_Set3DConeOrientation(rawPtr, ref orientation);\n        }\n        public RESULT get3DConeOrientation(out VECTOR orientation)\n        {\n            return FMOD_ChannelGroup_Get3DConeOrientation(rawPtr, out orientation);\n        }\n        public RESULT set3DCustomRolloff(ref VECTOR points, int numpoints)\n        {\n            return FMOD_ChannelGroup_Set3DCustomRolloff(rawPtr, ref points, numpoints);\n        }\n        public RESULT get3DCustomRolloff(out IntPtr points, out int numpoints)\n        {\n            return FMOD_ChannelGroup_Get3DCustomRolloff(rawPtr, out points, out numpoints);\n        }\n        public RESULT set3DOcclusion(float directocclusion, float reverbocclusion)\n        {\n            return FMOD_ChannelGroup_Set3DOcclusion(rawPtr, directocclusion, reverbocclusion);\n        }\n        public RESULT get3DOcclusion(out float directocclusion, out float reverbocclusion)\n        {\n            return FMOD_ChannelGroup_Get3DOcclusion(rawPtr, out directocclusion, out reverbocclusion);\n        }\n        public RESULT set3DSpread(float angle)\n        {\n            return FMOD_ChannelGroup_Set3DSpread(rawPtr, angle);\n        }\n        public RESULT get3DSpread(out float angle)\n        {\n            return FMOD_ChannelGroup_Get3DSpread(rawPtr, out angle);\n        }\n        public RESULT set3DLevel(float level)\n        {\n            return FMOD_ChannelGroup_Set3DLevel(rawPtr, level);\n        }\n        public RESULT get3DLevel(out float level)\n        {\n            return FMOD_ChannelGroup_Get3DLevel(rawPtr, out level);\n        }\n        public RESULT set3DDopplerLevel(float level)\n        {\n            return FMOD_ChannelGroup_Set3DDopplerLevel(rawPtr, level);\n        }\n        public RESULT get3DDopplerLevel(out float level)\n        {\n            return FMOD_ChannelGroup_Get3DDopplerLevel(rawPtr, out level);\n        }\n        public RESULT set3DDistanceFilter(bool custom, float customLevel, float centerFreq)\n        {\n            return FMOD_ChannelGroup_Set3DDistanceFilter(rawPtr, custom, customLevel, centerFreq);\n        }\n        public RESULT get3DDistanceFilter(out bool custom, out float customLevel, out float centerFreq)\n        {\n            return FMOD_ChannelGroup_Get3DDistanceFilter(rawPtr, out custom, out customLevel, out centerFreq);\n        }\n\n        // Userdata set/get.\n        public RESULT setUserData(IntPtr userdata)\n        {\n            return FMOD_ChannelGroup_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData(out IntPtr userdata)\n        {\n            return FMOD_ChannelGroup_GetUserData(rawPtr, out userdata);\n        }\n\n        #region importfunctions\n\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Stop(IntPtr channelgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetPaused(IntPtr channelgroup, bool paused);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetPaused(IntPtr channelgroup, out bool paused);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetVolume(IntPtr channelgroup, out float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetVolumeRamp(IntPtr channelgroup, bool ramp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetVolumeRamp(IntPtr channelgroup, out bool ramp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetAudibility(IntPtr channelgroup, out float audibility);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetPitch(IntPtr channelgroup, float pitch);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetPitch(IntPtr channelgroup, out float pitch);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetMute(IntPtr channelgroup, bool mute);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetMute(IntPtr channelgroup, out bool mute);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetReverbProperties(IntPtr channelgroup, int instance, float wet);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetReverbProperties(IntPtr channelgroup, int instance, out float wet);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetLowPassGain(IntPtr channelgroup, float gain);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetLowPassGain(IntPtr channelgroup, out float gain);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetMode(IntPtr channelgroup, MODE mode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetMode(IntPtr channelgroup, out MODE mode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetCallback(IntPtr channelgroup, CHANNEL_CALLBACK callback);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_IsPlaying(IntPtr channelgroup, out bool isplaying);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetPan(IntPtr channelgroup, float pan);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetMixLevelsOutput(IntPtr channelgroup, float frontleft, float frontright, float center, float lfe, float surroundleft, float surroundright, float backleft, float backright);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetMixLevelsInput(IntPtr channelgroup, float[] levels, int numlevels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetMixMatrix(IntPtr channelgroup, float[] matrix, int outchannels, int inchannels, int inchannel_hop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetMixMatrix(IntPtr channelgroup, float[] matrix, out int outchannels, out int inchannels, int inchannel_hop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetDSPClock(IntPtr channelgroup, out ulong dspclock, out ulong parentclock);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetDelay(IntPtr channelgroup, ulong dspclock_start, ulong dspclock_end, bool stopchannels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetDelay(IntPtr channelgroup, out ulong dspclock_start, out ulong dspclock_end, out bool stopchannels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_AddFadePoint(IntPtr channelgroup, ulong dspclock, float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetFadePointRamp(IntPtr channelgroup, ulong dspclock, float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_RemoveFadePoints(IntPtr channelgroup, ulong dspclock_start, ulong dspclock_end);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetFadePoints(IntPtr channelgroup, ref uint numpoints, ulong[] point_dspclock, float[] point_volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DAttributes(IntPtr channelgroup, ref VECTOR pos, ref VECTOR vel, ref VECTOR alt_pan_pos);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DAttributes(IntPtr channelgroup, out VECTOR pos, out VECTOR vel, out VECTOR alt_pan_pos);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DMinMaxDistance(IntPtr channelgroup, float mindistance, float maxdistance);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DMinMaxDistance(IntPtr channelgroup, out float mindistance, out float maxdistance);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DConeSettings(IntPtr channelgroup, float insideconeangle, float outsideconeangle, float outsidevolume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DConeSettings(IntPtr channelgroup, out float insideconeangle, out float outsideconeangle, out float outsidevolume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DConeOrientation(IntPtr channelgroup, ref VECTOR orientation);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DConeOrientation(IntPtr channelgroup, out VECTOR orientation);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DCustomRolloff(IntPtr channelgroup, ref VECTOR points, int numpoints);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DCustomRolloff(IntPtr channelgroup, out IntPtr points, out int numpoints);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DOcclusion(IntPtr channelgroup, float directocclusion, float reverbocclusion);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DOcclusion(IntPtr channelgroup, out float directocclusion, out float reverbocclusion);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DSpread(IntPtr channelgroup, float angle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DSpread(IntPtr channelgroup, out float angle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DLevel(IntPtr channelgroup, float level);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DLevel(IntPtr channelgroup, out float level);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DDopplerLevel(IntPtr channelgroup, float level);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DDopplerLevel(IntPtr channelgroup, out float level);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Set3DDistanceFilter(IntPtr channelgroup, bool custom, float customLevel, float centerFreq);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Get3DDistanceFilter(IntPtr channelgroup, out bool custom, out float customLevel, out float centerFreq);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetSystemObject(IntPtr channelgroup, out IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetVolume(IntPtr channelgroup, float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetDSP(IntPtr channelgroup, int index, out IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_AddDSP(IntPtr channelgroup, int index, IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_RemoveDSP(IntPtr channelgroup, IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetNumDSPs(IntPtr channelgroup, out int numdsps);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetDSPIndex(IntPtr channelgroup, IntPtr dsp, int index);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetDSPIndex(IntPtr channelgroup, IntPtr dsp, out int index);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_OverridePanDSP(IntPtr channelgroup, IntPtr pan);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_SetUserData(IntPtr channelgroup, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetUserData(IntPtr channelgroup, out IntPtr userdata);\n\n        #endregion\n\n        #region wrapperinternal\n\n        protected ChannelControl(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'Channel' API\n    */\n    public class Channel : ChannelControl\n    {\n        // Channel specific control functionality.\n        public RESULT setFrequency          (float frequency)\n        {\n            return FMOD_Channel_SetFrequency(getRaw(), frequency);\n        }\n        public RESULT getFrequency          (out float frequency)\n        {\n            return FMOD_Channel_GetFrequency(getRaw(), out frequency);\n        }\n        public RESULT setPriority           (int priority)\n        {\n            return FMOD_Channel_SetPriority(getRaw(), priority);\n        }\n        public RESULT getPriority           (out int priority)\n        {\n            return FMOD_Channel_GetPriority(getRaw(), out priority);\n        }\n        public RESULT setPosition           (uint position, TIMEUNIT postype)\n        {\n            return FMOD_Channel_SetPosition(getRaw(), position, postype);\n        }\n        public RESULT getPosition           (out uint position, TIMEUNIT postype)\n        {\n            return FMOD_Channel_GetPosition(getRaw(), out position, postype);\n        }\n        public RESULT setChannelGroup       (ChannelGroup channelgroup)\n        {\n            return FMOD_Channel_SetChannelGroup(getRaw(), channelgroup.getRaw());\n        }\n        public RESULT getChannelGroup       (out ChannelGroup channelgroup)\n        {\n            channelgroup = null;\n\n            IntPtr channelgroupraw;\n            RESULT result = FMOD_Channel_GetChannelGroup(getRaw(), out channelgroupraw);\n            channelgroup = new ChannelGroup(channelgroupraw);\n\n            return result;\n        }\n        public RESULT setLoopCount(int loopcount)\n        {\n            return FMOD_Channel_SetLoopCount(getRaw(), loopcount);\n        }\n        public RESULT getLoopCount(out int loopcount)\n        {\n            return FMOD_Channel_GetLoopCount(getRaw(), out loopcount);\n        }\n        public RESULT setLoopPoints(uint loopstart, TIMEUNIT loopstarttype, uint loopend, TIMEUNIT loopendtype)\n        {\n            return FMOD_Channel_SetLoopPoints(getRaw(), loopstart, loopstarttype, loopend, loopendtype);\n        }\n        public RESULT getLoopPoints(out uint loopstart, TIMEUNIT loopstarttype, out uint loopend, TIMEUNIT loopendtype)\n        {\n            return FMOD_Channel_GetLoopPoints(getRaw(), out loopstart, loopstarttype, out loopend, loopendtype);\n        }\n\n        // Information only functions.\n        public RESULT isVirtual             (out bool isvirtual)\n        {\n            return FMOD_Channel_IsVirtual(getRaw(), out isvirtual);\n        }\n        public RESULT getCurrentSound       (out Sound sound)\n        {\n            sound = null;\n\n            IntPtr soundraw;\n            RESULT result = FMOD_Channel_GetCurrentSound(getRaw(), out soundraw);\n            sound = new Sound(soundraw);\n\n            return result;\n        }\n        public RESULT getIndex              (out int index)\n        {\n            return FMOD_Channel_GetIndex(getRaw(), out index);\n        }\n\n        #region importfunctions\n\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetFrequency          (IntPtr channel, float frequency);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetFrequency          (IntPtr channel, out float frequency);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetPriority           (IntPtr channel, int priority);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetPriority           (IntPtr channel, out int priority);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetChannelGroup       (IntPtr channel, IntPtr channelgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetChannelGroup       (IntPtr channel, out IntPtr channelgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_IsVirtual             (IntPtr channel, out bool isvirtual);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetCurrentSound       (IntPtr channel, out IntPtr sound);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetIndex              (IntPtr channel, out int index);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetPosition           (IntPtr channel, uint position, TIMEUNIT postype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetPosition           (IntPtr channel, out uint position, TIMEUNIT postype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetMode               (IntPtr channel, MODE mode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetMode               (IntPtr channel, out MODE mode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetLoopCount          (IntPtr channel, int loopcount);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetLoopCount          (IntPtr channel, out int loopcount);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetLoopPoints         (IntPtr channel, uint  loopstart, TIMEUNIT loopstarttype, uint  loopend, TIMEUNIT loopendtype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetLoopPoints         (IntPtr channel, out uint loopstart, TIMEUNIT loopstarttype, out uint loopend, TIMEUNIT loopendtype);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_SetUserData           (IntPtr channel, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Channel_GetUserData           (IntPtr channel, out IntPtr userdata);\n        #endregion\n\n        #region wrapperinternal\n\n        public Channel(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'ChannelGroup' API\n    */\n    public class ChannelGroup : ChannelControl\n    {\n        public RESULT release                ()\n        {\n            RESULT result = FMOD_ChannelGroup_Release(getRaw());\n            if (result == RESULT.OK)\n            {\n                rawPtr = IntPtr.Zero;\n            }\n            return result;\n        }\n\n        // Nested channel groups.\n        public RESULT addGroup               (ChannelGroup group, bool propagatedspclock, out DSPConnection connection)\n        {\n\t\t\tconnection = null;\n\t\t\t\n\t\t\tIntPtr connectionRaw;\n            RESULT result = FMOD_ChannelGroup_AddGroup(getRaw(), group.getRaw(), propagatedspclock, out connectionRaw);\n\t\t\tconnection = new DSPConnection(connectionRaw);\n\t\t\t\n\t\t\treturn result;\n        }\n        public RESULT getNumGroups           (out int numgroups)\n        {\n            return FMOD_ChannelGroup_GetNumGroups(getRaw(), out numgroups);\n        }\n        public RESULT getGroup               (int index, out ChannelGroup group)\n        {\n            group = null;\n\n            IntPtr groupraw;\n            RESULT result = FMOD_ChannelGroup_GetGroup(getRaw(), index, out groupraw);\n            group = new ChannelGroup(groupraw);\n\n            return result;\n        }\n        public RESULT getParentGroup         (out ChannelGroup group)\n        {\n            group = null;\n\n            IntPtr groupraw;\n            RESULT result = FMOD_ChannelGroup_GetParentGroup(getRaw(), out groupraw);\n            group = new ChannelGroup(groupraw);\n\n            return result;\n        }\n\n        // Information only functions.\n        public RESULT getName                (StringBuilder name, int namelen)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(name.Capacity);\n\n            RESULT result = FMOD_ChannelGroup_GetName(getRaw(), stringMem, namelen);\n\n            StringMarshalHelper.NativeToBuilder(name, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT getNumChannels         (out int numchannels)\n        {\n            return FMOD_ChannelGroup_GetNumChannels(getRaw(), out numchannels);\n        }\n        public RESULT getChannel             (int index, out Channel channel)\n        {\n            channel = null;\n\n            IntPtr channelraw;\n            RESULT result = FMOD_ChannelGroup_GetChannel(getRaw(), index, out channelraw);\n            channel = new Channel(channelraw);\n\n            return result;\n        }\n\n        #region importfunctions\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_Release          (IntPtr channelgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_AddGroup         (IntPtr channelgroup, IntPtr group, bool propagatedspclock, out IntPtr connection);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetNumGroups     (IntPtr channelgroup, out int numgroups);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetGroup         (IntPtr channelgroup, int index, out IntPtr group);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetParentGroup   (IntPtr channelgroup, out IntPtr group);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetName          (IntPtr channelgroup, IntPtr name, int namelen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetNumChannels   (IntPtr channelgroup, out int numchannels);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_ChannelGroup_GetChannel       (IntPtr channelgroup, int index, out IntPtr channel);\n        #endregion\n\n        #region wrapperinternal\n\n        public ChannelGroup(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'SoundGroup' API\n    */\n    public class SoundGroup : HandleBase\n    {\n        public RESULT release                ()\n        {\n            RESULT result = FMOD_SoundGroup_Release(getRaw());\n            if (result == RESULT.OK)\n            {\n                rawPtr = IntPtr.Zero;\n            }\n            return result;\n        }\n\n        public RESULT getSystemObject        (out System system)\n        {\n            system = null;\n\n            IntPtr systemraw;\n            RESULT result = FMOD_SoundGroup_GetSystemObject(rawPtr, out systemraw);\n            system = new System(systemraw);\n\n            return result;\n        }\n\n        // SoundGroup control functions.\n        public RESULT setMaxAudible          (int maxaudible)\n        {\n            return FMOD_SoundGroup_SetMaxAudible(rawPtr, maxaudible);\n        }\n        public RESULT getMaxAudible          (out int maxaudible)\n        {\n            return FMOD_SoundGroup_GetMaxAudible(rawPtr, out maxaudible);\n        }\n        public RESULT setMaxAudibleBehavior  (SOUNDGROUP_BEHAVIOR behavior)\n        {\n            return FMOD_SoundGroup_SetMaxAudibleBehavior(rawPtr, behavior);\n        }\n        public RESULT getMaxAudibleBehavior  (out SOUNDGROUP_BEHAVIOR behavior)\n        {\n            return FMOD_SoundGroup_GetMaxAudibleBehavior(rawPtr, out behavior);\n        }\n        public RESULT setMuteFadeSpeed       (float speed)\n        {\n            return FMOD_SoundGroup_SetMuteFadeSpeed(rawPtr, speed);\n        }\n        public RESULT getMuteFadeSpeed       (out float speed)\n        {\n            return FMOD_SoundGroup_GetMuteFadeSpeed(rawPtr, out speed);\n        }\n        public RESULT setVolume       (float volume)\n        {\n            return FMOD_SoundGroup_SetVolume(rawPtr, volume);\n        }\n        public RESULT getVolume       (out float volume)\n        {\n            return FMOD_SoundGroup_GetVolume(rawPtr, out volume);\n        }\n        public RESULT stop       ()\n        {\n            return FMOD_SoundGroup_Stop(rawPtr);\n        }\n\n        // Information only functions.\n        public RESULT getName                (StringBuilder name, int namelen)\n        {\n            IntPtr stringMem = Marshal.AllocHGlobal(name.Capacity);\n\n            RESULT result = FMOD_SoundGroup_GetName(rawPtr, stringMem, namelen);\n\n            StringMarshalHelper.NativeToBuilder(name, stringMem);\n            Marshal.FreeHGlobal(stringMem);\n\n            return result;\n        }\n        public RESULT getNumSounds           (out int numsounds)\n        {\n            return FMOD_SoundGroup_GetNumSounds(rawPtr, out numsounds);\n        }\n        public RESULT getSound               (int index, out Sound sound)\n        {\n            sound = null;\n\n            IntPtr soundraw;\n            RESULT result = FMOD_SoundGroup_GetSound(rawPtr, index, out soundraw);\n            sound = new Sound(soundraw);\n\n            return result;\n        }\n        public RESULT getNumPlaying          (out int numplaying)\n        {\n            return FMOD_SoundGroup_GetNumPlaying(rawPtr, out numplaying);\n        }\n\n        // Userdata set/get.\n        public RESULT setUserData            (IntPtr userdata)\n        {\n            return FMOD_SoundGroup_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData            (out IntPtr userdata)\n        {\n            return FMOD_SoundGroup_GetUserData(rawPtr, out userdata);\n        }\n\n        #region importfunctions\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_Release            (IntPtr soundgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetSystemObject    (IntPtr soundgroup, out IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_SetMaxAudible      (IntPtr soundgroup, int maxaudible);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetMaxAudible      (IntPtr soundgroup, out int maxaudible);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_SetMaxAudibleBehavior(IntPtr soundgroup, SOUNDGROUP_BEHAVIOR behavior);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetMaxAudibleBehavior(IntPtr soundgroup, out SOUNDGROUP_BEHAVIOR behavior);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_SetMuteFadeSpeed   (IntPtr soundgroup, float speed);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetMuteFadeSpeed   (IntPtr soundgroup, out float speed);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_SetVolume          (IntPtr soundgroup, float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetVolume          (IntPtr soundgroup, out float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_Stop               (IntPtr soundgroup);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetName            (IntPtr soundgroup, IntPtr name, int namelen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetNumSounds       (IntPtr soundgroup, out int numsounds);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetSound           (IntPtr soundgroup, int index, out IntPtr sound);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetNumPlaying      (IntPtr soundgroup, out int numplaying);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_SetUserData        (IntPtr soundgroup, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_SoundGroup_GetUserData        (IntPtr soundgroup, out IntPtr userdata);\n        #endregion\n\n        #region wrapperinternal\n\n        public SoundGroup(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'DSP' API\n    */\n    public class DSP : HandleBase\n    {\n        public RESULT release                   ()\n        {\n            RESULT result = FMOD_DSP_Release(getRaw());\n            if (result == RESULT.OK)\n            {\n                rawPtr = IntPtr.Zero;\n            }\n            return result;\n        }\n        public RESULT getSystemObject           (out System system)\n        {\n            system = null;\n\n            IntPtr systemraw;\n            RESULT result = FMOD_DSP_GetSystemObject(rawPtr, out systemraw);\n            system = new System(systemraw);\n\n            return result;\n        }\n\n        // Connection / disconnection / input and output enumeration.\n        public RESULT addInput(DSP target, out DSPConnection connection, DSPCONNECTION_TYPE type)\n        {\n            connection = null;\n\n            IntPtr dspconnectionraw;\n            RESULT result = FMOD_DSP_AddInput(rawPtr, target.getRaw(), out dspconnectionraw, type);\n            connection = new DSPConnection(dspconnectionraw);\n\n            return result;\n        }\n        public RESULT disconnectFrom            (DSP target, DSPConnection connection)\n        {\n            return FMOD_DSP_DisconnectFrom(rawPtr, target.getRaw(), connection.getRaw());\n        }\n        public RESULT disconnectAll             (bool inputs, bool outputs)\n        {\n            return FMOD_DSP_DisconnectAll(rawPtr, inputs, outputs);\n        }\n        public RESULT getNumInputs              (out int numinputs)\n        {\n            return FMOD_DSP_GetNumInputs(rawPtr, out numinputs);\n        }\n        public RESULT getNumOutputs             (out int numoutputs)\n        {\n            return FMOD_DSP_GetNumOutputs(rawPtr, out numoutputs);\n        }\n        public RESULT getInput                  (int index, out DSP input, out DSPConnection inputconnection)\n        {\n            input = null;\n            inputconnection = null;\n\n            IntPtr dspinputraw;\n            IntPtr dspconnectionraw;\n            RESULT result = FMOD_DSP_GetInput(rawPtr, index, out dspinputraw, out dspconnectionraw);\n            input = new DSP(dspinputraw);\n            inputconnection = new DSPConnection(dspconnectionraw);\n\n            return result;\n        }\n        public RESULT getOutput                 (int index, out DSP output, out DSPConnection outputconnection)\n        {\n            output = null;\n            outputconnection = null;\n\n            IntPtr dspoutputraw;\n            IntPtr dspconnectionraw;\n            RESULT result = FMOD_DSP_GetOutput(rawPtr, index, out dspoutputraw, out dspconnectionraw);\n            output = new DSP(dspoutputraw);\n            outputconnection = new DSPConnection(dspconnectionraw);\n\n            return result;\n        }\n\n        // DSP unit control.\n        public RESULT setActive                 (bool active)\n        {\n            return FMOD_DSP_SetActive(rawPtr, active);\n        }\n        public RESULT getActive                 (out bool active)\n        {\n            return FMOD_DSP_GetActive(rawPtr, out active);\n        }\n        public RESULT setBypass(bool bypass)\n        {\n            return FMOD_DSP_SetBypass(rawPtr, bypass);\n        }\n        public RESULT getBypass(out bool bypass)\n        {\n            return FMOD_DSP_GetBypass(rawPtr, out bypass);\n        }\n        public RESULT setWetDryMix(float prewet, float postwet, float dry)\n        {\n            return FMOD_DSP_SetWetDryMix(rawPtr, prewet, postwet, dry);\n        }\n        public RESULT getWetDryMix(out float prewet, out float postwet, out float dry)\n        {\n            return FMOD_DSP_GetWetDryMix(rawPtr, out prewet, out postwet, out dry);\n        }\n        public RESULT setChannelFormat(CHANNELMASK channelmask, int numchannels, SPEAKERMODE source_speakermode)\n        {\n            return FMOD_DSP_SetChannelFormat(rawPtr, channelmask, numchannels, source_speakermode);\n        }\n        public RESULT getChannelFormat(out CHANNELMASK channelmask, out int numchannels, out SPEAKERMODE source_speakermode)\n        {\n            return FMOD_DSP_GetChannelFormat(rawPtr, out channelmask, out numchannels, out source_speakermode);\n        }\n        public RESULT getOutputChannelFormat(CHANNELMASK inmask, int inchannels, SPEAKERMODE inspeakermode, out CHANNELMASK outmask, out int outchannels, out SPEAKERMODE outspeakermode)\n        {\n            return FMOD_DSP_GetOutputChannelFormat(rawPtr, inmask, inchannels, inspeakermode, out outmask, out outchannels, out outspeakermode);\n        }\n        public RESULT reset                     ()\n        {\n            return FMOD_DSP_Reset(rawPtr);\n        }\n\n        // DSP parameter control.\n        public RESULT setParameterFloat(int index, float value)\n        {\n            return FMOD_DSP_SetParameterFloat(rawPtr, index, value);\n        }\n        public RESULT setParameterInt(int index, int value)\n        {\n            return FMOD_DSP_SetParameterInt(rawPtr, index, value);\n        }\n        public RESULT setParameterBool(int index, bool value)\n        {\n            return FMOD_DSP_SetParameterBool(rawPtr, index, value);\n        }\n        public RESULT setParameterData(int index, byte[] data)\n        {\n            return FMOD_DSP_SetParameterData(rawPtr, index, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0), (uint)data.Length);\n        }\n        public RESULT getParameterFloat(int index, out float value)\n        {\n            IntPtr valuestr = IntPtr.Zero;\n            return FMOD_DSP_GetParameterFloat(rawPtr, index, out value, valuestr, 0);\n        }\n        public RESULT getParameterInt(int index, out int value)\n        {\n            IntPtr valuestr = IntPtr.Zero;\n            return FMOD_DSP_GetParameterInt(rawPtr, index, out value, valuestr, 0);\n        }\n        public RESULT getParameterBool(int index, out bool value)\n        {\n            return FMOD_DSP_GetParameterBool(rawPtr, index, out value, IntPtr.Zero, 0);\n        }\n        public RESULT getParameterData(int index, out IntPtr data, out uint length)\n        {\n            return FMOD_DSP_GetParameterData(rawPtr, index, out data, out length, IntPtr.Zero, 0);\n        }\n        public RESULT getNumParameters          (out int numparams)\n        {\n            return FMOD_DSP_GetNumParameters(rawPtr, out numparams);\n        }\n        public RESULT getParameterInfo          (int index, out DSP_PARAMETER_DESC desc)\n        {\n            IntPtr descPtr;\n            RESULT result = FMOD_DSP_GetParameterInfo(rawPtr, index, out descPtr);\n            if (result == RESULT.OK)\n            {\n                desc = (DSP_PARAMETER_DESC)Marshal.PtrToStructure(descPtr, typeof(DSP_PARAMETER_DESC));\n            }\n            else\n            {\n                desc = new DSP_PARAMETER_DESC();\n            }\n            return result;\n        }\n        public RESULT getDataParameterIndex(int datatype, out int index)\n        {\n            return FMOD_DSP_GetDataParameterIndex     (rawPtr, datatype, out index);\n        }\n        public RESULT showConfigDialog          (IntPtr hwnd, bool show)\n        {\n            return FMOD_DSP_ShowConfigDialog          (rawPtr, hwnd, show);\n        }\n\n        //  DSP attributes.\n        public RESULT getInfo                   (StringBuilder name, out uint version, out int channels, out int configwidth, out int configheight)\n        {\n            IntPtr nameMem = Marshal.AllocHGlobal(32);\n            RESULT result = FMOD_DSP_GetInfo(rawPtr, nameMem, out version, out channels, out configwidth, out configheight);\n            StringMarshalHelper.NativeToBuilder(name, nameMem);\n            Marshal.FreeHGlobal(nameMem);\n            return result;\n        }\n        public RESULT getType                   (out DSP_TYPE type)\n        {\n            return FMOD_DSP_GetType(rawPtr, out type);\n        }\n        public RESULT getIdle                   (out bool idle)\n        {\n            return FMOD_DSP_GetIdle(rawPtr, out idle);\n        }\n\n        // Userdata set/get.\n        public RESULT setUserData               (IntPtr userdata)\n        {\n            return FMOD_DSP_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData               (out IntPtr userdata)\n        {\n            return FMOD_DSP_GetUserData(rawPtr, out userdata);\n        }\n\n        // Metering.\n        public RESULT setMeteringEnabled(bool inputEnabled, bool outputEnabled)\n        {\n            return FMOD_DSP_SetMeteringEnabled(rawPtr, inputEnabled, outputEnabled);\n        }\n        public RESULT getMeteringEnabled(out bool inputEnabled, out bool outputEnabled)\n        {\n            return FMOD_DSP_GetMeteringEnabled(rawPtr, out inputEnabled, out outputEnabled);\n        }\n\n        public RESULT getMeteringInfo(DSP_METERING_INFO inputInfo, DSP_METERING_INFO outputInfo)\n        {\n            return FMOD_DSP_GetMeteringInfo(rawPtr, inputInfo, outputInfo);\n        }\n\n        #region importfunctions\n\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_Release                   (IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetSystemObject           (IntPtr dsp, out IntPtr system);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_AddInput                  (IntPtr dsp, IntPtr target, out IntPtr connection, DSPCONNECTION_TYPE type);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_DisconnectFrom            (IntPtr dsp, IntPtr target, IntPtr connection);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_DisconnectAll             (IntPtr dsp, bool inputs, bool outputs);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetNumInputs              (IntPtr dsp, out int numinputs);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetNumOutputs             (IntPtr dsp, out int numoutputs);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetInput                  (IntPtr dsp, int index, out IntPtr input, out IntPtr inputconnection);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetOutput                 (IntPtr dsp, int index, out IntPtr output, out IntPtr outputconnection);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetActive                 (IntPtr dsp, bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetActive                 (IntPtr dsp, out bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetBypass                 (IntPtr dsp, bool bypass);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetBypass                 (IntPtr dsp, out bool bypass);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetWetDryMix              (IntPtr dsp, float prewet, float postwet, float dry);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetWetDryMix              (IntPtr dsp, out float prewet, out float postwet, out float dry);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetChannelFormat          (IntPtr dsp, CHANNELMASK channelmask, int numchannels, SPEAKERMODE source_speakermode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetChannelFormat          (IntPtr dsp, out CHANNELMASK channelmask, out int numchannels, out SPEAKERMODE source_speakermode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetOutputChannelFormat    (IntPtr dsp, CHANNELMASK inmask, int inchannels, SPEAKERMODE inspeakermode, out CHANNELMASK outmask, out int outchannels, out SPEAKERMODE outspeakermode);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_Reset                     (IntPtr dsp);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetParameterFloat         (IntPtr dsp, int index, float value);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetParameterInt           (IntPtr dsp, int index, int value);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetParameterBool          (IntPtr dsp, int index, bool value);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetParameterData          (IntPtr dsp, int index, IntPtr data, uint length);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetParameterFloat         (IntPtr dsp, int index, out float value, IntPtr valuestr, int valuestrlen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetParameterInt           (IntPtr dsp, int index, out int value, IntPtr valuestr, int valuestrlen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetParameterBool          (IntPtr dsp, int index, out bool value, IntPtr valuestr, int valuestrlen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetParameterData          (IntPtr dsp, int index, out IntPtr data, out uint length, IntPtr valuestr, int valuestrlen);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetNumParameters          (IntPtr dsp, out int numparams);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetParameterInfo          (IntPtr dsp, int index, out IntPtr desc);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetDataParameterIndex     (IntPtr dsp, int datatype, out int index);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_ShowConfigDialog          (IntPtr dsp, IntPtr hwnd, bool show);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetInfo                   (IntPtr dsp, IntPtr name, out uint version, out int channels, out int configwidth, out int configheight);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetType                   (IntPtr dsp, out DSP_TYPE type);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetIdle                   (IntPtr dsp, out bool idle);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_SetUserData               (IntPtr dsp, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSP_GetUserData               (IntPtr dsp, out IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        public static extern RESULT FMOD_DSP_SetMeteringEnabled         (IntPtr dsp, bool inputEnabled, bool outputEnabled);\n        [DllImport(VERSION.dll)]\n        public static extern RESULT FMOD_DSP_GetMeteringEnabled         (IntPtr dsp, out bool inputEnabled, out bool outputEnabled);\n        [DllImport(VERSION.dll)]\n        public static extern RESULT FMOD_DSP_GetMeteringInfo            (IntPtr dsp, [Out] DSP_METERING_INFO inputInfo, [Out] DSP_METERING_INFO outputInfo);\n        #endregion\n\n        #region wrapperinternal\n\n        public DSP(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'DSPConnection' API\n    */\n    public class DSPConnection : HandleBase\n    {\n        public RESULT getInput              (out DSP input)\n        {\n            input = null;\n\n            IntPtr dspraw;\n            RESULT result = FMOD_DSPConnection_GetInput(rawPtr, out dspraw);\n            input = new DSP(dspraw);\n\n            return result;\n        }\n        public RESULT getOutput             (out DSP output)\n        {\n            output = null;\n\n            IntPtr dspraw;\n            RESULT result = FMOD_DSPConnection_GetOutput(rawPtr, out dspraw);\n            output = new DSP(dspraw);\n\n            return result;\n        }\n        public RESULT setMix                (float volume)\n        {\n            return FMOD_DSPConnection_SetMix(rawPtr, volume);\n        }\n        public RESULT getMix                (out float volume)\n        {\n            return FMOD_DSPConnection_GetMix(rawPtr, out volume);\n        }\n        public RESULT setMixMatrix(float[] matrix, int outchannels, int inchannels, int inchannel_hop)\n        {\n            return FMOD_DSPConnection_SetMixMatrix(rawPtr, matrix, outchannels, inchannels, inchannel_hop);\n        }\n        public RESULT getMixMatrix(float[] matrix, out int outchannels, out int inchannels, int inchannel_hop)\n        {\n            return FMOD_DSPConnection_GetMixMatrix(rawPtr, matrix, out outchannels, out inchannels, inchannel_hop);\n        }\n        public RESULT getType(out DSPCONNECTION_TYPE type)\n        {\n            return FMOD_DSPConnection_GetType(rawPtr, out type);\n        }\n\n        // Userdata set/get.\n        public RESULT setUserData(IntPtr userdata)\n        {\n            return FMOD_DSPConnection_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData(out IntPtr userdata)\n        {\n            return FMOD_DSPConnection_GetUserData(rawPtr, out userdata);\n        }\n\n        #region importfunctions\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_GetInput        (IntPtr dspconnection, out IntPtr input);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_GetOutput       (IntPtr dspconnection, out IntPtr output);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_SetMix          (IntPtr dspconnection, float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_GetMix          (IntPtr dspconnection, out float volume);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_SetMixMatrix    (IntPtr dspconnection, float[] matrix, int outchannels, int inchannels, int inchannel_hop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_GetMixMatrix    (IntPtr dspconnection, float[] matrix, out int outchannels, out int inchannels, int inchannel_hop);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_GetType         (IntPtr dspconnection, out DSPCONNECTION_TYPE type);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_SetUserData     (IntPtr dspconnection, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_DSPConnection_GetUserData     (IntPtr dspconnection, out IntPtr userdata);\n        #endregion\n\n        #region wrapperinternal\n\n        public DSPConnection(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n    /*\n        'Geometry' API\n    */\n    public class Geometry : HandleBase\n    {\n        public RESULT release               ()\n        {\n            RESULT result = FMOD_Geometry_Release(getRaw());\n            if (result == RESULT.OK)\n            {\n                rawPtr = IntPtr.Zero;\n            }\n            return result;\n        }\n\n        // Polygon manipulation.\n        public RESULT addPolygon            (float directocclusion, float reverbocclusion, bool doublesided, int numvertices, VECTOR[] vertices, out int polygonindex)\n        {\n            return FMOD_Geometry_AddPolygon(rawPtr, directocclusion, reverbocclusion, doublesided, numvertices, vertices, out polygonindex);\n        }\n        public RESULT getNumPolygons        (out int numpolygons)\n        {\n            return FMOD_Geometry_GetNumPolygons(rawPtr, out numpolygons);\n        }\n        public RESULT getMaxPolygons        (out int maxpolygons, out int maxvertices)\n        {\n            return FMOD_Geometry_GetMaxPolygons(rawPtr, out maxpolygons, out maxvertices);\n        }\n        public RESULT getPolygonNumVertices (int index, out int numvertices)\n        {\n            return FMOD_Geometry_GetPolygonNumVertices(rawPtr, index, out numvertices);\n        }\n        public RESULT setPolygonVertex      (int index, int vertexindex, ref VECTOR vertex)\n        {\n            return FMOD_Geometry_SetPolygonVertex(rawPtr, index, vertexindex, ref vertex);\n        }\n        public RESULT getPolygonVertex      (int index, int vertexindex, out VECTOR vertex)\n        {\n            return FMOD_Geometry_GetPolygonVertex(rawPtr, index, vertexindex, out vertex);\n        }\n        public RESULT setPolygonAttributes  (int index, float directocclusion, float reverbocclusion, bool doublesided)\n        {\n            return FMOD_Geometry_SetPolygonAttributes(rawPtr, index, directocclusion, reverbocclusion, doublesided);\n        }\n        public RESULT getPolygonAttributes  (int index, out float directocclusion, out float reverbocclusion, out bool doublesided)\n        {\n            return FMOD_Geometry_GetPolygonAttributes(rawPtr, index, out directocclusion, out reverbocclusion, out doublesided);\n        }\n\n        // Object manipulation.\n        public RESULT setActive             (bool active)\n        {\n            return FMOD_Geometry_SetActive(rawPtr, active);\n        }\n        public RESULT getActive             (out bool active)\n        {\n            return FMOD_Geometry_GetActive(rawPtr, out active);\n        }\n        public RESULT setRotation           (ref VECTOR forward, ref VECTOR up)\n        {\n            return FMOD_Geometry_SetRotation(rawPtr, ref forward, ref up);\n        }\n        public RESULT getRotation           (out VECTOR forward, out VECTOR up)\n        {\n            return FMOD_Geometry_GetRotation(rawPtr, out forward, out up);\n        }\n        public RESULT setPosition           (ref VECTOR position)\n        {\n            return FMOD_Geometry_SetPosition(rawPtr, ref position);\n        }\n        public RESULT getPosition           (out VECTOR position)\n        {\n            return FMOD_Geometry_GetPosition(rawPtr, out position);\n        }\n        public RESULT setScale              (ref VECTOR scale)\n        {\n            return FMOD_Geometry_SetScale(rawPtr, ref scale);\n        }\n        public RESULT getScale              (out VECTOR scale)\n        {\n            return FMOD_Geometry_GetScale(rawPtr, out scale);\n        }\n        public RESULT save                  (IntPtr data, out int datasize)\n        {\n            return FMOD_Geometry_Save(rawPtr, data, out datasize);\n        }\n\n        // Userdata set/get.\n        public RESULT setUserData               (IntPtr userdata)\n        {\n            return FMOD_Geometry_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData               (out IntPtr userdata)\n        {\n            return FMOD_Geometry_GetUserData(rawPtr, out userdata);\n        }\n\n        #region importfunctions\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_Release              (IntPtr geometry);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_AddPolygon           (IntPtr geometry, float directocclusion, float reverbocclusion, bool doublesided, int numvertices, VECTOR[] vertices, out int polygonindex);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetNumPolygons       (IntPtr geometry, out int numpolygons);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetMaxPolygons       (IntPtr geometry, out int maxpolygons, out int maxvertices);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetPolygonNumVertices(IntPtr geometry, int index, out int numvertices);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_SetPolygonVertex     (IntPtr geometry, int index, int vertexindex, ref VECTOR vertex);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetPolygonVertex     (IntPtr geometry, int index, int vertexindex, out VECTOR vertex);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_SetPolygonAttributes (IntPtr geometry, int index, float directocclusion, float reverbocclusion, bool doublesided);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetPolygonAttributes (IntPtr geometry, int index, out float directocclusion, out float reverbocclusion, out bool doublesided);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_SetActive            (IntPtr geometry, bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetActive            (IntPtr geometry, out bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_SetRotation          (IntPtr geometry, ref VECTOR forward, ref VECTOR up);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetRotation          (IntPtr geometry, out VECTOR forward, out VECTOR up);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_SetPosition          (IntPtr geometry, ref VECTOR position);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetPosition          (IntPtr geometry, out VECTOR position);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_SetScale             (IntPtr geometry, ref VECTOR scale);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetScale             (IntPtr geometry, out VECTOR scale);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_Save                 (IntPtr geometry, IntPtr data, out int datasize);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_SetUserData          (IntPtr geometry, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Geometry_GetUserData          (IntPtr geometry, out IntPtr userdata);\n        #endregion\n\n        #region wrapperinternal\n\n        public Geometry(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n\n    /*\n        'Reverb3D' API\n    */\n    public class Reverb3D : HandleBase\n    {\n        public RESULT release()\n        {\n            RESULT result = FMOD_Reverb3D_Release(getRaw());\n            if (result == RESULT.OK)\n            {\n                rawPtr = IntPtr.Zero;\n            }\n            return result;\n        }\n\n        // Reverb manipulation.\n        public RESULT set3DAttributes(ref VECTOR position, float mindistance, float maxdistance)\n        {\n            return FMOD_Reverb3D_Set3DAttributes(rawPtr, ref position, mindistance, maxdistance);\n        }\n        public RESULT get3DAttributes(ref VECTOR position, ref float mindistance, ref float maxdistance)\n        {\n            return FMOD_Reverb3D_Get3DAttributes(rawPtr, ref position, ref mindistance, ref maxdistance);\n        }\n        public RESULT setProperties(ref REVERB_PROPERTIES properties)\n        {\n            return FMOD_Reverb3D_SetProperties(rawPtr, ref properties);\n        }\n        public RESULT getProperties(ref REVERB_PROPERTIES properties)\n        {\n            return FMOD_Reverb3D_GetProperties(rawPtr, ref properties);\n        }\n        public RESULT setActive(bool active)\n        {\n            return FMOD_Reverb3D_SetActive(rawPtr, active);\n        }\n        public RESULT getActive(out bool active)\n        {\n            return FMOD_Reverb3D_GetActive(rawPtr, out active);\n        }\n\n        // Userdata set/get.\n        public RESULT setUserData(IntPtr userdata)\n        {\n            return FMOD_Reverb3D_SetUserData(rawPtr, userdata);\n        }\n        public RESULT getUserData(out IntPtr userdata)\n        {\n            return FMOD_Reverb3D_GetUserData(rawPtr, out userdata);\n        }\n\n        #region importfunctions\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_Release(IntPtr reverb);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_Set3DAttributes(IntPtr reverb, ref VECTOR position, float mindistance, float maxdistance);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_Get3DAttributes(IntPtr reverb, ref VECTOR position, ref float mindistance, ref float maxdistance);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_SetProperties(IntPtr reverb, ref REVERB_PROPERTIES properties);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_GetProperties(IntPtr reverb, ref REVERB_PROPERTIES properties);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_SetActive(IntPtr reverb, bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_GetActive(IntPtr reverb, out bool active);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_SetUserData(IntPtr reverb, IntPtr userdata);\n        [DllImport(VERSION.dll)]\n        private static extern RESULT FMOD_Reverb3D_GetUserData(IntPtr reverb, out IntPtr userdata);\n        #endregion\n\n        #region wrapperinternal\n\n        public Reverb3D(IntPtr raw)\n            : base(raw)\n        {\n        }\n\n        #endregion\n    }\n\n    class StringMarshalHelper\n    {\n        static internal void NativeToBuilder(StringBuilder builder, IntPtr nativeMem)\n        {\n            byte[] bytes = new byte[builder.Capacity];\n            Marshal.Copy(nativeMem, bytes, 0, builder.Capacity);\n\t\t\tint strlen = Array.IndexOf(bytes, (byte)0);\n\t\t\tif (strlen > 0)\n\t\t\t{\n\t\t\t\tString str = Encoding.UTF8.GetString(bytes, 0, strlen);\n\t\t\t\tbuilder.Append(str);\n\t\t\t}\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/FMOD Studio API/fmod_dsp.cs",
    "content": "/*$ preserve start $*/\n/* ========================================================================================== */\n/* FMOD Studio - DSP header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016.  */\n/*                                                                                            */\n/* Use this header if you are interested in delving deeper into the FMOD software mixing /    */\n/* DSP engine.  In this header you can find parameter structures for FMOD system registered   */\n/* DSP effects and generators.                                                                */\n/*                                                                                            */\n/* ========================================================================================== */\n\nusing System;\nusing System.Text;\nusing System.Runtime.InteropServices;\n\nnamespace FMOD\n{\n/*$ preserve end $*/\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure for FMOD_DSP_PROCESS_CALLBACK input and output buffers.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        FMOD_DSP_DESCRIPTION\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_BUFFER_ARRAY\n    {\n        public int              numbuffers;              /* [r/w] number of buffers */\n        public int[]            buffernumchannels;       /* [r/w] array of number of channels for each buffer */\n        public CHANNELMASK[]    bufferchannelmask;       /* [r/w] array of channel masks for each buffer */\n        public IntPtr[]         buffers;                 /* [r/w] array of buffers */\n        public SPEAKERMODE      speakermode;             /* [r/w] speaker mode for all buffers in the array */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Operation type for FMOD_DSP_PROCESS_CALLBACK.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_DESCRIPTION\n    ]\n    */\n    public enum DSP_PROCESS_OPERATION\n    {\n        PROCESS_PERFORM = 0,               /* Process the incoming audio in 'inbufferarray' and output to 'outbufferarray'. */\n        PROCESS_QUERY                      /* The DSP is being queried for the expected output format and whether it needs to process audio or should be bypassed.  The function should return any value other than FMOD_OK if audio can pass through unprocessed. If audio is to be processed, 'outbufferarray' must be filled with the expected output format, channel count and mask. */\n    }\n\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Complex number structure used for holding FFT frequency domain-data for FMOD_FFTREAL and FMOD_IFFTREAL DSP callbacks.\n\n        [REMARKS]\n\n        [SEE_ALSO]    \n        FMOD_DSP_STATE_SYSTEMCALLBACKS\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct COMPLEX\n    {\n        public float real; /* Real component */\n        public float imag; /* Imaginary component */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Flags for the FMOD_DSP_PAN_SUM_SURROUND_MATRIX callback.\n\n        [REMARKS]\n        This functionality is experimental, please contact support@fmod.org for more information.\n\n        [SEE_ALSO]\n        FMOD_DSP_STATE_PAN_CALLBACKS\n    ]\n    */\n    public enum DSP_PAN_SURROUND_FLAGS\n    {\n        DEFAULT = 0,\n        ROTATION_NOT_BIASED = 1,\n    }\n\n    /*\n        DSP callbacks\n    */\n    public delegate RESULT DSP_CREATECALLBACK                   (ref DSP_STATE dsp_state);\n    public delegate RESULT DSP_RELEASECALLBACK                  (ref DSP_STATE dsp_state);\n    public delegate RESULT DSP_RESETCALLBACK                    (ref DSP_STATE dsp_state);\n    public delegate RESULT DSP_SETPOSITIONCALLBACK              (ref DSP_STATE dsp_state, uint pos);\n    public delegate RESULT DSP_READCALLBACK                     (ref DSP_STATE dsp_state, IntPtr inbuffer, IntPtr outbuffer, uint length, int inchannels, ref int outchannels);\n    public delegate RESULT DSP_SHOULDIPROCESS_CALLBACK          (ref DSP_STATE dsp_state, bool inputsidle, uint length, CHANNELMASK inmask, int inchannels, SPEAKERMODE speakermode);\n    public delegate RESULT DSP_PROCESS_CALLBACK                 (ref DSP_STATE dsp_state, uint length, ref DSP_BUFFER_ARRAY inbufferarray, ref DSP_BUFFER_ARRAY outbufferarray, bool inputsidle, DSP_PROCESS_OPERATION op);\n\n    public delegate RESULT DSP_SETPARAM_FLOAT_CALLBACK          (ref DSP_STATE dsp_state, int index, float value);\n    public delegate RESULT DSP_SETPARAM_INT_CALLBACK            (ref DSP_STATE dsp_state, int index, int value);\n    public delegate RESULT DSP_SETPARAM_BOOL_CALLBACK           (ref DSP_STATE dsp_state, int index, bool value);\n    public delegate RESULT DSP_SETPARAM_DATA_CALLBACK           (ref DSP_STATE dsp_state, int index, IntPtr data, uint length);\n    public delegate RESULT DSP_GETPARAM_FLOAT_CALLBACK          (ref DSP_STATE dsp_state, int index, ref float value, IntPtr valuestr);\n    public delegate RESULT DSP_GETPARAM_INT_CALLBACK            (ref DSP_STATE dsp_state, int index, ref int value, IntPtr valuestr);\n    public delegate RESULT DSP_GETPARAM_BOOL_CALLBACK           (ref DSP_STATE dsp_state, int index, ref bool value, IntPtr valuestr);\n    public delegate RESULT DSP_GETPARAM_DATA_CALLBACK           (ref DSP_STATE dsp_state, int index, ref IntPtr data, ref uint length, IntPtr valuestr);\n\n    public delegate RESULT DSP_SYSTEM_REGISTER_CALLBACK         (ref DSP_STATE dsp_state);\n    public delegate RESULT DSP_SYSTEM_DEREGISTER_CALLBACK       (ref DSP_STATE dsp_state);\n    public delegate RESULT DSP_SYSTEM_MIX_CALLBACK              (ref DSP_STATE dsp_state, int stage);\n\n    public delegate RESULT DSP_SYSTEM_GETSAMPLERATE             (ref DSP_STATE dsp_state, ref int rate);\n    public delegate RESULT DSP_SYSTEM_GETBLOCKSIZE              (ref DSP_STATE dsp_state, ref uint blocksize);\n    public delegate RESULT DSP_SYSTEM_GETSPEAKERMODE            (ref DSP_STATE dsp_state, ref int speakermode_mixer, ref int speakermode_output);\n\n    public delegate RESULT DSP_DFT_FFTREAL                      (ref DSP_STATE dsp_state, int size, IntPtr signal, IntPtr dft, IntPtr window, int signalhop);\n    public delegate RESULT DSP_DFT_IFFTREAL                     (ref DSP_STATE dsp_state, int size, IntPtr dft, IntPtr signal, IntPtr window, int signalhop);\n\n    public delegate RESULT DSP_PAN_SUM_MONO_MATRIX              (ref DSP_STATE dsp_state, int sourceSpeakerMode, float lowFrequencyGain, float overallGain, IntPtr matrix);\n    public delegate RESULT DSP_PAN_SUM_STEREO_MATRIX            (ref DSP_STATE dsp_state, int sourceSpeakerMode, float pan, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);\n    public delegate RESULT DSP_PAN_SUM_SURROUND_MATRIX          (ref DSP_STATE dsp_state, int sourceSpeakerMode, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix, DSP_PAN_SURROUND_FLAGS flags);\n    public delegate RESULT DSP_PAN_SUM_MONO_TO_SURROUND_MATRIX  (ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);\n    public delegate RESULT DSP_PAN_SUM_STEREO_TO_SURROUND_MATRIX(ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);\n    public delegate RESULT DSP_PAN_3D_GET_ROLLOFF_GAIN          (ref DSP_STATE dsp_state, DSP_PAN_3D_ROLLOFF_TYPE rolloff, float distance, float mindistance, float maxdistance, out float gain);\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        These definitions can be used for creating FMOD defined special effects or DSP units.\n\n        [REMARKS]\n        To get them to be active, first create the unit, then add it somewhere into the DSP network, either at the front of the network near the soundcard unit to affect the global output (by using System::getDSPHead), or on a single channel (using Channel::getDSPHead).\n\n        [SEE_ALSO]\n        System::createDSPByType\n    ]\n    */\n    public enum DSP_TYPE : int\n    {\n        UNKNOWN,            /* This unit was created via a non FMOD plugin so has an unknown purpose. */\n        MIXER,              /* This unit does nothing but take inputs and mix them together then feed the result to the soundcard unit. */\n        OSCILLATOR,         /* This unit generates sine/square/saw/triangle or noise tones. */\n        LOWPASS,            /* This unit filters sound using a high quality, resonant lowpass filter algorithm but consumes more CPU time. */\n        ITLOWPASS,          /* This unit filters sound using a resonant lowpass filter algorithm that is used in Impulse Tracker, but with limited cutoff range (0 to 8060hz). */\n        HIGHPASS,           /* This unit filters sound using a resonant highpass filter algorithm. */\n        ECHO,               /* This unit produces an echo on the sound and fades out at the desired rate. */\n        FADER,              /* This unit pans and scales the volume of a unit. */\n        FLANGE,             /* This unit produces a flange effect on the sound. */\n        DISTORTION,         /* This unit distorts the sound. */\n        NORMALIZE,          /* This unit normalizes or amplifies the sound to a certain level. */\n        LIMITER,            /* This unit limits the sound to a certain level. */\n        PARAMEQ,            /* This unit attenuates or amplifies a selected frequency range. */\n        PITCHSHIFT,         /* This unit bends the pitch of a sound without changing the speed of playback. */\n        CHORUS,             /* This unit produces a chorus effect on the sound. */\n        VSTPLUGIN,          /* This unit allows the use of Steinberg VST plugins */\n        WINAMPPLUGIN,       /* This unit allows the use of Nullsoft Winamp plugins */\n        ITECHO,             /* This unit produces an echo on the sound and fades out at the desired rate as is used in Impulse Tracker. */\n        COMPRESSOR,         /* This unit implements dynamic compression (linked multichannel, wideband) */\n        SFXREVERB,          /* This unit implements SFX reverb */\n        LOWPASS_SIMPLE,     /* This unit filters sound using a simple lowpass with no resonance, but has flexible cutoff and is fast. */\n        DELAY,              /* This unit produces different delays on individual channels of the sound. */\n        TREMOLO,            /* This unit produces a tremolo / chopper effect on the sound. */\n        LADSPAPLUGIN,       /* This unit allows the use of LADSPA standard plugins. */\n        SEND,               /* This unit sends a copy of the signal to a return DSP anywhere in the DSP tree. */\n        RETURN,             /* This unit receives signals from a number of send DSPs. */\n        HIGHPASS_SIMPLE,    /* This unit filters sound using a simple highpass with no resonance, but has flexible cutoff and is fast. */\n        PAN,                /* This unit pans the signal, possibly upmixing or downmixing as well. */\n        THREE_EQ,           /* This unit is a three-band equalizer. */\n        FFT,                /* This unit simply analyzes the signal and provides spectrum information back through getParameter. */\n        LOUDNESS_METER,     /* This unit analyzes the loudness and true peak of the signal. */\n        ENVELOPEFOLLOWER,   /* This unit tracks the envelope of the input/sidechain signal */\n        CONVOLUTIONREVERB,  /* This unit implements convolution reverb. */\n        CHANNELMIX,         /* This unit provides per signal channel gain, and output channel mapping to allow 1 multichannel signal made up of many groups of signals to map to a single output signal. */\n        TRANSCEIVER,        /* This unit 'sends' and 'receives' from a selection of up to 32 different slots.  It is like a send/return but it uses global slots rather than returns as the destination.  It also has other features.  Multiple transceivers can receive from a single channel, or multiple transceivers can send to a single channel, or a combination of both. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        DSP parameter types.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    public enum DSP_PARAMETER_TYPE\n    {\n        FLOAT = 0,\n        INT,\n        BOOL,\n        DATA,\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        DSP float parameter mappings. These determine how values are mapped across dials and automation curves.\n\n        [REMARKS]\n        FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_AUTO generates a mapping based on range and units. For example, if the units are in Hertz and the range is with-in the audio spectrum, a Bark scale will be chosen. Logarithmic scales may also be generated for ranges above zero spanning several orders of magnitude.\n\n        [SEE_ALSO]\n        FMOD_DSP_PARAMETER_FLOAT_MAPPING\n    ]\n    */\n    public enum DSP_PARAMETER_FLOAT_MAPPING_TYPE\n    {\n        DSP_PARAMETER_FLOAT_MAPPING_TYPE_LINEAR = 0,          /* Values mapped linearly across range. */\n        DSP_PARAMETER_FLOAT_MAPPING_TYPE_AUTO,                /* A mapping is automatically chosen based on range and units.  See remarks. */\n        DSP_PARAMETER_FLOAT_MAPPING_TYPE_PIECEWISE_LINEAR,    /* Values mapped in a piecewise linear fashion defined by FMOD_DSP_PARAMETER_DESC_FLOAT::mapping.piecewiselinearmapping. */\n    }\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Structure to define a piecewise linear mapping.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]    \n        FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE\n        FMOD_DSP_PARAMETER_FLOAT_MAPPING\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR\n    {\n        public int numpoints;                       /* [w] The number of <position, value> pairs in the piecewise mapping (at least 2). */\n        public IntPtr pointparamvalues;             /* [w] The values in the parameter's units for each point */\n        public IntPtr pointpositions;               /* [w] The positions along the control's scale (e.g. dial angle) corresponding to each parameter value.  The range of this scale is arbitrary and all positions will be relative to the minimum and maximum values (e.g. [0,1,3] is equivalent to [1,2,4] and [2,4,8]).  If this array is zero, pointparamvalues will be distributed with equal spacing. */\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure to define a mapping for a DSP unit's float parameter.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE\n        FMOD_DSP_PARAMETER_DESC_FLOAT\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_FLOAT_MAPPING\n    {\n        public DSP_PARAMETER_FLOAT_MAPPING_TYPE type;\n        public DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR piecewiselinearmapping;    /* [w] Only required for FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_PIECEWISE_LINEAR type mapping. */\n    }\n\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure to define a float parameter for a DSP unit.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        System::createDSP\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_PARAMETER_DESC\n        FMOD_DSP_PARAMETER_FLOAT_MAPPING\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_DESC_FLOAT\n    {\n        public float                     min;                      /* [w] Minimum parameter value. */\n        public float                     max;                      /* [w] Maximum parameter value. */\n        public float                     defaultval;               /* [w] Default parameter value. */\n        public DSP_PARAMETER_FLOAT_MAPPING mapping;           /* [w] How the values are distributed across dials and automation curves (e.g. linearly, exponentially etc). */\n    }\n\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure to define a int parameter for a DSP unit.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        System::createDSP\n        DSP::setParameterInt\n        DSP::getParameterInt\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_DESC_INT\n    {\n        public int                       min;                      /* [w] Minimum parameter value. */\n        public int                       max;                      /* [w] Maximum parameter value. */\n        public int                       defaultval;               /* [w] Default parameter value. */\n        public bool                      goestoinf;                /* [w] Whether the last value represents infiniy. */\n        public IntPtr                    valuenames;               /* [w] Names for each value.  There should be as many strings as there are possible values (max - min + 1).  Optional. */\n    }\n\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure to define a boolean parameter for a DSP unit.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        System::createDSP\n        DSP::setParameterBool\n        DSP::getParameterBool\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_DESC_BOOL\n    {\n        public bool                      defaultval;               /* [w] Default parameter value. */\n        public IntPtr                    valuenames;               /* [w] Names for false and true, respectively.  There should be two strings.  Optional. */\n    }\n\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        Structure to define a data parameter for a DSP unit.  Use 0 or above for custom types.  This parameter will be treated specially by the system if set to one of the FMOD_DSP_PARAMETER_DATA_TYPE values.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        System::createDSP\n        DSP::setParameterData\n        DSP::getParameterData\n        FMOD_DSP_PARAMETER_DATA_TYPE\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_DESC_DATA\n    {\n        public int                       datatype;                 /* [w] The type of data for this parameter.  Use 0 or above for custom types or set to one of the FMOD_DSP_PARAMETER_DATA_TYPE values. */\n    }\n\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n\n        [REMARKS]\n        Members marked with [w] mean the user sets the value before passing it to the function.\n        Members marked with [r] mean FMOD sets the value to be used after the function exits.\n        \n        The step parameter tells the gui or application that the parameter has a certain granularity.\n        For example in the example of cutoff frequency with a range from 100.0 to 22050.0 you might only want the selection to be in 10hz increments.  For this you would simply use 10.0 as the step value.\n        For a boolean, you can use min = 0.0, max = 1.0, step = 1.0.  This way the only possible values are 0.0 and 1.0.\n        Some applications may detect min = 0.0, max = 1.0, step = 1.0 and replace a graphical slider bar with a checkbox instead.\n        A step value of 1.0 would simulate integer values only.\n        A step value of 0.0 would mean the full floating point range is accessable.\n\n        [SEE_ALSO]\n        System::createDSP\n        System::getDSP\n    ]\n    */\n    [StructLayout(LayoutKind.Explicit)]\n    public struct DSP_PARAMETER_DESC_UNION\n    {\n        [FieldOffset(0)]\n        public DSP_PARAMETER_DESC_FLOAT   floatdesc;  /* [w] Struct containing information about the parameter in floating point format.  Use when type is FMOD_DSP_PARAMETER_TYPE_FLOAT. */\n        [FieldOffset(0)]\n        public DSP_PARAMETER_DESC_INT     intdesc;    /* [w] Struct containing information about the parameter in integer format.  Use when type is FMOD_DSP_PARAMETER_TYPE_INT. */\n        [FieldOffset(0)]\n        public DSP_PARAMETER_DESC_BOOL    booldesc;   /* [w] Struct containing information about the parameter in boolean format.  Use when type is FMOD_DSP_PARAMETER_TYPE_BOOL. */\n        [FieldOffset(0)]\n        public DSP_PARAMETER_DESC_DATA    datadesc;   /* [w] Struct containing information about the parameter in data format.  Use when type is FMOD_DSP_PARAMETER_TYPE_DATA. */\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_DESC\n    {\n        public DSP_PARAMETER_TYPE   type;            /* [w] Type of this parameter. */\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]\n        public char[]               name;            /* [w] Name of the parameter to be displayed (ie \"Cutoff frequency\"). */\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]\n        public char[]               label;           /* [w] Short string to be put next to value to denote the unit type (ie \"hz\"). */\n        public string               description;     /* [w] Description of the parameter to be displayed as a help item / tooltip for this parameter. */\n\n        public DSP_PARAMETER_DESC_UNION desc;\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Built-in types for the 'datatype' member of FMOD_DSP_PARAMETER_DESC_DATA.  Data parameters of type other than FMOD_DSP_PARAMETER_DATA_TYPE_USER will be treated specially by the system.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_PARAMETER_DESC_DATA\n        FMOD_DSP_PARAMETER_OVERALLGAIN\n        FMOD_DSP_PARAMETER_3DATTRIBUTES\n        FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI\n        FMOD_DSP_PARAMETER_SIDECHAIN\n    ]\n    */\n    public enum DSP_PARAMETER_DATA_TYPE\n    {\n        DSP_PARAMETER_DATA_TYPE_USER = 0,              /* The default data type.  All user data types should be 0 or above. */\n        DSP_PARAMETER_DATA_TYPE_OVERALLGAIN = -1,      /* The data type for FMOD_DSP_PARAMETER_OVERALLGAIN parameters.  There should a maximum of one per DSP. */\n        DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES = -2,     /* The data type for FMOD_DSP_PARAMETER_3DATTRIBUTES parameters.  There should a maximum of one per DSP. */\n        DSP_PARAMETER_DATA_TYPE_SIDECHAIN = -3,        /* The data type for FMOD_DSP_PARAMETER_SIDECHAIN parameters.  There should a maximum of one per DSP. */\n        DSP_PARAMETER_DATA_TYPE_FFT = -4,              /* The data type for FMOD_DSP_PARAMETER_FFT parameters.  There should a maximum of one per DSP. */\n        DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI = -5, /* The data type for FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI parameters.  There should a maximum of one per DSP. */\n    }\n\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Structure for data parameters of type FMOD_DSP_PARAMETER_DATA_TYPE_OVERALLGAIN.\n        A parameter of this type is used in effects that affect the overgain of the signal in a predictable way.\n        This parameter is read by the system to determine the effect's gain for voice virtualization.\n    \n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n    \n        [SEE_ALSO]    \n        FMOD_DSP_PARAMETER_DATA_TYPE\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_OVERALLGAIN\n    {\n        public float linear_gain;                                  /* [r] The overall linear gain of the effect on the direct signal path */\n        public float linear_gain_additive;                         /* [r] Additive gain, for parallel signal paths */\n    }\n    \n    \n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Structure for data parameters of type FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES.\n        A parameter of this type is used in effects that respond to a sound's 3D position.\n        The system will set this parameter automatically if a sound's position changes.\n    \n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n    \n        [SEE_ALSO]    \n        FMOD_DSP_PARAMETER_DATA_TYPE\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_3DATTRIBUTES\n    {\n        public _3D_ATTRIBUTES relative;                        /* [w] The position of the sound relative to the listener. */\n        public _3D_ATTRIBUTES absolute;                        /* [w] The position of the sound in world coordinates. */\n    }\n    \n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Structure for data parameters of type FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES.\n        A parameter of this type is used in effects that respond to a sound's 3D position.\n        The system will set this parameter automatically if a sound's position changes.\n    \n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n    \n        [SEE_ALSO]    \n        FMOD_DSP_PARAMETER_DATA_TYPE\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_3DATTRIBUTES_MULTI\n    {\n        public int            numlisteners;                    /* [w] The number of listeners. */\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]\n        public _3D_ATTRIBUTES[] relative;                      /* [w] The position of the sound relative to the listeners. */\n        public _3D_ATTRIBUTES absolute;                        /* [w] The position of the sound in world coordinates. */\n    }\n    \n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Structure for data parameters of type FMOD_DSP_PARAMETER_DATA_TYPE_SIDECHAIN.\n        A parameter of this type is declared for effects which support sidechaining.\n    \n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n    \n        [SEE_ALSO]    \n        FMOD_DSP_PARAMETER_DATA_TYPE\n        FMOD_DSP_PARAMETER_DESC\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_SIDECHAIN\n    {\n        public int sidechainenable;                               /* [r/w] Whether sidechains are enabled. */\n    }\n    \n    \n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Structure for data parameters of type FMOD_DSP_PARAMETER_DATA_TYPE_FFT.\n        A parameter of this type is declared for the FMOD_DSP_TYPE_FFT effect.\n    \n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n        \n        Notes on the spectrum data member.  Values inside the float buffer are typically between 0 and 1.0.\n        Each top level array represents one PCM channel of data.\n        Address data as spectrum[channel][bin].  A bin is 1 fft window entry.\n        Only read/display half of the buffer typically for analysis as the 2nd half is usually the same data reversed due to the nature of the way FFT works.\n    \n        [SEE_ALSO]    \n        FMOD_DSP_PARAMETER_DATA_TYPE\n        FMOD_DSP_PARAMETER_DESC\n        FMOD_DSP_PARAMETER_DATA_TYPE_FFT\n        FMOD_DSP_TYPE\n        FMOD_DSP_FFT\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_PARAMETER_FFT\n    {\n        public int     length;                                    /* [r] Number of entries in this spectrum window.   Divide this by the output rate to get the hz per entry. */\n        public int     numchannels;                               /* [r] Number of channels in spectrum. */\n        \n        [MarshalAs(UnmanagedType.ByValArray,SizeConst=32)]\n        private IntPtr[] spectrum_internal;                           /* [r] Per channel spectrum arrays.  See remarks for more. */\n        \n        public float[][] spectrum\n        {\n            get\n            {\n                var buffer = new float[numchannels][];\n                \n                for (int i = 0; i < numchannels; ++i)\n                {\n                    buffer[i] = new float[length];\n                    Marshal.Copy(spectrum_internal[i], buffer[i], 0, length);\n                }\n                \n                return buffer;\n            }\n        }\n    }\n\n    /*\n    [STRUCTURE]\n    [\n        [DESCRIPTION]\n        When creating a DSP unit, declare one of these and provide the relevant callbacks and name for FMOD to use when it creates and uses a DSP unit of this type.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n        \n        There are 2 different ways to change a parameter in this architecture.\n        One is to use DSP::setParameterFloat / DSP::setParameterInt / DSP::setParameterBool / DSP::setParameterData.  This is platform independant and is dynamic, so new unknown plugins can have their parameters enumerated and used.\n        The other is to use DSP::showConfigDialog.  This is platform specific and requires a GUI, and will display a dialog box to configure the plugin.\n\n        [SEE_ALSO]    \n        System::createDSP\n        DSP::setParameterFloat\n        DSP::setParameterInt\n        DSP::setParameterBool\n        DSP::setParameterData\n        FMOD_DSP_STATE\n        FMOD_DSP_CREATE_CALLBACK\n        FMOD_DSP_RELEASE_CALLBACK\n        FMOD_DSP_RESET_CALLBACK\n        FMOD_DSP_READ_CALLBACK\n        FMOD_DSP_PROCESS_CALLBACK\n        FMOD_DSP_SETPOSITION_CALLBACK\n        FMOD_DSP_PARAMETER_DESC\n        FMOD_DSP_SETPARAM_FLOAT_CALLBACK\n        FMOD_DSP_SETPARAM_INT_CALLBACK\n        FMOD_DSP_SETPARAM_BOOL_CALLBACK\n        FMOD_DSP_SETPARAM_DATA_CALLBACK\n        FMOD_DSP_GETPARAM_FLOAT_CALLBACK\n        FMOD_DSP_GETPARAM_INT_CALLBACK\n        FMOD_DSP_GETPARAM_BOOL_CALLBACK\n        FMOD_DSP_GETPARAM_DATA_CALLBACK\n        FMOD_DSP_SHOULDIPROCESS_CALLBACK\n        FMOD_DSP_SYSTEM_REGISTER_CALLBACK\n        FMOD_DSP_SYSTEM_DEREGISTER_CALLBACK\n        FMOD_DSP_SYSTEM_MIX_CALLBACK\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_DESCRIPTION\n    {\n        public uint                           pluginsdkversion;   /* [w] The plugin SDK version this plugin is built for.  set to this to FMOD_PLUGIN_SDK_VERSION defined above. */\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]\n        public char[]                         name;               /* [w] Name of the unit to be displayed in the network. */\n        public uint                           version;            /* [w] Plugin writer's version number. */\n        public int                            numinputbuffers;    /* [w] Number of input buffers to process.  Use 0 for DSPs that only generate sound and 1 for effects that process incoming sound. */\n        public int                            numoutputbuffers;   /* [w] Number of audio output buffers.  Only one output buffer is currently supported. */\n        public DSP_CREATECALLBACK             create;             /* [w] Create callback.  This is called when DSP unit is created.  Can be null. */\n        public DSP_RELEASECALLBACK            release;            /* [w] Release callback.  This is called just before the unit is freed so the user can do any cleanup needed for the unit.  Can be null. */\n        public DSP_RESETCALLBACK              reset;              /* [w] Reset callback.  This is called by the user to reset any history buffers that may need resetting for a filter, when it is to be used or re-used for the first time to its initial clean state.  Use to avoid clicks or artifacts. */\n        public DSP_READCALLBACK               read;               /* [w] Read callback.  Processing is done here.  Can be null. */\n        public DSP_PROCESS_CALLBACK           process;            /* [w] Process callback.  Can be specified instead of the read callback if any channel format changes occur between input and output.  This also replaces shouldiprocess and should return an error if the effect is to be bypassed.  Can be null. */\n        public DSP_SETPOSITIONCALLBACK        setposition;        /* [w] Setposition callback.  This is called if the unit wants to update its position info but not process data.  Can be null. */\n\n        public int                            numparameters;      /* [w] Number of parameters used in this filter.  The user finds this with DSP::getNumParameters */\n        public IntPtr                         paramdesc;          /* [w] Variable number of parameter structures. */\n        public DSP_SETPARAM_FLOAT_CALLBACK    setparameterfloat;  /* [w] This is called when the user calls DSP.setParameterFloat. Can be null. */\n        public DSP_SETPARAM_INT_CALLBACK      setparameterint;    /* [w] This is called when the user calls DSP.setParameterInt.   Can be null. */\n        public DSP_SETPARAM_BOOL_CALLBACK     setparameterbool;   /* [w] This is called when the user calls DSP.setParameterBool.  Can be null. */\n        public DSP_SETPARAM_DATA_CALLBACK     setparameterdata;   /* [w] This is called when the user calls DSP.setParameterData.  Can be null. */\n        public DSP_GETPARAM_FLOAT_CALLBACK    getparameterfloat;  /* [w] This is called when the user calls DSP.getParameterFloat. Can be null. */\n        public DSP_GETPARAM_INT_CALLBACK      getparameterint;    /* [w] This is called when the user calls DSP.getParameterInt.   Can be null. */\n        public DSP_GETPARAM_BOOL_CALLBACK     getparameterbool;   /* [w] This is called when the user calls DSP.getParameterBool.  Can be null. */\n        public DSP_GETPARAM_DATA_CALLBACK     getparameterdata;   /* [w] This is called when the user calls DSP.getParameterData.  Can be null. */\n        public DSP_SHOULDIPROCESS_CALLBACK    shouldiprocess;     /* [w] This is called before processing.  You can detect if inputs are idle and return FMOD_OK to process, or any other error code to avoid processing the effect.  Use a count down timer to allow effect tails to process before idling! */\n        public IntPtr                         userdata;           /* [w] Optional. Specify 0 to ignore. This is user data to be attached to the DSP unit during creation.  Access via DSP::getUserData. */\n\n        public DSP_SYSTEM_REGISTER_CALLBACK   sys_register;       /* [w] Register callback.  This is called when DSP unit is loaded/registered.  Useful for 'global'/per system object init for plugin.  Can be null. */\n        public DSP_SYSTEM_DEREGISTER_CALLBACK sys_deregister;     /* [w] Deregister callback.  This is called when DSP unit is unloaded/deregistered.  Useful as 'global'/per system object shutdown for plugin.  Can be null. */\n        public DSP_SYSTEM_MIX_CALLBACK        sys_mix;            /* [w] System mix stage callback.  This is called when the mixer starts to execute or is just finishing executing.  Useful for 'global'/per system object once a mix update calls for a plugin.  Can be null. */\n    }\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Struct containing DFT callbacks for plugins, to enable a plugin to perform optimized time-frequency domain conversion.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        FMOD_DSP_STATE_SYSTEMCALLBACKS\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_STATE_DFTCALLBACKS\n    {\n        public DSP_DFT_FFTREAL                            fftreal;        /* [r] Callback for performing an FFT on a real signal. */\n        public DSP_DFT_IFFTREAL                           inversefftreal; /* [r] Callback for performing an inverse FFT to get a real signal. */\n    }\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Struct containing panning helper callbacks for plugins.\n\n        [REMARKS]\n        These are experimental, please contact support@fmod.org for more information.\n\n        [SEE_ALSO]\n        FMOD_DSP_STATE_SYSTEMCALLBACKS\n        FMOD_PAN_SURROUND_FLAGS\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_STATE_PAN_CALLBACKS\n    {\n        public DSP_PAN_SUM_MONO_MATRIX                summonomatrix;\n        public DSP_PAN_SUM_STEREO_MATRIX              sumstereomatrix;\n        public DSP_PAN_SUM_SURROUND_MATRIX            sumsurroundmatrix;\n        public DSP_PAN_SUM_MONO_TO_SURROUND_MATRIX    summonotosurroundmatrix;\n        public DSP_PAN_SUM_STEREO_TO_SURROUND_MATRIX  sumstereotosurroundmatrix;\n        public DSP_PAN_3D_GET_ROLLOFF_GAIN            getrolloffgain;\n    }\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        Struct containing System level callbacks for plugins, to enable a plugin to query information about the system or allocate memory using FMOD's (and therefore possibly the game's) allocators.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        FMOD_DSP_STATE\n        FMOD_DSP_STATE_DFTCALLBACKS  \n        FMOD_DSP_STATE_PAN_CALLBACKS     \n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_STATE_SYSTEMCALLBACKS\n    {\n        MEMORY_ALLOC_CALLBACK              alloc;          /* [r] Memory allocation callback. Use this for all dynamic memory allocation within the plugin. */\n        MEMORY_REALLOC_CALLBACK            realloc;        /* [r] Memory reallocation callback. */\n        MEMORY_FREE_CALLBACK               free;           /* [r] Memory free callback. */\n        DSP_SYSTEM_GETSAMPLERATE           getsamplerate;  /* [r] Callback for getting the system samplerate. */\n        DSP_SYSTEM_GETBLOCKSIZE            getblocksize;   /* [r] Callback for getting the system's block size.  DSPs will be requested to process blocks of varying length up to this size.*/\n        IntPtr                             dft;            /* [r] Struct containing callbacks for performing FFTs and inverse FFTs. */\n        IntPtr                             pancallbacks;   /* [r] Pointer to a structure of callbacks for calculating pan, up-mix and down-mix matrices. */\n        DSP_SYSTEM_GETSPEAKERMODE          getspeakermode; /* [r] Callback for getting the system's speaker modes.  One is the mixer's default speaker mode, the other is the output mode the system is downmixing or upmixing to.*/\n    }\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        DSP plugin structure that is passed into each callback.\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n        \n        'systemobject' is an integer that relates to the System object that created the DSP or registered the DSP plugin.  If only 1 System object is created then it should be 0.  A second object would be 1 and so on.\n        FMOD_DSP_STATE_SYSTEMCALLBACKS::getsamplerate and FMOD_DSP_STATE_SYSTEMCALLBACKS::getblocksize could return different results so it could be relevant to plugin developers to monitor which object is being used.\n\n        [SEE_ALSO]\n        FMOD_DSP_DESCRIPTION\n        FMOD_DSP_STATE_SYSTEMCALLBACKS\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public struct DSP_STATE\n    {\n        public IntPtr     instance;            /* [r] Handle to the DSP hand the user created.  Not to be modified.  C++ users cast to FMOD::DSP to use.  */\n        public IntPtr     plugindata;          /* [r/w] Plugin writer created data the output author wants to attach to this object. */\n        public uint       channelmask;         /* [r] Specifies which speakers the DSP effect is active on */\n        public int        source_speakermode;  /* [r] Specifies which speaker mode the signal originated for information purposes, ie in case panning needs to be done differently. */\n        public IntPtr     sidechaindata;       /* [r] The mixed result of all incoming sidechains is stored at this pointer address. */\n        public int        sidechainchannels;   /* [r] The number of channels of pcm data stored within the sidechain buffer. */\n        public IntPtr     callbacks;           /* [r] Struct containing callbacks for system level functionality. */\n        public int        systemobject;        /* [r] FMOD::System object index, relating to the System object that created this DSP. */\n    }\n\n    /*\n    [STRUCTURE] \n    [\n        [DESCRIPTION]\n        DSP metering info used for retrieving metering info\n\n        [REMARKS]\n        Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only.  Do not change this value.\n        Members marked with [w] mean the variable can be written to.  The user can set the value.\n\n        [SEE_ALSO]\n        FMOD_SPEAKER\n    ]\n    */\n    [StructLayout(LayoutKind.Sequential)]\n    public class DSP_METERING_INFO\n    {\n        public int   numsamples;        /* [r] The number of samples considered for this metering info. */\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]\n        public float[] peaklevel;       /* [r] The peak level per channel. */\n        [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]\n        public float[] rmslevel;        /* [r] The rms level per channel. */\n        public short numchannels;       /* [r] Number of channels. */\n    }\n\n\n\n    /*\n        ==============================================================================================================\n\n        FMOD built in effect parameters.\n        Use DSP::setParameter with these enums for the 'index' parameter.\n\n        ==============================================================================================================\n    */\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_OSCILLATOR filter.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameter\n        DSP::getParameter\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_OSCILLATOR\n    {\n        TYPE,   /* Waveform type.  0 = sine.  1 = square. 2 = sawup. 3 = sawdown. 4 = triangle. 5 = noise.  */\n        RATE    /* Frequency of the sinewave in hz.  1.0 to 22000.0.  Default = 220.0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_LOWPASS filter.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameter\n        DSP::getParameter\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_LOWPASS\n    {\n        CUTOFF,    /* Lowpass cutoff frequency in hz.   1.0 to 22000.0.  Default = 5000.0. */\n        RESONANCE  /* Lowpass resonance Q value. 1.0 to 10.0.  Default = 1.0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_ITLOWPASS filter.\n        This is different to the default FMOD_DSP_TYPE_ITLOWPASS filter in that it uses a different quality algorithm and is\n        the filter used to produce the correct sounding playback in .IT files.\n        FMOD Ex's .IT playback uses this filter.\n\n        [REMARKS]\n        Note! This filter actually has a limited cutoff frequency below the specified maximum, due to its limited design,\n        so for a more  open range filter use FMOD_DSP_LOWPASS or if you don't mind not having resonance,\n        FMOD_DSP_LOWPASS_SIMPLE.\n        The effective maximum cutoff is about 8060hz.\n\n        [SEE_ALSO]\n        DSP::setParameter\n        DSP::getParameter\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_ITLOWPASS\n    {\n        CUTOFF,    /* Lowpass cutoff frequency in hz.  1.0 to 22000.0.  Default = 5000.0/ */\n        RESONANCE  /* Lowpass resonance Q value.  0.0 to 127.0.  Default = 1.0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_HIGHPASS filter.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameter\n        DSP::getParameter\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_HIGHPASS\n    {\n        CUTOFF,    /* (Type:float) - Highpass cutoff frequency in hz.  1.0 to output 22000.0.  Default = 5000.0. */\n        RESONANCE  /* (Type:float) - Highpass resonance Q value.  1.0 to 10.0.  Default = 1.0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_ECHO filter.\n\n        [REMARKS]\n        Note.  Every time the delay is changed, the plugin re-allocates the echo buffer.  This means the echo will dissapear at that time while it refills its new buffer.\n        Larger echo delays result in larger amounts of memory allocated.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_ECHO\n    {\n        DELAY,       /* (Type:float) - Echo delay in ms.  10  to 5000.  Default = 500. */\n        FEEDBACK,    /* (Type:float) - Echo decay per delay.  0 to 100.  100.0 = No decay, 0.0 = total decay (ie simple 1 line delay).  Default = 50.0. */\n        DRYLEVEL,    /* (Type:float) - Original sound volume in dB.  -80.0 to 10.0.  Default = 0. */\n        WETLEVEL     /* (Type:float) - Volume of echo signal to pass to output in dB.  -80.0 to 10.0.  Default = 0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_DELAY filter.\n\n        [REMARKS]\n        Note.  Every time MaxDelay is changed, the plugin re-allocates the delay buffer.  This means the delay will dissapear at that time while it refills its new buffer.\n        A larger MaxDelay results in larger amounts of memory allocated.\n        Channel delays above MaxDelay will be clipped to MaxDelay and the delay buffer will not be resized.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_DELAY\n    {\n        CH0,      /* Channel #0 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH1,      /* Channel #1 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH2,      /* Channel #2 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH3,      /* Channel #3 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH4,      /* Channel #4 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH5,      /* Channel #5 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH6,      /* Channel #6 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH7,      /* Channel #7 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH8,      /* Channel #8 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH9,      /* Channel #9 Delay in ms.   0  to 10000.  Default = 0.  */\n        CH10,     /* Channel #10 Delay in ms.  0  to 10000.  Default = 0.  */\n        CH11,     /* Channel #11 Delay in ms.  0  to 10000.  Default = 0.  */\n        CH12,     /* Channel #12 Delay in ms.  0  to 10000.  Default = 0.  */\n        CH13,     /* Channel #13 Delay in ms.  0  to 10000.  Default = 0.  */\n        CH14,     /* Channel #14 Delay in ms.  0  to 10000.  Default = 0.  */\n        CH15,     /* Channel #15 Delay in ms.  0  to 10000.  Default = 0.  */\n        MAXDELAY, /* Maximum delay in ms.      0  to 1000.   Default = 10. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_FLANGE filter.\n\n        [REMARKS]\n        Flange is an effect where the signal is played twice at the same time, and one copy slides back and forth creating a whooshing or flanging effect.\n        As there are 2 copies of the same signal, by default each signal is given 50% mix, so that the total is not louder than the original unaffected signal.\n        \n        Flange depth is a percentage of a 10ms shift from the original signal.  Anything above 10ms is not considered flange because to the ear it begins to 'echo' so 10ms is the highest value possible.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_FLANGE\n    {\n        MIX,         /* (Type:float) - Percentage of wet signal in mix.  0 to 100. Default = 50. */\n        DEPTH,       /* (Type:float) - Flange depth (percentage of 40ms delay).  0.01 to 1.0.  Default = 1.0. */\n        RATE         /* (Type:float) - Flange speed in hz.  0.0 to 20.0.  Default = 0.1. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_TREMOLO filter.\n\n        [REMARKS]\n        The tremolo effect varies the amplitude of a sound. Depending on the settings, this unit can produce a tremolo, chopper or auto-pan effect.\n        \n        The shape of the LFO (low freq. oscillator) can morphed between sine, triangle and sawtooth waves using the FMOD_DSP_TREMOLO_SHAPE and FMOD_DSP_TREMOLO_SKEW parameters.\n        FMOD_DSP_TREMOLO_DUTY and FMOD_DSP_TREMOLO_SQUARE are useful for a chopper-type effect where the first controls the on-time duration and second controls the flatness of the envelope.\n        FMOD_DSP_TREMOLO_SPREAD varies the LFO phase between channels to get an auto-pan effect. This works best with a sine shape LFO.\n        The LFO can be synchronized using the FMOD_DSP_TREMOLO_PHASE parameter which sets its instantaneous phase.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameter\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_TREMOLO\n    {\n        FREQUENCY,     /* LFO frequency in Hz.  0.1 to 20.  Default = 4. */\n        DEPTH,         /* Tremolo depth.  0 to 1.  Default = 0. */\n        SHAPE,         /* LFO shape morph between triangle and sine.  0 to 1.  Default = 0. */\n        SKEW,          /* Time-skewing of LFO cycle.  -1 to 1.  Default = 0. */\n        DUTY,          /* LFO on-time.  0 to 1.  Default = 0.5. */\n        SQUARE,        /* Flatness of the LFO shape.  0 to 1.  Default = 0. */\n        PHASE,         /* Instantaneous LFO phase.  0 to 1.  Default = 0. */\n        SPREAD         /* Rotation / auto-pan effect.  -1 to 1.  Default = 0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_DISTORTION filter.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_DISTORTION\n    {\n        LEVEL    /* Distortion value.  0.0 to 1.0.  Default = 0.5. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_NORMALIZE filter.\n\n        [REMARKS]\n        Normalize amplifies the sound based on the maximum peaks within the signal.\n        For example if the maximum peaks in the signal were 50% of the bandwidth, it would scale the whole sound by 2.\n        The lower threshold value makes the normalizer ignores peaks below a certain point, to avoid over-amplification if a loud signal suddenly came in, and also to avoid amplifying to maximum things like background hiss.\n        \n        Because FMOD is a realtime audio processor, it doesn't have the luxury of knowing the peak for the whole sound (ie it can't see into the future), so it has to process data as it comes in.\n        To avoid very sudden changes in volume level based on small samples of new data, fmod fades towards the desired amplification which makes for smooth gain control.  The fadetime parameter can control this.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameter\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_NORMALIZE\n    {\n        FADETIME,    /* Time to ramp the silence to full in ms.  0.0 to 20000.0. Default = 5000.0. */\n        THRESHHOLD,  /* Lower volume range threshold to ignore.  0.0 to 1.0.  Default = 0.1.  Raise higher to stop amplification of very quiet signals. */\n        MAXAMP       /* Maximum amplification allowed.  1.0 to 100000.0.  Default = 20.0.  1.0 = no amplifaction, higher values allow more boost. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_LIMITER filter.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_LIMITER\n    {\n        RELEASETIME,   /* (Type:float) - Time to ramp the silence to full in ms.  1.0 to 1000.0. Default = 10.0. */\n        CEILING,       /* (Type:float) - Maximum level of the output signal in dB.  -12.0 to 0.0.  Default = 0.0. */\n        MAXIMIZERGAIN, /* (Type:float) - Maximum amplification allowed in dB.  0.0 to 12.0.  Default = 0.0. 0.0 = no amplifaction, higher values allow more boost. */\n        MODE,          /* (Type:float) - Channel processing mode. 0 or 1. Default = 0. 0 = Independent (limiter per channel), 1 = Linked. */\n    }\n    \n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_PARAMEQ filter.\n\n        [REMARKS]\n        Parametric EQ is a bandpass filter that attenuates or amplifies a selected frequency and its neighbouring frequencies.\n        \n        To create a multi-band EQ create multiple FMOD_DSP_TYPE_PARAMEQ units and set each unit to different frequencies, for example 1000hz, 2000hz, 4000hz, 8000hz, 16000hz with a range of 1 octave each.\n        \n        When a frequency has its gain set to 1.0, the sound will be unaffected and represents the original signal exactly.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_PARAMEQ\n    {\n        CENTER,     /* Frequency center.  20.0 to 22000.0.  Default = 8000.0. */\n        BANDWIDTH,  /* Octave range around the center frequency to filter.  0.2 to 5.0.  Default = 1.0. */\n        GAIN        /* Frequency Gain.  0.05 to 3.0.  Default = 1.0.  */\n    }\n\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_PITCHSHIFT filter.\n\n        [REMARKS]\n        This pitch shifting unit can be used to change the pitch of a sound without speeding it up or slowing it down.\n        It can also be used for time stretching or scaling, for example if the pitch was doubled, and the frequency of the sound was halved, the pitch of the sound would sound correct but it would be twice as slow.\n        \n        Warning! This filter is very computationally expensive!  Similar to a vocoder, it requires several overlapping FFT and IFFT's to produce smooth output, and can require around 440mhz for 1 stereo 48khz signal using the default settings.\n        Reducing the signal to mono will half the cpu usage, as will the overlap count.\n        Reducing this will lower audio quality, but what settings to use are largely dependant on the sound being played.  A noisy polyphonic signal will need higher overlap and fft size compared to a speaking voice for example.\n        \n        This pitch shifter is based on the pitch shifter code at http://www.dspdimension.com, written by Stephan M. Bernsee.\n        The original code is COPYRIGHT 1999-2003 Stephan M. Bernsee <smb@dspdimension.com>.\n        \n        'maxchannels' dictates the amount of memory allocated.  By default, the maxchannels value is 0.  If FMOD is set to stereo, the pitch shift unit will allocate enough memory for 2 channels.  If it is 5.1, it will allocate enough memory for a 6 channel pitch shift, etc.\n        If the pitch shift effect is only ever applied to the global mix (ie it was added with System::addDSP), then 0 is the value to set as it will be enough to handle all speaker modes.\n        When the pitch shift is added to a channel (ie Channel::addDSP) then the channel count that comes in could be anything from 1 to 8 possibly.  It is only in this case where you might want to increase the channel count above the output's channel count.\n        If a channel pitch shift is set to a lower number than the sound's channel count that is coming in, it will not pitch shift the sound.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_PITCHSHIFT\n    {\n        PITCH,       /* Pitch value.  0.5 to 2.0.  Default = 1.0. 0.5 = one octave down, 2.0 = one octave up.  1.0 does not change the pitch. */\n        FFTSIZE,     /* FFT window size.  256, 512, 1024, 2048, 4096.  Default = 1024.  Increase this to reduce 'smearing'.  This effect is a warbling sound similar to when an mp3 is encoded at very low bitrates. */\n        OVERLAP,     /* Window overlap.  1 to 32.  Default = 4.  Increase this to reduce 'tremolo' effect.  Increasing it by a factor of 2 doubles the CPU usage. */\n        MAXCHANNELS  /* Maximum channels supported.  0 to 16.  0 = same as fmod's default output polyphony, 1 = mono, 2 = stereo etc.  See remarks for more.  Default = 0.  It is suggested to leave at 0! */\n    }\n\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_CHORUS filter.\n\n        [REMARKS]\n        Chorous is an effect where the sound is more 'spacious' due to 1 to 3 versions of the sound being played along side the original signal but with the pitch of each copy modulating on a sine wave.\n        This is a highly configurable chorus unit.  It supports 3 taps, small and large delay times and also feedback.\n        This unit also could be used to do a simple echo, or a flange effect.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_CHORUS\n    {\n        MIX,      /* (Type:float) - Volume of original signal to pass to output.  0.0 to 100.0. Default = 50.0. */\n        RATE,     /* (Type:float) - Chorus modulation rate in Hz.  0.0 to 20.0.  Default = 0.8 Hz. */\n        DEPTH,    /* (Type:float) - Chorus modulation depth.  0.0 to 100.0.  Default = 3.0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_ITECHO filter.\n        This is effectively a software based echo filter that emulates the DirectX DMO echo effect.  Impulse tracker files can support this, and FMOD will produce the effect on ANY platform, not just those that support DirectX effects!\n\n        [REMARKS]\n        Note.  Every time the delay is changed, the plugin re-allocates the echo buffer.  This means the echo will dissapear at that time while it refills its new buffer.\n        Larger echo delays result in larger amounts of memory allocated.\n        \n        As this is a stereo filter made mainly for IT playback, it is targeted for stereo signals.\n        With mono signals only the FMOD_DSP_ITECHO_LEFTDELAY is used.\n        For multichannel signals (>2) there will be no echo on those channels.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n        System::addDSP\n    ]\n    */\n    public enum DSP_ITECHO\n    {\n        WETDRYMIX,      /* (Type:float) - Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0.0 through 100.0 (all wet).  Default = 50. */\n        FEEDBACK,       /* (Type:float) - Percentage of output fed back into input, in the range from 0.0 through 100.0.  Default = 50. */\n        LEFTDELAY,      /* (Type:float) - Delay for left channel, in milliseconds, in the range from 1.0 through 2000.0.  Default = 500 ms. */\n        RIGHTDELAY,     /* (Type:float) - Delay for right channel, in milliseconds, in the range from 1.0 through 2000.0.  Default = 500 ms. */\n        PANDELAY        /* (Type:float) - Value that specifies whether to swap left and right delays with each successive echo.  Ranges from 0.0 (equivalent to FALSE) to 1.0 (equivalent to TRUE), meaning no swap.  Default = 0.  CURRENTLY NOT SUPPORTED. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_COMPRESSOR unit.\n        This is a multichannel software limiter that is uniform across the whole spectrum.\n\n        [REMARKS]\n        The limiter is not guaranteed to catch every peak above the threshold level,\n        because it cannot apply gain reduction instantaneously - the time delay is\n        determined by the attack time. However setting the attack time too short will\n        distort the sound, so it is a compromise. High level peaks can be avoided by\n        using a short attack time - but not too short, and setting the threshold a few\n        decibels below the critical level.\n        \n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        DSP::setParameterBool\n        DSP::getParameterBool\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_COMPRESSOR\n    {\n        THRESHOLD,   /* (Type:float) - Threshold level (dB) in the range from -80 through 0. The default value is 0. */ \n        RATIO,       /* (Type:float) - Compression Ratio (dB/dB) in the range from 1 to 50. The default value is 2.5. */ \n        ATTACK,      /* (Type:float) - Attack time (milliseconds), in the range from 0.1 through 1000. The default value is 20. */\n        RELEASE,     /* (Type:float) - Release time (milliseconds), in the range from 10 through 5000. The default value is 100 */\n        GAINMAKEUP,  /* (Type:float) - Make-up gain (dB) applied after limiting, in the range from 0 through 30. The default value is 0. */\n        USESIDECHAIN,/* (Type:bool)  - Whether to analyse the sidechain signal instead of the input signal. The default value is false */\n        LINKED       /* (Type:bool)  - FALSE = Independent (compressor per channel), TRUE = Linked.  The default value is TRUE. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_SFXREVERB unit.\n\n        [REMARKS]\n        This is a high quality I3DL2 based reverb.\n        On top of the I3DL2 property set, \"Dry Level\" is also included to allow the dry mix to be changed.\n        \n        These properties can be set with presets in FMOD_REVERB_PRESETS.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n        FMOD_REVERB_PRESETS\n    ]\n    */\n    public enum DSP_SFXREVERB\n    {\n        DECAYTIME,           /* (Type:float) - Decay Time       : Reverberation decay time at low-frequencies in milliseconds.  Ranges from 100.0 to 20000.0. Default is 1500. */\n        EARLYDELAY,          /* (Type:float) - Early Delay      : Delay time of first reflection in milliseconds.  Ranges from 0.0 to 300.0.  Default is 20. */\n        LATEDELAY,           /* (Type:float) - Reverb Delay     : Late reverberation delay time relative to first reflection in milliseconds.  Ranges from 0.0 to 100.0.  Default is 40. */\n        HFREFERENCE,         /* (Type:float) - HF Reference     : Reference frequency for high-frequency decay in Hz.  Ranges from 20.0 to 20000.0. Default is 5000. */\n        HFDECAYRATIO,        /* (Type:float) - Decay HF Ratio   : High-frequency decay time relative to decay time in percent.  Ranges from 10.0 to 100.0. Default is 50. */\n        DIFFUSION,           /* (Type:float) - Diffusion        : Reverberation diffusion (echo density) in percent.  Ranges from 0.0 to 100.0.  Default is 100. */\n        DENSITY,             /* (Type:float) - Density          : Reverberation density (modal density) in percent.  Ranges from 0.0 to 100.0.  Default is 100. */\n        LOWSHELFFREQUENCY,   /* (Type:float) - Low Shelf Frequency : Transition frequency of low-shelf filter in Hz.  Ranges from 20.0 to 1000.0. Default is 250. */\n        LOWSHELFGAIN,        /* (Type:float) - Low Shelf Gain   : Gain of low-shelf filter in dB.  Ranges from -36.0 to 12.0.  Default is 0. */\n        HIGHCUT,             /* (Type:float) - High Cut         : Cutoff frequency of low-pass filter in Hz.  Ranges from 20.0 to 20000.0. Default is 20000. */\n        EARLYLATEMIX,        /* (Type:float) - Early/Late Mix   : Blend ratio of late reverb to early reflections in percent.  Ranges from 0.0 to 100.0.  Default is 50. */\n        WETLEVEL,            /* (Type:float) - Wet Level        : Reverb signal level in dB.  Ranges from -80.0 to 20.0.  Default is -6. */\n        DRYLEVEL             /* (Type:float) - Dry Level        : Dry signal level in dB.  Ranges from -80.0 to 20.0.  Default is 0. */\n    }\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_LOWPASS_SIMPLE filter.\n        This is a very simple low pass filter, based on two single-pole RC time-constant modules.\n        The emphasis is on speed rather than accuracy, so this should not be used for task requiring critical filtering.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_LOWPASS_SIMPLE\n    {\n        CUTOFF     /* Lowpass cutoff frequency in hz.  10.0 to 22000.0.  Default = 5000.0 */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_SEND DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterInt\n        DSP::getParameterInt\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_SEND\n    {\n        RETURNID,     /* (Type:int) - ID of the Return DSP this send is connected to (integer values only). -1 indicates no connected Return DSP. Default = -1. */\n        LEVEL,        /* (Type:float) - Send level. 0.0 to 1.0. Default = 1.0 */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_RETURN DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterInt\n        DSP::getParameterInt\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_RETURN\n    {\n        ID,                 /* (Type:int) - ID of this Return DSP. Read-only.  Default = -1. */\n        INPUT_SPEAKER_MODE  /* (Type:int) - Input speaker mode of this return.  Default = FMOD_SPEAKERMODE_DEFAULT. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_HIGHPASS_SIMPLE filter.\n        This is a very simple single-order high pass filter.\n        The emphasis is on speed rather than accuracy, so this should not be used for task requiring critical filtering. \n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_HIGHPASS_SIMPLE\n    {\n        CUTOFF     /* (Type:float) - Highpass cutoff frequency in hz.  10.0 to 22000.0.  Default = 1000.0 */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter values for the FMOD_DSP_PAN_SURROUND_FROM_STEREO_MODE parameter of the FMOD_DSP_TYPE_PAN DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_PAN\n    ]\n    */\n    public enum DSP_PAN_SURROUND_FROM_STEREO_MODE_TYPE\n    {\n        DISTRIBUTED,\n        DISCRETE\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter values for the FMOD_DSP_PAN_MODE parameter of the FMOD_DSP_TYPE_PAN DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_PAN\n    ]\n    */\n    public enum DSP_PAN_MODE_TYPE\n    {\n        MONO,\n        STEREO,\n        SURROUND\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter values for the FMOD_DSP_PAN_3D_ROLLOFF parameter of the FMOD_DSP_TYPE_PAN DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_PAN\n    ]\n    */\n    public enum DSP_PAN_3D_ROLLOFF_TYPE\n    {\n        LINEARSQUARED,\n        LINEAR,\n        INVERSE,\n        INVERSETAPERED,\n        CUSTOM\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter values for the FMOD_DSP_PAN_3D_EXTENT_MODE parameter of the FMOD_DSP_TYPE_PAN DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_PAN\n    ]\n    */\n    public enum DSP_PAN_3D_EXTENT_MODE_TYPE\n    {\n        AUTO,\n        USER,\n        OFF\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_PAN DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        DSP::setParameterInt\n        DSP::getParameterInt\n        DSP::setParameterData\n        DSP::getParameterData\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_PAN\n    {\n        MODE,                           /* (Type:int)   - Panner mode.              FMOD_DSP_PAN_MODE_MONO for mono down-mix, FMOD_DSP_PAN_MODE_STEREO for stereo panning or FMOD_DSP_PAN_MODE_SURROUND for surround panning.  Default = FMOD_DSP_PAN_MODE_SURROUND */\n        STEREO_POSITION,                /* (Type:float) - Stereo pan position       STEREO_POSITION_MIN to STEREO_POSITION_MAX.  Default = 0.0. */\n        SURROUND_DIRECTION,             /* (Type:float) - Surround pan direction    ROTATION_MIN to ROTATION_MAX.  Default = 0.0. */\n        SURROUND_EXTENT,                /* (Type:float) - Surround pan extent       EXTENT_MIN to EXTENT_MAX.  Default = 360.0. */\n        SURROUND_ROTATION,              /* (Type:float) - Surround pan rotation     ROTATION_MIN to ROTATION_MAX.  Default = 0.0. */\n        SURROUND_LFE_LEVEL,             /* (Type:float) - Surround pan LFE level    SURROUND_LFE_LEVEL_MIN to SURROUND_LFE_LEVEL_MAX.  Default = 0.0. */\n        SURROUND_FROM_STEREO_MODE,      /* (Type:int)   - Stereo-To-Surround Mode   FMOD_DSP_PAN_SURROUND_FROM_STEREO_MODE_DISTRIBUTED to FMOD_DSP_PAN_SURROUND_FROM_STEREO_MODE_DISCRETE.  Default = FMOD_DSP_PAN_SURROUND_FROM_STEREO_MODE_DISCRETE. */\n        SURROUND_STEREO_SEPARATION,     /* (Type:float) - Stereo-To-Surround Stereo Separation. ROTATION_MIN to ROTATION_MAX.  Default = 60.0. */\n        SURROUND_STEREO_AXIS,           /* (Type:float) - Stereo-To-Surround Stereo Axis. ROTATION_MIN to ROTATION_MAX.  Default = 0.0. */\n        ENABLED_SURROUND_SPEAKERS,      /* (Type:int)   - Surround Speakers Enabled. 0 to 0xFFF.  Default = 0xFFF.  */\n        _3D_POSITION,                   /* (Type:data)  - 3D Position               data of type FMOD_DSP_PARAMETER_DATA_TYPE_3DPOS */\n        _3D_ROLLOFF,                    /* (Type:int)   - 3D Rolloff                FMOD_DSP_PAN_3D_ROLLOFF_LINEARSQUARED to FMOD_DSP_PAN_3D_ROLLOFF_CUSTOM.  Default = FMOD_DSP_PAN_3D_ROLLOFF_LINEARSQUARED. */\n        _3D_MIN_DISTANCE,               /* (Type:float) - 3D Min Distance           0.0 to GAME_UNITS_MAX.  Default = 1.0. */\n        _3D_MAX_DISTANCE,               /* (Type:float) - 3D Max Distance           0.0 to GAME_UNITS_MAX.  Default = 20.0. */\n        _3D_EXTENT_MODE,                /* (Type:int)   - 3D Extent Mode            FMOD_DSP_PAN_3D_EXTENT_MODE_AUTO to FMOD_DSP_PAN_3D_EXTENT_MODE_OFF.  Default = FMOD_DSP_PAN_3D_EXTENT_MODE_AUTO. */\n        _3D_SOUND_SIZE,                 /* (Type:float) - 3D Sound Size             0.0 to GAME_UNITS_MAX.  Default = 0.0. */\n        _3D_MIN_EXTENT,                 /* (Type:float) - 3D Min Extent             EXTENT_MIN to EXTENT_MAX.  Default = 0.0. */\n        _3D_PAN_BLEND,                  /* (Type:float) - 3D Pan Blend              PAN_BLEND_MIN to PAN_BLEND_MAX.  Default = 0.0. */\n        LFE_UPMIX_ENABLED,              /* (Type:int)   - LFE Upmix Enabled         0 to 1.  Default = 0. */\n        OVERALL_GAIN,                   /* (Type:data)  - Overall Gain              data of type FMOD_DSP_PARAMETER_DATA_TYPE_OVERALLGAIN */\n        SURROUND_SPEAKER_MODE           /* (Type:int)   - Surround speaker mode.    Target speaker mode for surround panning.  Default = FMOD_SPEAKERMODE_DEFAULT. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter values for the FMOD_DSP_THREE_EQ_CROSSOVERSLOPE parameter of the FMOD_DSP_TYPE_THREE_EQ DSP.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        FMOD_DSP_THREE_EQ\n    ]\n    */\n    public enum DSP_THREE_EQ_CROSSOVERSLOPE_TYPE\n    {\n        _12DB,\n        _24DB,\n        _48DB\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_THREE_EQ filter.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        DSP::setParameterInt\n        DSP::getParameterInt\n        FMOD_DSP_TYPE\n        FMOD_DSP_THREE_EQ_CROSSOVERSLOPE_TYPE\n    ]\n    */\n    public enum DSP_THREE_EQ\n    {\n        LOWGAIN,       /* (Type:float) - Low frequency gain in dB.  -80.0 to 10.0.  Default = 0. */\n        MIDGAIN,       /* (Type:float) - Mid frequency gain in dB.  -80.0 to 10.0.  Default = 0. */\n        HIGHGAIN,      /* (Type:float) - High frequency gain in dB.  -80.0 to 10.0.  Default = 0. */\n        LOWCROSSOVER,  /* (Type:float) - Low-to-mid crossover frequency in Hz.  10.0 to 22000.0.  Default = 400.0. */\n        HIGHCROSSOVER, /* (Type:float) - Mid-to-high crossover frequency in Hz.  10.0 to 22000.0.  Default = 4000.0. */\n        CROSSOVERSLOPE /* (Type:int)   - Crossover Slope.  0 = 12dB/Octave, 1 = 24dB/Octave, 2 = 48dB/Octave.  Default = 1 (24dB/Octave). */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        List of windowing methods for the FMOD_DSP_TYPE_FFT unit.  Used in spectrum analysis to reduce leakage / transient signals intefering with the analysis.\n        This is a problem with analysis of continuous signals that only have a small portion of the signal sample (the fft window size).\n        Windowing the signal with a curve or triangle tapers the sides of the fft window to help alleviate this problem.\n\n        [REMARKS]\n        Cyclic signals such as a sine wave that repeat their cycle in a multiple of the window size do not need windowing.\n        I.e. If the sine wave repeats every 1024, 512, 256 etc samples and the FMOD fft window is 1024, then the signal would not need windowing.\n        Not windowing is the same as FMOD_DSP_FFT_WINDOW_RECT, which is the default.\n        If the cycle of the signal (ie the sine wave) is not a multiple of the window size, it will cause frequency abnormalities, so a different windowing method is needed.\n        \n        FMOD_DSP_FFT_WINDOW_RECT.\n        <img src=\"..\\static\\overview\\rectangle.gif\"></img>\n        \n        FMOD_DSP_FFT_WINDOW_TRIANGLE.\n        <img src=\"..\\static\\overview\\triangle.gif\"></img>\n        \n        FMOD_DSP_FFT_WINDOW_HAMMING.\n        <img src=\"..\\static\\overview\\hamming.gif\"></img>\n        \n        FMOD_DSP_FFT_WINDOW_HANNING.\n        <img src=\"..\\static\\overview\\hanning.gif\"></img>\n        \n        FMOD_DSP_FFT_WINDOW_BLACKMAN.\n        <img src=\"..\\static\\overview\\blackman.gif\"></img>\n        \n        FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS.\n        <img src=\"..\\static\\overview\\blackmanharris.gif\"></img>\n    \n        [SEE_ALSO]\n        FMOD_DSP_FFT\n    ]\n    */\n    public enum DSP_FFT_WINDOW\n    {\n        RECT,            /* w[n] = 1.0                                                                                            */\n        TRIANGLE,        /* w[n] = TRI(2n/N)                                                                                      */\n        HAMMING,         /* w[n] = 0.54 - (0.46 * COS(n/N) )                                                                      */\n        HANNING,         /* w[n] = 0.5 *  (1.0  - COS(n/N) )                                                                      */\n        BLACKMAN,        /* w[n] = 0.42 - (0.5  * COS(n/N) ) + (0.08 * COS(2.0 * n/N) )                                           */\n        BLACKMANHARRIS   /* w[n] = 0.35875 - (0.48829 * COS(1.0 * n/N)) + (0.14128 * COS(2.0 * n/N)) - (0.01168 * COS(3.0 * n/N)) */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_FFT dsp effect.\n\n        [REMARKS]\n        Set the attributes for the spectrum analysis with FMOD_DSP_FFT_WINDOWSIZE and FMOD_DSP_FFT_WINDOWTYPE, and retrieve the results with FMOD_DSP_FFT_SPECTRUM and FMOD_DSP_FFT_DOMINANT_FREQ.\n        FMOD_DSP_FFT_SPECTRUM stores its data in the FMOD_DSP_PARAMETER_DATA_TYPE_FFT.  You will need to cast to this structure to get the right data.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        DSP::setParameterInt\n        DSP::getParameterInt\n        DSP::setParameterData\n        DSP::getParameterData\n        FMOD_DSP_TYPE\n        FMOD_DSP_FFT_WINDOW\n    ]\n    */\n    public enum DSP_FFT\n    {\n        WINDOWSIZE,            /*  (Type:int)   - [r/w] Must be a power of 2 between 128 and 16384.  128, 256, 512, 1024, 2048, 4096, 8192, 16384 are accepted.  Default = 2048. */\n        WINDOWTYPE,            /*  (Type:int)   - [r/w] Refer to FMOD_DSP_FFT_WINDOW enumeration.  Default = FMOD_DSP_FFT_WINDOW_HAMMING. */\n        SPECTRUMDATA,          /*  (Type:data)  - [r]   Returns the current spectrum values between 0 and 1 for each 'fft bin'.  Cast data to FMOD_DSP_PARAMETER_DATA_TYPE_FFT.  Divide the niquist rate by the window size to get the hz value per entry. */\n        DOMINANT_FREQ          /*  (Type:float) - [r]   Returns the dominant frequencies for each channel. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_ENVELOPEFOLLOWER unit.\n        This is a simple envelope follower for tracking the signal level.\n\n        [REMARKS]\n        This unit does not affect the incoming signal\n        \n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        DSP::setParameterBool\n        DSP::getParameterBool\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_ENVELOPEFOLLOWER\n    {\n        ATTACK,      /* (Type:float) - Attack time (milliseconds), in the range from 0.1 through 1000. The default value is 20. */\n        RELEASE,     /* (Type:float) - Release time (milliseconds), in the range from 10 through 5000. The default value is 100 */\n        ENVELOPE,    /* (Type:float) - Current value of the envelope, in the range 0 to 1. Read-only. */\n        USESIDECHAIN /* (Type:bool)  - Whether to analyse the sidechain signal instead of the input signal. The default value is false */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_CHORUS filter.\n\n        [REMARKS]\n        Convolution Reverb reverb IR.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        DSP::setParameterData\n        DSP::getParameterData\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_CONVOLUTION_REVERB\n    {\n        IR,       /* (Type:data)  - [w]   16-bit reverb IR (short*) with an extra sample prepended to the start which specifies the number of channels. */\n        WET,      /* (Type:float) - [r/w] Volume of echo signal to pass to output in dB.  -80.0 to 10.0.  Default = 0. */\n        DRY       /* (Type:float) - [r/w] Original sound volume in dB.  -80.0 to 10.0.  Default = 0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_CHANNELMIX_OUTPUTGROUPING parameter for FMOD_DSP_TYPE_CHANNELMIX effect.\n\n        [REMARKS]\n\n        [SEE_ALSO]\n        DSP::setParameterInt\n        DSP::getParameterInt\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_CHANNELMIX_OUTPUT\n    {\n        DEFAULT,      /*  Output channel count = input channel count.  Mapping: See FMOD_SPEAKER enumeration. */\n        ALLMONO,      /*  Output channel count = 1.  Mapping: Mono, Mono, Mono, Mono, Mono, Mono, ... (each channel all the way up to FMOD_MAX_CHANNEL_WIDTH channels are treated as if they were mono) */\n        ALLSTEREO,    /*  Output channel count = 2.  Mapping: Left, Right, Left, Right, Left, Right, ... (each pair of channels is treated as stereo all the way up to FMOD_MAX_CHANNEL_WIDTH channels) */\n        ALLQUAD,      /*  Output channel count = 4.  Mapping: Repeating pattern of Front Left, Front Right, Surround Left, Surround Right. */\n        ALL5POINT1,   /*  Output channel count = 6.  Mapping: Repeating pattern of Front Left, Front Right, Center, LFE, Surround Left, Surround Right. */\n        ALL7POINT1,   /*  Output channel count = 8.  Mapping: Repeating pattern of Front Left, Front Right, Center, LFE, Surround Left, Surround Right, Back Left, Back Right.  */\n        ALLLFE        /*  Output channel count = 6.  Mapping: Repeating pattern of LFE in a 5.1 output signal.  */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_CHANNELMIX filter.\n\n        [REMARKS]\n        For FMOD_DSP_CHANNELMIX_OUTPUTGROUPING, this value will set the output speaker format for the DSP, and also map the incoming channels to the \n        outgoing channels in a round-robin fashion.  Use this for example play a 32 channel input signal as if it were a repeating group of output signals.\n        Ie.\n        FMOD_DSP_CHANNELMIX_OUTPUT_ALLMONO    = all incoming channels are mixed to a mono output.\n        FMOD_DSP_CHANNELMIX_OUTPUT_ALLSTEREO  = all incoming channels are mixed to a stereo output, ie even incoming channels 0,2,4,6,etc are mixed to left, and odd incoming channels 1,3,5,7,etc are mixed to right.\n        FMOD_DSP_CHANNELMIX_OUTPUT_ALL5POINT1 = all incoming channels are mixed to a 5.1 output.  If there are less than 6 coming in, it will just fill the first n channels in the 6 output channels.   \n                                                 If there are more, then it will repeat the input pattern to the output like it did with the stereo case, ie 12 incoming channels are mapped as 0-5 mixed to the \n                                                 5.1 output and 6 to 11 mapped to the 5.1 output.\n        FMOD_DSP_CHANNELMIX_OUTPUT_ALLLFE     = all incoming channels are mixed to a 5.1 output but via the LFE channel only.\n\n\n        [SEE_ALSO]\n        DSP::setParameterInt\n        DSP::getParameterInt\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_CHANNELMIX\n    {\n        OUTPUTGROUPING,     /* (Type:int)   - Refer to FMOD_DSP_CHANNELMIX_OUTPUT enumeration.  Default = FMOD_DSP_CHANNELMIX_OUTPUT_DEFAULT.  See remarks. */\n        GAIN_CH0,           /* (Type:float) - Channel  #0 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH1,           /* (Type:float) - Channel  #1 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH2,           /* (Type:float) - Channel  #2 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH3,           /* (Type:float) - Channel  #3 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH4,           /* (Type:float) - Channel  #4 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH5,           /* (Type:float) - Channel  #5 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH6,           /* (Type:float) - Channel  #6 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH7,           /* (Type:float) - Channel  #7 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH8,           /* (Type:float) - Channel  #8 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH9,           /* (Type:float) - Channel  #9 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH10,          /* (Type:float) - Channel #10 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH11,          /* (Type:float) - Channel #11 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH12,          /* (Type:float) - Channel #12 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH13,          /* (Type:float) - Channel #13 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH14,          /* (Type:float) - Channel #14 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH15,          /* (Type:float) - Channel #15 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH16,          /* (Type:float) - Channel #16 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH17,          /* (Type:float) - Channel #17 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH18,          /* (Type:float) - Channel #18 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH19,          /* (Type:float) - Channel #19 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH20,          /* (Type:float) - Channel #20 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH21,          /* (Type:float) - Channel #21 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH22,          /* (Type:float) - Channel #22 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH23,          /* (Type:float) - Channel #23 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH24,          /* (Type:float) - Channel #24 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH25,          /* (Type:float) - Channel #25 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH26,          /* (Type:float) - Channel #26 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH27,          /* (Type:float) - Channel #27 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH28,          /* (Type:float) - Channel #28 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH29,          /* (Type:float) - Channel #29 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH30,          /* (Type:float) - Channel #30 gain in dB.  -80.0 to 10.0.  Default = 0. */\n        GAIN_CH31           /* (Type:float) - Channel #31 gain in dB.  -80.0 to 10.0.  Default = 0. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TRANSCEIVER_SPEAKERMODE parameter for FMOD_DSP_TYPE_TRANSCEIVER effect.\n\n        [REMARKS]\n        The speaker mode of a transceiver buffer (of which there are up to 32 of) is determined automatically depending on the signal flowing through the transceiver effect, or it can be forced.\n        Use a smaller fixed speaker mode buffer to save memory.\n\n        Only relevant for transmitter dsps, as they control the format of the transceiver channel's buffer.\n\n        If multiple transceivers transmit to a single buffer in different speaker modes, it will allocate memory for each speaker mode.   This uses more memory than a single speaker mode.\n        If there are multiple receivers reading from a channel with multiple speaker modes, it will read them all and mix them together.\n\n        If the system's speaker mode is stereo or mono, it will not create a 3rd buffer, it will just use the mono/stereo speaker mode buffer.\n\n        [SEE_ALSO]\n        DSP::setParameterInt\n        DSP::getParameterInt\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_TRANSCEIVER_SPEAKERMODE\n    {\n        AUTO = -1,     /* A transmitter will use whatever signal channel count coming in to the transmitter, to determine which speaker mode is allocated for the transceiver channel. */\n        MONO = 0,      /* A transmitter will always downmix to a mono channel buffer. */\n        STEREO,        /* A transmitter will always upmix or downmix to a stereo channel buffer. */\n        SURROUND,      /* A transmitter will always upmix or downmix to a surround channel buffer.   Surround is the speaker mode of the system above stereo, so could be quad/surround/5.1/7.1. */\n    }\n\n\n    /*\n    [ENUM]\n    [\n        [DESCRIPTION]\n        Parameter types for the FMOD_DSP_TYPE_TRANSCEIVER filter.\n\n        [REMARKS]\n        The transceiver only transmits and receives to a global array of 32 channels.   The transceiver can be set to receiver mode (like a return) and can receive the signal at a variable gain (FMOD_DSP_TRANSCEIVER_GAIN).\n        The transceiver can also be set to transmit to a chnnel (like a send) and can transmit the signal with a variable gain (FMOD_DSP_TRANSCEIVER_GAIN).\n    \n        The FMOD_DSP_TRANSCEIVER_TRANSMITSPEAKERMODE is only applicable to the transmission format, not the receive format.   This means this parameter is ignored in 'receive mode'.  This allows receivers to receive at\n        the speaker mode of the user's choice.   Receiving from a mono channel, is cheaper than receiving from a surround channel for example.\n        The 3 speaker modes FMOD_DSP_TRANSCEIVER_SPEAKERMODE_MONO, FMOD_DSP_TRANSCEIVER_SPEAKERMODE_STEREO, FMOD_DSP_TRANSCEIVER_SPEAKERMODE_SURROUND are stored as seperate buffers in memory for a tranmitter channel.\n        To save memory, use 1 common speaker mode for a transmitter.\n\n        The transceiver is double buffered to avoid desyncing of transmitters and receivers.   This means there will be a 1 block delay on a receiver, compared to the data sent from a transmitter.\n\n        Multiple transmitters sending to the same channel will be mixed together.\n\n        [SEE_ALSO]\n        DSP::setParameterFloat\n        DSP::getParameterFloat\n        DSP::setParameterInt\n        DSP::getParameterInt\n        DSP::setParameterBool\n        DSP::getParameterBool\n        FMOD_DSP_TYPE\n    ]\n    */\n    public enum DSP_TRANSCEIVER\n    {\n        TRANSMIT,            /* (Type:bool)  - [r/w] - FALSE = Transceiver is a 'receiver' (like a return) and accepts data from a channel.  TRUE = Transceiver is a 'transmitter' (like a send).  Default = FALSE. */\n        GAIN,                /* (Type:float) - [r/w] - Gain to receive or transmit at in dB.  -80.0 to 10.0.  Default = 0. */\n        CHANNEL,             /* (Type:int)   - [r/w] - Integer to select current global slot, shared by all Transceivers, that can be transmitted to or received from.  0 to 31.  Default = 0.*/\n        TRANSMITSPEAKERMODE  /* (Type:int)   - [r/w] - Speaker mode (transmitter mode only).  Specifies either 0 (Auto) Default = 0.*/\n    }\n\n\n/*$ preserve start $*/\n}\n/*$ preserve end $*/\n"
  },
  {
    "path": "AssetStudioUtility/FMOD Studio API/fmod_errors.cs",
    "content": "/* =================================================================================================== */\n/* FMOD Studio - Error string header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016.  */\n/*                                                                                                     */\n/* Use this header if you want to store or display a string version / english explanation of           */\n/* the FMOD error codes.                                                                               */\n/*                                                                                                     */\n/* =================================================================================================== */\n\nnamespace FMOD\n{\n    public class Error\n    {\n        public static string String(FMOD.RESULT errcode)\n        {\n            switch (errcode)\n            {\n                case FMOD.RESULT.OK:                            return \"No errors.\";\n                case FMOD.RESULT.ERR_BADCOMMAND:                return \"Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound).\";\n                case FMOD.RESULT.ERR_CHANNEL_ALLOC:             return \"Error trying to allocate a channel.\";\n                case FMOD.RESULT.ERR_CHANNEL_STOLEN:            return \"The specified channel has been reused to play another sound.\";\n                case FMOD.RESULT.ERR_DMA:                       return \"DMA Failure.  See debug output for more information.\";\n                case FMOD.RESULT.ERR_DSP_CONNECTION:            return \"DSP connection error.  Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts.\";\n                case FMOD.RESULT.ERR_DSP_DONTPROCESS:           return \"DSP return code from a DSP process query callback.  Tells mixer not to call the process callback and therefore not consume CPU.  Use this to optimize the DSP graph.\";\n                case FMOD.RESULT.ERR_DSP_FORMAT:                return \"DSP Format error.  A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map.\";\n                case FMOD.RESULT.ERR_DSP_INUSE:                 return \"DSP is already in the mixer's DSP network. It must be removed before being reinserted or released.\";\n                case FMOD.RESULT.ERR_DSP_NOTFOUND:              return \"DSP connection error.  Couldn't find the DSP unit specified.\";\n                case FMOD.RESULT.ERR_DSP_RESERVED:              return \"DSP operation error.  Cannot perform operation on this DSP as it is reserved by the system.\";\n                case FMOD.RESULT.ERR_DSP_SILENCE:               return \"DSP return code from a DSP process query callback.  Tells mixer silence would be produced from read, so go idle and not consume CPU.  Use this to optimize the DSP graph.\";\n                case FMOD.RESULT.ERR_DSP_TYPE:                  return \"DSP operation cannot be performed on a DSP of this type.\";\n                case FMOD.RESULT.ERR_FILE_BAD:                  return \"Error loading file.\";\n                case FMOD.RESULT.ERR_FILE_COULDNOTSEEK:         return \"Couldn't perform seek operation.  This is a limitation of the medium (ie netstreams) or the file format.\";\n                case FMOD.RESULT.ERR_FILE_DISKEJECTED:          return \"Media was ejected while reading.\";\n                case FMOD.RESULT.ERR_FILE_EOF:                  return \"End of file unexpectedly reached while trying to read essential data (truncated?).\";\n                case FMOD.RESULT.ERR_FILE_ENDOFDATA:            return \"End of current chunk reached while trying to read data.\";\n                case FMOD.RESULT.ERR_FILE_NOTFOUND:             return \"File not found.\";\n                case FMOD.RESULT.ERR_FORMAT:                    return \"Unsupported file or audio format.\";\n                case FMOD.RESULT.ERR_HEADER_MISMATCH:           return \"There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library.\";\n                case FMOD.RESULT.ERR_HTTP:                      return \"A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere.\";\n                case FMOD.RESULT.ERR_HTTP_ACCESS:               return \"The specified resource requires authentication or is forbidden.\";\n                case FMOD.RESULT.ERR_HTTP_PROXY_AUTH:           return \"Proxy authentication is required to access the specified resource.\";\n                case FMOD.RESULT.ERR_HTTP_SERVER_ERROR:         return \"A HTTP server error occurred.\";\n                case FMOD.RESULT.ERR_HTTP_TIMEOUT:              return \"The HTTP request timed out.\";\n                case FMOD.RESULT.ERR_INITIALIZATION:            return \"FMOD was not initialized correctly to support this function.\";\n                case FMOD.RESULT.ERR_INITIALIZED:               return \"Cannot call this command after System::init.\";\n                case FMOD.RESULT.ERR_INTERNAL:                  return \"An error occurred that wasn't supposed to.  Contact support.\";\n                case FMOD.RESULT.ERR_INVALID_FLOAT:             return \"Value passed in was a NaN, Inf or denormalized float.\";\n                case FMOD.RESULT.ERR_INVALID_HANDLE:            return \"An invalid object handle was used.\";\n                case FMOD.RESULT.ERR_INVALID_PARAM:             return \"An invalid parameter was passed to this function.\";\n                case FMOD.RESULT.ERR_INVALID_POSITION:          return \"An invalid seek position was passed to this function.\";\n                case FMOD.RESULT.ERR_INVALID_SPEAKER:           return \"An invalid speaker was passed to this function based on the current speaker mode.\";\n                case FMOD.RESULT.ERR_INVALID_SYNCPOINT:         return \"The syncpoint did not come from this sound handle.\";\n                case FMOD.RESULT.ERR_INVALID_THREAD:            return \"Tried to call a function on a thread that is not supported.\";\n                case FMOD.RESULT.ERR_INVALID_VECTOR:            return \"The vectors passed in are not unit length, or perpendicular.\";\n                case FMOD.RESULT.ERR_MAXAUDIBLE:                return \"Reached maximum audible playback count for this sound's soundgroup.\";\n                case FMOD.RESULT.ERR_MEMORY:                    return \"Not enough memory or resources.\";\n                case FMOD.RESULT.ERR_MEMORY_CANTPOINT:          return \"Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used.\";\n                case FMOD.RESULT.ERR_NEEDS3D:                   return \"Tried to call a command on a 2d sound when the command was meant for 3d sound.\";\n                case FMOD.RESULT.ERR_NEEDSHARDWARE:             return \"Tried to use a feature that requires hardware support.\";\n                case FMOD.RESULT.ERR_NET_CONNECT:               return \"Couldn't connect to the specified host.\";\n                case FMOD.RESULT.ERR_NET_SOCKET_ERROR:          return \"A socket error occurred.  This is a catch-all for socket-related errors not listed elsewhere.\";\n                case FMOD.RESULT.ERR_NET_URL:                   return \"The specified URL couldn't be resolved.\";\n                case FMOD.RESULT.ERR_NET_WOULD_BLOCK:           return \"Operation on a non-blocking socket could not complete immediately.\";\n                case FMOD.RESULT.ERR_NOTREADY:                  return \"Operation could not be performed because specified sound/DSP connection is not ready.\";\n                case FMOD.RESULT.ERR_OUTPUT_ALLOCATED:          return \"Error initializing output device, but more specifically, the output device is already in use and cannot be reused.\";\n                case FMOD.RESULT.ERR_OUTPUT_CREATEBUFFER:       return \"Error creating hardware sound buffer.\";\n                case FMOD.RESULT.ERR_OUTPUT_DRIVERCALL:         return \"A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted.\";\n                case FMOD.RESULT.ERR_OUTPUT_FORMAT:             return \"Soundcard does not support the specified format.\";\n                case FMOD.RESULT.ERR_OUTPUT_INIT:               return \"Error initializing output device.\";\n                case FMOD.RESULT.ERR_OUTPUT_NODRIVERS:          return \"The output device has no drivers installed.  If pre-init, FMOD_OUTPUT_NOSOUND is selected as the output mode.  If post-init, the function just fails.\";\n                case FMOD.RESULT.ERR_PLUGIN:                    return \"An unspecified error has been returned from a plugin.\";\n                case FMOD.RESULT.ERR_PLUGIN_MISSING:            return \"A requested output, dsp unit type or codec was not available.\";\n                case FMOD.RESULT.ERR_PLUGIN_RESOURCE:           return \"A resource that the plugin requires cannot be found. (ie the DLS file for MIDI playback)\";\n                case FMOD.RESULT.ERR_PLUGIN_VERSION:            return \"A plugin was built with an unsupported SDK version.\";\n                case FMOD.RESULT.ERR_RECORD:                    return \"An error occurred trying to initialize the recording device.\";\n                case FMOD.RESULT.ERR_REVERB_CHANNELGROUP:       return \"Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection.\";\n                case FMOD.RESULT.ERR_REVERB_INSTANCE:           return \"Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist.\";\n                case FMOD.RESULT.ERR_SUBSOUNDS:                 return \"The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have.  The operation may also not be able to be performed on a parent sound.\";\n                case FMOD.RESULT.ERR_SUBSOUND_ALLOCATED:        return \"This subsound is already being used by another sound, you cannot have more than one parent to a sound.  Null out the other parent's entry first.\";\n                case FMOD.RESULT.ERR_SUBSOUND_CANTMOVE:         return \"Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file.\";\n                case FMOD.RESULT.ERR_TAGNOTFOUND:               return \"The specified tag could not be found or there are no tags.\";\n                case FMOD.RESULT.ERR_TOOMANYCHANNELS:           return \"The sound created exceeds the allowable input channel count.  This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat.\";\n                case FMOD.RESULT.ERR_TRUNCATED:                 return \"The retrieved string is too long to fit in the supplied buffer and has been truncated.\";\n                case FMOD.RESULT.ERR_UNIMPLEMENTED:             return \"Something in FMOD hasn't been implemented when it should be! contact support!\";\n                case FMOD.RESULT.ERR_UNINITIALIZED:             return \"This command failed because System::init or System::setDriver was not called.\";\n                case FMOD.RESULT.ERR_UNSUPPORTED:               return \"A command issued was not supported by this object.  Possibly a plugin without certain callbacks specified.\";\n                case FMOD.RESULT.ERR_VERSION:                   return \"The version number of this file format is not supported.\";\n                case FMOD.RESULT.ERR_EVENT_ALREADY_LOADED:      return \"The specified bank has already been loaded.\";\n                case FMOD.RESULT.ERR_EVENT_LIVEUPDATE_BUSY:     return \"The live update connection failed due to the game already being connected.\";\n                case FMOD.RESULT.ERR_EVENT_LIVEUPDATE_MISMATCH: return \"The live update connection failed due to the game data being out of sync with the tool.\";\n                case FMOD.RESULT.ERR_EVENT_LIVEUPDATE_TIMEOUT:  return \"The live update connection timed out.\";\n                case FMOD.RESULT.ERR_EVENT_NOTFOUND:            return \"The requested event, bus or vca could not be found.\";\n                case FMOD.RESULT.ERR_STUDIO_UNINITIALIZED:      return \"The Studio::System object is not yet initialized.\";\n                case FMOD.RESULT.ERR_STUDIO_NOT_LOADED:         return \"The specified resource is not loaded, so it can't be unloaded.\";\n                case FMOD.RESULT.ERR_INVALID_STRING:            return \"An invalid string was passed to this function.\";\n                case FMOD.RESULT.ERR_ALREADY_LOCKED:            return \"The specified resource is already locked.\";\n                case FMOD.RESULT.ERR_NOT_LOCKED:                return \"The specified resource is not locked, so it can't be unlocked.\";\n\t\t\t\tcase FMOD.RESULT.ERR_RECORD_DISCONNECTED:       return \"The specified recording driver has been disconnected.\";\n\t\t\t\tcase FMOD.RESULT.ERR_TOOMANYSAMPLES:            return \"The length provided exceed the allowable limit.\";\n                default:                                        return \"Unknown error.\";\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/ImageExtensions.cs",
    "content": "﻿using SixLabors.ImageSharp;\nusing SixLabors.ImageSharp.Formats.Bmp;\nusing SixLabors.ImageSharp.Formats.Tga;\nusing SixLabors.ImageSharp.PixelFormats;\nusing System.IO;\nusing System.Runtime.InteropServices;\n\nnamespace AssetStudio\n{\n    public static class ImageExtensions\n    {\n        public static void WriteToStream(this Image image, Stream stream, ImageFormat imageFormat)\n        {\n            switch (imageFormat)\n            {\n                case ImageFormat.Jpeg:\n                    image.SaveAsJpeg(stream);\n                    break;\n                case ImageFormat.Png:\n                    image.SaveAsPng(stream);\n                    break;\n                case ImageFormat.Bmp:\n                    image.Save(stream, new BmpEncoder\n                    {\n                        BitsPerPixel = BmpBitsPerPixel.Pixel32,\n                        SupportTransparency = true\n                    });\n                    break;\n                case ImageFormat.Tga:\n                    image.Save(stream, new TgaEncoder\n                    {\n                        BitsPerPixel = TgaBitsPerPixel.Pixel32,\n                        Compression = TgaCompression.None\n                    });\n                    break;\n            }\n        }\n\n        public static MemoryStream ConvertToStream(this Image image, ImageFormat imageFormat)\n        {\n            var stream = new MemoryStream();\n            image.WriteToStream(stream, imageFormat);\n            return stream;\n        }\n\n        public static byte[] ConvertToBytes<TPixel>(this Image<TPixel> image) where TPixel : unmanaged, IPixel<TPixel>\n        {\n            if (image.TryGetSinglePixelSpan(out var pixelSpan))\n            {\n                return MemoryMarshal.AsBytes(pixelSpan).ToArray();\n            }\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/ImageFormat.cs",
    "content": "﻿namespace AssetStudio\n{\n    public enum ImageFormat\n    {\n        Jpeg,\n        Png,\n        Bmp,\n        Tga\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/ModelConverter.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public class ModelConverter : IImported\n    {\n        public ImportedFrame RootFrame { get; protected set; }\n        public List<ImportedMesh> MeshList { get; protected set; } = new List<ImportedMesh>();\n        public List<ImportedMaterial> MaterialList { get; protected set; } = new List<ImportedMaterial>();\n        public List<ImportedTexture> TextureList { get; protected set; } = new List<ImportedTexture>();\n        public List<ImportedKeyframedAnimation> AnimationList { get; protected set; } = new List<ImportedKeyframedAnimation>();\n        public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>();\n\n        private ImageFormat imageFormat;\n        private Avatar avatar;\n        private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();\n        private Dictionary<AnimationClip, string> boundAnimationPathDic = new Dictionary<AnimationClip, string>();\n        private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();\n        private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();\n        private Dictionary<Transform, ImportedFrame> transformDictionary = new Dictionary<Transform, ImportedFrame>();\n        Dictionary<uint, string> morphChannelNames = new Dictionary<uint, string>();\n\n        public ModelConverter(GameObject m_GameObject, ImageFormat imageFormat, AnimationClip[] animationList = null)\n        {\n            this.imageFormat = imageFormat;\n            if (m_GameObject.m_Animator != null)\n            {\n                InitWithAnimator(m_GameObject.m_Animator);\n                if (animationList == null)\n                {\n                    CollectAnimationClip(m_GameObject.m_Animator);\n                }\n            }\n            else\n            {\n                InitWithGameObject(m_GameObject);\n            }\n            if (animationList != null)\n            {\n                foreach (var animationClip in animationList)\n                {\n                    animationClipHashSet.Add(animationClip);\n                }\n            }\n            ConvertAnimations();\n        }\n\n        public ModelConverter(string rootName, List<GameObject> m_GameObjects, ImageFormat imageFormat, AnimationClip[] animationList = null)\n        {\n            this.imageFormat = imageFormat;\n            RootFrame = CreateFrame(rootName, Vector3.Zero, new Quaternion(0, 0, 0, 0), Vector3.One);\n            foreach (var m_GameObject in m_GameObjects)\n            {\n                if (m_GameObject.m_Animator != null && animationList == null)\n                {\n                    CollectAnimationClip(m_GameObject.m_Animator);\n                }\n\n                var m_Transform = m_GameObject.m_Transform;\n                ConvertTransforms(m_Transform, RootFrame);\n                CreateBonePathHash(m_Transform);\n            }\n            foreach (var m_GameObject in m_GameObjects)\n            {\n                var m_Transform = m_GameObject.m_Transform;\n                ConvertMeshRenderer(m_Transform);\n            }\n            if (animationList != null)\n            {\n                foreach (var animationClip in animationList)\n                {\n                    animationClipHashSet.Add(animationClip);\n                }\n            }\n            ConvertAnimations();\n        }\n\n        public ModelConverter(Animator m_Animator, ImageFormat imageFormat, AnimationClip[] animationList = null)\n        {\n            this.imageFormat = imageFormat;\n            InitWithAnimator(m_Animator);\n            if (animationList == null)\n            {\n                CollectAnimationClip(m_Animator);\n            }\n            else\n            {\n                foreach (var animationClip in animationList)\n                {\n                    animationClipHashSet.Add(animationClip);\n                }\n            }\n            ConvertAnimations();\n        }\n\n        private void InitWithAnimator(Animator m_Animator)\n        {\n            if (m_Animator.m_Avatar.TryGet(out var m_Avatar))\n                avatar = m_Avatar;\n\n            m_Animator.m_GameObject.TryGet(out var m_GameObject);\n            InitWithGameObject(m_GameObject, m_Animator.m_HasTransformHierarchy);\n        }\n\n        private void InitWithGameObject(GameObject m_GameObject, bool hasTransformHierarchy = true)\n        {\n            var m_Transform = m_GameObject.m_Transform;\n            if (!hasTransformHierarchy)\n            {\n                ConvertTransforms(m_Transform, null);\n                DeoptimizeTransformHierarchy();\n            }\n            else\n            {\n                var frameList = new List<ImportedFrame>();\n                var tempTransform = m_Transform;\n                while (tempTransform.m_Father.TryGet(out var m_Father))\n                {\n                    frameList.Add(ConvertTransform(m_Father));\n                    tempTransform = m_Father;\n                }\n                if (frameList.Count > 0)\n                {\n                    RootFrame = frameList[frameList.Count - 1];\n                    for (var i = frameList.Count - 2; i >= 0; i--)\n                    {\n                        var frame = frameList[i];\n                        var parent = frameList[i + 1];\n                        parent.AddChild(frame);\n                    }\n                    ConvertTransforms(m_Transform, frameList[0]);\n                }\n                else\n                {\n                    ConvertTransforms(m_Transform, null);\n                }\n\n                CreateBonePathHash(m_Transform);\n            }\n\n            ConvertMeshRenderer(m_Transform);\n        }\n\n        private void ConvertMeshRenderer(Transform m_Transform)\n        {\n            m_Transform.m_GameObject.TryGet(out var m_GameObject);\n\n            if (m_GameObject.m_MeshRenderer != null)\n            {\n                ConvertMeshRenderer(m_GameObject.m_MeshRenderer);\n            }\n\n            if (m_GameObject.m_SkinnedMeshRenderer != null)\n            {\n                ConvertMeshRenderer(m_GameObject.m_SkinnedMeshRenderer);\n            }\n\n            if (m_GameObject.m_Animation != null)\n            {\n                foreach (var animation in m_GameObject.m_Animation.m_Animations)\n                {\n                    if (animation.TryGet(out var animationClip))\n                    {\n                        if (!boundAnimationPathDic.ContainsKey(animationClip))\n                        {\n                            boundAnimationPathDic.Add(animationClip, GetTransformPath(m_Transform));\n                        }\n                        animationClipHashSet.Add(animationClip);\n                    }\n                }\n            }\n\n            foreach (var pptr in m_Transform.m_Children)\n            {\n                if (pptr.TryGet(out var child))\n                    ConvertMeshRenderer(child);\n            }\n        }\n\n        private void CollectAnimationClip(Animator m_Animator)\n        {\n            if (m_Animator.m_Controller.TryGet(out var m_Controller))\n            {\n                switch (m_Controller)\n                {\n                    case AnimatorOverrideController m_AnimatorOverrideController:\n                        {\n                            if (m_AnimatorOverrideController.m_Controller.TryGet<AnimatorController>(out var m_AnimatorController))\n                            {\n                                foreach (var pptr in m_AnimatorController.m_AnimationClips)\n                                {\n                                    if (pptr.TryGet(out var m_AnimationClip))\n                                    {\n                                        animationClipHashSet.Add(m_AnimationClip);\n                                    }\n                                }\n                            }\n                            break;\n                        }\n\n                    case AnimatorController m_AnimatorController:\n                        {\n                            foreach (var pptr in m_AnimatorController.m_AnimationClips)\n                            {\n                                if (pptr.TryGet(out var m_AnimationClip))\n                                {\n                                    animationClipHashSet.Add(m_AnimationClip);\n                                }\n                            }\n                            break;\n                        }\n                }\n            }\n        }\n\n        private ImportedFrame ConvertTransform(Transform trans)\n        {\n            var frame = new ImportedFrame(trans.m_Children.Length);\n            transformDictionary.Add(trans, frame);\n            trans.m_GameObject.TryGet(out var m_GameObject);\n            frame.Name = m_GameObject.m_Name;\n            SetFrame(frame, trans.m_LocalPosition, trans.m_LocalRotation, trans.m_LocalScale);\n            return frame;\n        }\n\n        private static ImportedFrame CreateFrame(string name, Vector3 t, Quaternion q, Vector3 s)\n        {\n            var frame = new ImportedFrame();\n            frame.Name = name;\n            SetFrame(frame, t, q, s);\n            return frame;\n        }\n\n        private static void SetFrame(ImportedFrame frame, Vector3 t, Quaternion q, Vector3 s)\n        {\n            frame.LocalPosition = new Vector3(-t.X, t.Y, t.Z);\n            frame.LocalRotation = Fbx.QuaternionToEuler(new Quaternion(q.X, -q.Y, -q.Z, q.W));\n            frame.LocalScale = s;\n        }\n\n        private void ConvertTransforms(Transform trans, ImportedFrame parent)\n        {\n            var frame = ConvertTransform(trans);\n            if (parent == null)\n            {\n                RootFrame = frame;\n            }\n            else\n            {\n                parent.AddChild(frame);\n            }\n            foreach (var pptr in trans.m_Children)\n            {\n                if (pptr.TryGet(out var child))\n                    ConvertTransforms(child, frame);\n            }\n        }\n\n        private void ConvertMeshRenderer(Renderer meshR)\n        {\n            var mesh = GetMesh(meshR);\n            if (mesh == null)\n                return;\n            var iMesh = new ImportedMesh();\n            meshR.m_GameObject.TryGet(out var m_GameObject2);\n            iMesh.Path = GetTransformPath(m_GameObject2.m_Transform);\n            iMesh.SubmeshList = new List<ImportedSubmesh>();\n            var subHashSet = new HashSet<int>();\n            var combine = false;\n            int firstSubMesh = 0;\n            if (meshR.m_StaticBatchInfo?.subMeshCount > 0)\n            {\n                firstSubMesh = meshR.m_StaticBatchInfo.firstSubMesh;\n                var finalSubMesh = meshR.m_StaticBatchInfo.firstSubMesh + meshR.m_StaticBatchInfo.subMeshCount;\n                for (int i = meshR.m_StaticBatchInfo.firstSubMesh; i < finalSubMesh; i++)\n                {\n                    subHashSet.Add(i);\n                }\n                combine = true;\n            }\n            else if (meshR.m_SubsetIndices?.Length > 0)\n            {\n                firstSubMesh = (int)meshR.m_SubsetIndices.Min(x => x);\n                foreach (var index in meshR.m_SubsetIndices)\n                {\n                    subHashSet.Add((int)index);\n                }\n                combine = true;\n            }\n\n            iMesh.hasNormal = mesh.m_Normals?.Length > 0;\n            iMesh.hasUV = new bool[8];\n            for (int uv = 0; uv < 8; uv++)\n            {\n                iMesh.hasUV[uv] = mesh.GetUV(uv)?.Length > 0;\n            }\n            iMesh.hasTangent = mesh.m_Tangents != null && mesh.m_Tangents.Length == mesh.m_VertexCount * 4;\n            iMesh.hasColor = mesh.m_Colors?.Length > 0;\n\n            int firstFace = 0;\n            for (int i = 0; i < mesh.m_SubMeshes.Length; i++)\n            {\n                int numFaces = (int)mesh.m_SubMeshes[i].indexCount / 3;\n                if (subHashSet.Count > 0 && !subHashSet.Contains(i))\n                {\n                    firstFace += numFaces;\n                    continue;\n                }\n                var submesh = mesh.m_SubMeshes[i];\n                var iSubmesh = new ImportedSubmesh();\n                Material mat = null;\n                if (i - firstSubMesh < meshR.m_Materials.Length)\n                {\n                    if (meshR.m_Materials[i - firstSubMesh].TryGet(out var m_Material))\n                    {\n                        mat = m_Material;\n                    }\n                }\n                ImportedMaterial iMat = ConvertMaterial(mat);\n                iSubmesh.Material = iMat.Name;\n                iSubmesh.BaseVertex = (int)mesh.m_SubMeshes[i].firstVertex;\n\n                //Face\n                iSubmesh.FaceList = new List<ImportedFace>(numFaces);\n                var end = firstFace + numFaces;\n                for (int f = firstFace; f < end; f++)\n                {\n                    var face = new ImportedFace();\n                    face.VertexIndices = new int[3];\n                    face.VertexIndices[0] = (int)(mesh.m_Indices[f * 3 + 2] - submesh.firstVertex);\n                    face.VertexIndices[1] = (int)(mesh.m_Indices[f * 3 + 1] - submesh.firstVertex);\n                    face.VertexIndices[2] = (int)(mesh.m_Indices[f * 3] - submesh.firstVertex);\n                    iSubmesh.FaceList.Add(face);\n                }\n                firstFace = end;\n\n                iMesh.SubmeshList.Add(iSubmesh);\n            }\n\n            // Shared vertex list\n            iMesh.VertexList = new List<ImportedVertex>((int)mesh.m_VertexCount);\n            for (var j = 0; j < mesh.m_VertexCount; j++)\n            {\n                var iVertex = new ImportedVertex();\n                //Vertices\n                int c = 3;\n                if (mesh.m_Vertices.Length == mesh.m_VertexCount * 4)\n                {\n                    c = 4;\n                }\n                iVertex.Vertex = new Vector3(-mesh.m_Vertices[j * c], mesh.m_Vertices[j * c + 1], mesh.m_Vertices[j * c + 2]);\n                //Normals\n                if (iMesh.hasNormal)\n                {\n                    if (mesh.m_Normals.Length == mesh.m_VertexCount * 3)\n                    {\n                        c = 3;\n                    }\n                    else if (mesh.m_Normals.Length == mesh.m_VertexCount * 4)\n                    {\n                        c = 4;\n                    }\n                    iVertex.Normal = new Vector3(-mesh.m_Normals[j * c], mesh.m_Normals[j * c + 1], mesh.m_Normals[j * c + 2]);\n                }\n                //UV\n                iVertex.UV = new float[8][];\n                for (int uv = 0; uv < 8; uv++)\n                {\n                    if (iMesh.hasUV[uv])\n                    {\n                        var m_UV = mesh.GetUV(uv);\n                        if (m_UV.Length == mesh.m_VertexCount * 2)\n                        {\n                            c = 2;\n                        }\n                        else if (m_UV.Length == mesh.m_VertexCount * 3)\n                        {\n                            c = 3;\n                        }\n                        iVertex.UV[uv] = new[] { m_UV[j * c], m_UV[j * c + 1] };\n                    }\n                }\n                //Tangent\n                if (iMesh.hasTangent)\n                {\n                    iVertex.Tangent = new Vector4(-mesh.m_Tangents[j * 4], mesh.m_Tangents[j * 4 + 1], mesh.m_Tangents[j * 4 + 2], mesh.m_Tangents[j * 4 + 3]);\n                }\n                //Colors\n                if (iMesh.hasColor)\n                {\n                    if (mesh.m_Colors.Length == mesh.m_VertexCount * 3)\n                    {\n                        iVertex.Color = new Color(mesh.m_Colors[j * 3], mesh.m_Colors[j * 3 + 1], mesh.m_Colors[j * 3 + 2], 1.0f);\n                    }\n                    else\n                    {\n                        iVertex.Color = new Color(mesh.m_Colors[j * 4], mesh.m_Colors[j * 4 + 1], mesh.m_Colors[j * 4 + 2], mesh.m_Colors[j * 4 + 3]);\n                    }\n                }\n                //BoneInfluence\n                if (mesh.m_Skin?.Length > 0)\n                {\n                    var inf = mesh.m_Skin[j];\n                    iVertex.BoneIndices = new int[4];\n                    iVertex.Weights = new float[4];\n                    for (var k = 0; k < 4; k++)\n                    {\n                        iVertex.BoneIndices[k] = inf.boneIndex[k];\n                        iVertex.Weights[k] = inf.weight[k];\n                    }\n                }\n                iMesh.VertexList.Add(iVertex);\n            }\n\n            if (meshR is SkinnedMeshRenderer sMesh)\n            {\n                //Bone\n                /*\n                 * 0 - None\n                 * 1 - m_Bones\n                 * 2 - m_BoneNameHashes\n                 */\n                var boneType = 0;\n                if (sMesh.m_Bones.Length > 0)\n                {\n                    if (sMesh.m_Bones.Length == mesh.m_BindPose.Length)\n                    {\n                        var verifiedBoneCount = sMesh.m_Bones.Count(x => x.TryGet(out _));\n                        if (verifiedBoneCount > 0)\n                        {\n                            boneType = 1;\n                        }\n                        if (verifiedBoneCount != sMesh.m_Bones.Length)\n                        {\n                            //尝试使用m_BoneNameHashes 4.3 and up\n                            if (mesh.m_BindPose.Length > 0 && (mesh.m_BindPose.Length == mesh.m_BoneNameHashes?.Length))\n                            {\n                                //有效bone数量是否大于SkinnedMeshRenderer\n                                var verifiedBoneCount2 = mesh.m_BoneNameHashes.Count(x => FixBonePath(GetPathFromHash(x)) != null);\n                                if (verifiedBoneCount2 > verifiedBoneCount)\n                                {\n                                    boneType = 2;\n                                }\n                            }\n                        }\n                    }\n                }\n                if (boneType == 0)\n                {\n                    //尝试使用m_BoneNameHashes 4.3 and up\n                    if (mesh.m_BindPose.Length > 0 && (mesh.m_BindPose.Length == mesh.m_BoneNameHashes?.Length))\n                    {\n                        var verifiedBoneCount = mesh.m_BoneNameHashes.Count(x => FixBonePath(GetPathFromHash(x)) != null);\n                        if (verifiedBoneCount > 0)\n                        {\n                            boneType = 2;\n                        }\n                    }\n                }\n\n                if (boneType == 1)\n                {\n                    var boneCount = sMesh.m_Bones.Length;\n                    iMesh.BoneList = new List<ImportedBone>(boneCount);\n                    for (int i = 0; i < boneCount; i++)\n                    {\n                        var bone = new ImportedBone();\n                        if (sMesh.m_Bones[i].TryGet(out var m_Transform))\n                        {\n                            bone.Path = GetTransformPath(m_Transform);\n                        }\n                        var convert = Matrix4x4.Scale(new Vector3(-1, 1, 1));\n                        bone.Matrix = convert * mesh.m_BindPose[i] * convert;\n                        iMesh.BoneList.Add(bone);\n                    }\n                }\n                else if (boneType == 2)\n                {\n                    var boneCount = mesh.m_BindPose.Length;\n                    iMesh.BoneList = new List<ImportedBone>(boneCount);\n                    for (int i = 0; i < boneCount; i++)\n                    {\n                        var bone = new ImportedBone();\n                        var boneHash = mesh.m_BoneNameHashes[i];\n                        var path = GetPathFromHash(boneHash);\n                        bone.Path = FixBonePath(path);\n                        var convert = Matrix4x4.Scale(new Vector3(-1, 1, 1));\n                        bone.Matrix = convert * mesh.m_BindPose[i] * convert;\n                        iMesh.BoneList.Add(bone);\n                    }\n                }\n\n                //Morphs\n                if (mesh.m_Shapes?.channels?.Length > 0)\n                {\n                    var morph = new ImportedMorph();\n                    MorphList.Add(morph);\n                    morph.Path = iMesh.Path;\n                    morph.Channels = new List<ImportedMorphChannel>(mesh.m_Shapes.channels.Length);\n                    for (int i = 0; i < mesh.m_Shapes.channels.Length; i++)\n                    {\n                        var channel = new ImportedMorphChannel();\n                        morph.Channels.Add(channel);\n                        var shapeChannel = mesh.m_Shapes.channels[i];\n\n                        var blendShapeName = \"blendShape.\" + shapeChannel.name;\n                        var crc = new SevenZip.CRC();\n                        var bytes = Encoding.UTF8.GetBytes(blendShapeName);\n                        crc.Update(bytes, 0, (uint)bytes.Length);\n                        morphChannelNames[crc.GetDigest()] = blendShapeName;\n\n                        channel.Name = shapeChannel.name.Split('.').Last();\n                        channel.KeyframeList = new List<ImportedMorphKeyframe>(shapeChannel.frameCount);\n                        var frameEnd = shapeChannel.frameIndex + shapeChannel.frameCount;\n                        for (int frameIdx = shapeChannel.frameIndex; frameIdx < frameEnd; frameIdx++)\n                        {\n                            var keyframe = new ImportedMorphKeyframe();\n                            channel.KeyframeList.Add(keyframe);\n                            keyframe.Weight = mesh.m_Shapes.fullWeights[frameIdx];\n                            var shape = mesh.m_Shapes.shapes[frameIdx];\n                            keyframe.hasNormals = shape.hasNormals;\n                            keyframe.hasTangents = shape.hasTangents;\n                            keyframe.VertexList = new List<ImportedMorphVertex>((int)shape.vertexCount);\n                            var vertexEnd = shape.firstVertex + shape.vertexCount;\n                            for (uint j = shape.firstVertex; j < vertexEnd; j++)\n                            {\n                                var destVertex = new ImportedMorphVertex();\n                                keyframe.VertexList.Add(destVertex);\n                                var morphVertex = mesh.m_Shapes.vertices[j];\n                                destVertex.Index = morphVertex.index;\n                                var sourceVertex = iMesh.VertexList[(int)morphVertex.index];\n                                destVertex.Vertex = new ImportedVertex();\n                                var morphPos = morphVertex.vertex;\n                                destVertex.Vertex.Vertex = sourceVertex.Vertex + new Vector3(-morphPos.X, morphPos.Y, morphPos.Z);\n                                if (shape.hasNormals)\n                                {\n                                    var morphNormal = morphVertex.normal;\n                                    destVertex.Vertex.Normal = new Vector3(-morphNormal.X, morphNormal.Y, morphNormal.Z);\n                                }\n                                if (shape.hasTangents)\n                                {\n                                    var morphTangent = morphVertex.tangent;\n                                    destVertex.Vertex.Tangent = new Vector4(-morphTangent.X, morphTangent.Y, morphTangent.Z, 0);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            //TODO combine mesh\n            if (combine)\n            {\n                meshR.m_GameObject.TryGet(out var m_GameObject);\n                var frame = RootFrame.FindChild(m_GameObject.m_Name);\n                if (frame != null)\n                {\n                    frame.LocalPosition = RootFrame.LocalPosition;\n                    frame.LocalRotation = RootFrame.LocalRotation;\n                    while (frame.Parent != null)\n                    {\n                        frame = frame.Parent;\n                        frame.LocalPosition = RootFrame.LocalPosition;\n                        frame.LocalRotation = RootFrame.LocalRotation;\n                    }\n                }\n            }\n\n            MeshList.Add(iMesh);\n        }\n\n        private static Mesh GetMesh(Renderer meshR)\n        {\n            if (meshR is SkinnedMeshRenderer sMesh)\n            {\n                if (sMesh.m_Mesh.TryGet(out var m_Mesh))\n                {\n                    return m_Mesh;\n                }\n            }\n            else\n            {\n                meshR.m_GameObject.TryGet(out var m_GameObject);\n                if (m_GameObject.m_MeshFilter != null)\n                {\n                    if (m_GameObject.m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))\n                    {\n                        return m_Mesh;\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        private string GetTransformPath(Transform transform)\n        {\n            if (transformDictionary.TryGetValue(transform, out var frame))\n            {\n                return frame.Path;\n            }\n            return null;\n        }\n\n        private string FixBonePath(AnimationClip m_AnimationClip, string path)\n        {\n            if (boundAnimationPathDic.TryGetValue(m_AnimationClip, out var basePath))\n            {\n                path = basePath + \"/\" + path;\n            }\n            return FixBonePath(path);\n        }\n\n        private string FixBonePath(string path)\n        {\n            var frame = RootFrame.FindFrameByPath(path);\n            return frame?.Path;\n        }\n\n        private static string GetTransformPathByFather(Transform transform)\n        {\n            transform.m_GameObject.TryGet(out var m_GameObject);\n            if (transform.m_Father.TryGet(out var father))\n            {\n                return GetTransformPathByFather(father) + \"/\" + m_GameObject.m_Name;\n            }\n\n            return m_GameObject.m_Name;\n        }\n\n        private ImportedMaterial ConvertMaterial(Material mat)\n        {\n            ImportedMaterial iMat;\n            if (mat != null)\n            {\n                iMat = ImportedHelpers.FindMaterial(mat.m_Name, MaterialList);\n                if (iMat != null)\n                {\n                    return iMat;\n                }\n                iMat = new ImportedMaterial();\n                iMat.Name = mat.m_Name;\n                //default values\n                iMat.Diffuse = new Color(0.8f, 0.8f, 0.8f, 1);\n                iMat.Ambient = new Color(0.2f, 0.2f, 0.2f, 1);\n                iMat.Emissive = new Color(0, 0, 0, 1);\n                iMat.Specular = new Color(0.2f, 0.2f, 0.2f, 1);\n                iMat.Reflection = new Color(0, 0, 0, 1);\n                iMat.Shininess = 20f;\n                iMat.Transparency = 0f;\n                foreach (var col in mat.m_SavedProperties.m_Colors)\n                {\n                    switch (col.Key)\n                    {\n                        case \"_Color\":\n                            iMat.Diffuse = col.Value;\n                            break;\n                        case \"_SColor\":\n                            iMat.Ambient = col.Value;\n                            break;\n                        case \"_EmissionColor\":\n                            iMat.Emissive = col.Value;\n                            break;\n                        case \"_SpecularColor\":\n                            iMat.Specular = col.Value;\n                            break;\n                        case \"_ReflectColor\":\n                            iMat.Reflection = col.Value;\n                            break;\n                    }\n                }\n\n                foreach (var flt in mat.m_SavedProperties.m_Floats)\n                {\n                    switch (flt.Key)\n                    {\n                        case \"_Shininess\":\n                            iMat.Shininess = flt.Value;\n                            break;\n                        case \"_Transparency\":\n                            iMat.Transparency = flt.Value;\n                            break;\n                    }\n                }\n\n                //textures\n                iMat.Textures = new List<ImportedMaterialTexture>();\n                foreach (var texEnv in mat.m_SavedProperties.m_TexEnvs)\n                {\n                    if (!texEnv.Value.m_Texture.TryGet<Texture2D>(out var m_Texture2D)) //TODO other Texture\n                    {\n                        continue;\n                    }\n\n                    var texture = new ImportedMaterialTexture();\n                    iMat.Textures.Add(texture);\n\n                    int dest = -1;\n                    if (texEnv.Key == \"_MainTex\")\n                        dest = 0;\n                    else if (texEnv.Key == \"_BumpMap\")\n                        dest = 3;\n                    else if (texEnv.Key.Contains(\"Specular\"))\n                        dest = 2;\n                    else if (texEnv.Key.Contains(\"Normal\"))\n                        dest = 1;\n\n                    texture.Dest = dest;\n\n                    var ext = $\".{imageFormat.ToString().ToLower()}\";\n                    if (textureNameDictionary.TryGetValue(m_Texture2D, out var textureName))\n                    {\n                        texture.Name = textureName;\n                    }\n                    else if (ImportedHelpers.FindTexture(m_Texture2D.m_Name + ext, TextureList) != null) //已有相同名字的图片\n                    {\n                        for (int i = 1; ; i++)\n                        {\n                            var name = m_Texture2D.m_Name + $\" ({i}){ext}\";\n                            if (ImportedHelpers.FindTexture(name, TextureList) == null)\n                            {\n                                texture.Name = name;\n                                textureNameDictionary.Add(m_Texture2D, name);\n                                break;\n                            }\n                        }\n                    }\n                    else\n                    {\n                        texture.Name = m_Texture2D.m_Name + ext;\n                        textureNameDictionary.Add(m_Texture2D, texture.Name);\n                    }\n\n                    texture.Offset = texEnv.Value.m_Offset;\n                    texture.Scale = texEnv.Value.m_Scale;\n                    ConvertTexture2D(m_Texture2D, texture.Name);\n                }\n\n                MaterialList.Add(iMat);\n            }\n            else\n            {\n                iMat = new ImportedMaterial();\n            }\n            return iMat;\n        }\n\n        private void ConvertTexture2D(Texture2D m_Texture2D, string name)\n        {\n            var iTex = ImportedHelpers.FindTexture(name, TextureList);\n            if (iTex != null)\n            {\n                return;\n            }\n\n            var stream = m_Texture2D.ConvertToStream(imageFormat, true);\n            if (stream != null)\n            {\n                using (stream)\n                {\n                    iTex = new ImportedTexture(stream, name);\n                    TextureList.Add(iTex);\n                }\n            }\n        }\n\n        private void ConvertAnimations()\n        {\n            foreach (var animationClip in animationClipHashSet)\n            {\n                var iAnim = new ImportedKeyframedAnimation();\n                var name = animationClip.m_Name;\n                if (AnimationList.Exists(x => x.Name == name))\n                {\n                    for (int i = 1; ; i++)\n                    {\n                        var fixName = name + $\"_{i}\";\n                        if (!AnimationList.Exists(x => x.Name == fixName))\n                        {\n                            name = fixName;\n                            break;\n                        }\n                    }\n                }\n                iAnim.Name = name;\n                iAnim.SampleRate = animationClip.m_SampleRate;\n                iAnim.TrackList = new List<ImportedAnimationKeyframedTrack>();\n                AnimationList.Add(iAnim);\n                if (animationClip.m_Legacy)\n                {\n                    foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves)\n                    {\n                        var track = iAnim.FindTrack(FixBonePath(animationClip, m_CompressedRotationCurve.m_Path));\n\n                        var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems;\n                        var data = m_CompressedRotationCurve.m_Times.UnpackInts();\n                        var times = new float[numKeys];\n                        int t = 0;\n                        for (int i = 0; i < numKeys; i++)\n                        {\n                            t += data[i];\n                            times[i] = t * 0.01f;\n                        }\n                        var quats = m_CompressedRotationCurve.m_Values.UnpackQuats();\n\n                        for (int i = 0; i < numKeys; i++)\n                        {\n                            var quat = quats[i];\n                            var value = Fbx.QuaternionToEuler(new Quaternion(quat.X, -quat.Y, -quat.Z, quat.W));\n                            track.Rotations.Add(new ImportedKeyframe<Vector3>(times[i], value));\n                        }\n                    }\n                    foreach (var m_RotationCurve in animationClip.m_RotationCurves)\n                    {\n                        var track = iAnim.FindTrack(FixBonePath(animationClip, m_RotationCurve.path));\n                        foreach (var m_Curve in m_RotationCurve.curve.m_Curve)\n                        {\n                            var value = Fbx.QuaternionToEuler(new Quaternion(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z, m_Curve.value.W));\n                            track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, value));\n                        }\n                    }\n                    foreach (var m_PositionCurve in animationClip.m_PositionCurves)\n                    {\n                        var track = iAnim.FindTrack(FixBonePath(animationClip, m_PositionCurve.path));\n                        foreach (var m_Curve in m_PositionCurve.curve.m_Curve)\n                        {\n                            track.Translations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(-m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));\n                        }\n                    }\n                    foreach (var m_ScaleCurve in animationClip.m_ScaleCurves)\n                    {\n                        var track = iAnim.FindTrack(FixBonePath(animationClip, m_ScaleCurve.path));\n                        foreach (var m_Curve in m_ScaleCurve.curve.m_Curve)\n                        {\n                            track.Scalings.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));\n                        }\n                    }\n                    if (animationClip.m_EulerCurves != null)\n                    {\n                        foreach (var m_EulerCurve in animationClip.m_EulerCurves)\n                        {\n                            var track = iAnim.FindTrack(FixBonePath(animationClip, m_EulerCurve.path));\n                            foreach (var m_Curve in m_EulerCurve.curve.m_Curve)\n                            {\n                                track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z)));\n                            }\n                        }\n                    }\n                    foreach (var m_FloatCurve in animationClip.m_FloatCurves)\n                    {\n                        if (m_FloatCurve.classID == ClassIDType.SkinnedMeshRenderer) //BlendShape\n                        {\n                            var channelName = m_FloatCurve.attribute;\n                            int dotPos = channelName.IndexOf('.');\n                            if (dotPos >= 0)\n                            {\n                                channelName = channelName.Substring(dotPos + 1);\n                            }\n\n                            var path = FixBonePath(animationClip, m_FloatCurve.path);\n                            if (string.IsNullOrEmpty(path))\n                            {\n                                path = GetPathByChannelName(channelName);\n                            }\n                            var track = iAnim.FindTrack(path);\n                            track.BlendShape = new ImportedBlendShape();\n                            track.BlendShape.ChannelName = channelName;\n                            foreach (var m_Curve in m_FloatCurve.curve.m_Curve)\n                            {\n                                track.BlendShape.Keyframes.Add(new ImportedKeyframe<float>(m_Curve.time, m_Curve.value));\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    var m_Clip = animationClip.m_MuscleClip.m_Clip;\n                    var streamedFrames = m_Clip.m_StreamedClip.ReadData();\n                    var m_ClipBindingConstant = animationClip.m_ClipBindingConstant ?? m_Clip.ConvertValueArrayToGenericBinding();\n                    for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++)\n                    {\n                        var frame = streamedFrames[frameIndex];\n                        var streamedValues = frame.keyList.Select(x => x.value).ToArray();\n                        for (int curveIndex = 0; curveIndex < frame.keyList.Length;)\n                        {\n                            ReadCurveData(iAnim, m_ClipBindingConstant, frame.keyList[curveIndex].index, frame.time, streamedValues, 0, ref curveIndex);\n                        }\n                    }\n                    var m_DenseClip = m_Clip.m_DenseClip;\n                    var streamCount = m_Clip.m_StreamedClip.curveCount;\n                    for (int frameIndex = 0; frameIndex < m_DenseClip.m_FrameCount; frameIndex++)\n                    {\n                        var time = m_DenseClip.m_BeginTime + frameIndex / m_DenseClip.m_SampleRate;\n                        var frameOffset = frameIndex * m_DenseClip.m_CurveCount;\n                        for (int curveIndex = 0; curveIndex < m_DenseClip.m_CurveCount;)\n                        {\n                            var index = streamCount + curveIndex;\n                            ReadCurveData(iAnim, m_ClipBindingConstant, (int)index, time, m_DenseClip.m_SampleArray, (int)frameOffset, ref curveIndex);\n                        }\n                    }\n                    if (m_Clip.m_ConstantClip != null)\n                    {\n                        var m_ConstantClip = m_Clip.m_ConstantClip;\n                        var denseCount = m_Clip.m_DenseClip.m_CurveCount;\n                        var time2 = 0.0f;\n                        for (int i = 0; i < 2; i++)\n                        {\n                            for (int curveIndex = 0; curveIndex < m_ConstantClip.data.Length;)\n                            {\n                                var index = streamCount + denseCount + curveIndex;\n                                ReadCurveData(iAnim, m_ClipBindingConstant, (int)index, time2, m_ConstantClip.data, 0, ref curveIndex);\n                            }\n                            time2 = animationClip.m_MuscleClip.m_StopTime;\n                        }\n                    }\n                }\n            }\n        }\n\n        private void ReadCurveData(ImportedKeyframedAnimation iAnim, AnimationClipBindingConstant m_ClipBindingConstant, int index, float time, float[] data, int offset, ref int curveIndex)\n        {\n            var binding = m_ClipBindingConstant.FindBinding(index);\n            if (binding.typeID == ClassIDType.SkinnedMeshRenderer) //BlendShape\n            {\n                var channelName = GetChannelNameFromHash(binding.attribute);\n                if (string.IsNullOrEmpty(channelName))\n                {\n                    curveIndex++;\n                    return;\n                }\n                int dotPos = channelName.IndexOf('.');\n                if (dotPos >= 0)\n                {\n                    channelName = channelName.Substring(dotPos + 1);\n                }\n\n                var bPath = FixBonePath(GetPathFromHash(binding.path));\n                if (string.IsNullOrEmpty(bPath))\n                {\n                    bPath = GetPathByChannelName(channelName);\n                }\n                var bTrack = iAnim.FindTrack(bPath);\n                bTrack.BlendShape = new ImportedBlendShape();\n                bTrack.BlendShape.ChannelName = channelName;\n                bTrack.BlendShape.Keyframes.Add(new ImportedKeyframe<float>(time, data[curveIndex++ + offset]));\n            }\n            else if (binding.typeID == ClassIDType.Transform)\n            {\n                var path = FixBonePath(GetPathFromHash(binding.path));\n                var track = iAnim.FindTrack(path);\n\n                switch (binding.attribute)\n                {\n                    case 1:\n                        track.Translations.Add(new ImportedKeyframe<Vector3>(time, new Vector3\n                        (\n                            -data[curveIndex++ + offset],\n                            data[curveIndex++ + offset],\n                            data[curveIndex++ + offset]\n                        )));\n                        break;\n                    case 2:\n                        var value = Fbx.QuaternionToEuler(new Quaternion\n                        (\n                            data[curveIndex++ + offset],\n                            -data[curveIndex++ + offset],\n                            -data[curveIndex++ + offset],\n                            data[curveIndex++ + offset]\n                        ));\n                        track.Rotations.Add(new ImportedKeyframe<Vector3>(time, value));\n                        break;\n                    case 3:\n                        track.Scalings.Add(new ImportedKeyframe<Vector3>(time, new Vector3\n                        (\n                            data[curveIndex++ + offset],\n                            data[curveIndex++ + offset],\n                            data[curveIndex++ + offset]\n                        )));\n                        break;\n                    case 4:\n                        track.Rotations.Add(new ImportedKeyframe<Vector3>(time, new Vector3\n                        (\n                            data[curveIndex++ + offset],\n                            -data[curveIndex++ + offset],\n                            -data[curveIndex++ + offset]\n                        )));\n                        break;\n                    default:\n                        curveIndex++;\n                        break;\n                }\n            }\n            else\n            {\n                curveIndex++;\n            }\n        }\n\n        private string GetPathFromHash(uint hash)\n        {\n            bonePathHash.TryGetValue(hash, out var boneName);\n            if (string.IsNullOrEmpty(boneName))\n            {\n                boneName = avatar?.FindBonePath(hash);\n            }\n            if (string.IsNullOrEmpty(boneName))\n            {\n                boneName = \"unknown \" + hash;\n            }\n            return boneName;\n        }\n\n        private void CreateBonePathHash(Transform m_Transform)\n        {\n            var name = GetTransformPathByFather(m_Transform);\n            var crc = new SevenZip.CRC();\n            var bytes = Encoding.UTF8.GetBytes(name);\n            crc.Update(bytes, 0, (uint)bytes.Length);\n            bonePathHash[crc.GetDigest()] = name;\n            int index;\n            while ((index = name.IndexOf(\"/\", StringComparison.Ordinal)) >= 0)\n            {\n                name = name.Substring(index + 1);\n                crc = new SevenZip.CRC();\n                bytes = Encoding.UTF8.GetBytes(name);\n                crc.Update(bytes, 0, (uint)bytes.Length);\n                bonePathHash[crc.GetDigest()] = name;\n            }\n            foreach (var pptr in m_Transform.m_Children)\n            {\n                if (pptr.TryGet(out var child))\n                    CreateBonePathHash(child);\n            }\n        }\n\n        private void DeoptimizeTransformHierarchy()\n        {\n            if (avatar == null)\n                throw new Exception(\"Transform hierarchy has been optimized, but can't find Avatar to deoptimize.\");\n            // 1. Figure out the skeletonPaths from the unstripped avatar\n            var skeletonPaths = new List<string>();\n            foreach (var id in avatar.m_Avatar.m_AvatarSkeleton.m_ID)\n            {\n                var path = avatar.FindBonePath(id);\n                skeletonPaths.Add(path);\n            }\n            // 2. Restore the original transform hierarchy\n            // Prerequisite: skeletonPaths follow pre-order traversal\n            for (var i = 1; i < skeletonPaths.Count; i++) // start from 1, skip the root transform because it will always be there.\n            {\n                var path = skeletonPaths[i];\n                var strs = path.Split('/');\n                string transformName;\n                ImportedFrame parentFrame;\n                if (strs.Length == 1)\n                {\n                    transformName = path;\n                    parentFrame = RootFrame;\n                }\n                else\n                {\n                    transformName = strs.Last();\n                    var parentFramePath = path.Substring(0, path.LastIndexOf('/'));\n                    parentFrame = RootFrame.FindRelativeFrameWithPath(parentFramePath);\n                }\n                var skeletonPose = avatar.m_Avatar.m_DefaultPose;\n                var xform = skeletonPose.m_X[i];\n                var frame = RootFrame.FindChild(transformName);\n                if (frame != null)\n                {\n                    SetFrame(frame, xform.t, xform.q, xform.s);\n                }\n                else\n                {\n                    frame = CreateFrame(transformName, xform.t, xform.q, xform.s);\n                }\n                parentFrame.AddChild(frame);\n            }\n        }\n\n        private string GetPathByChannelName(string channelName)\n        {\n            foreach (var morph in MorphList)\n            {\n                foreach (var channel in morph.Channels)\n                {\n                    if (channel.Name == channelName)\n                    {\n                        return morph.Path;\n                    }\n                }\n            }\n            return null;\n        }\n\n        private string GetChannelNameFromHash(uint attribute)\n        {\n            if (morphChannelNames.TryGetValue(attribute, out var name))\n            {\n                return name;\n            }\n            else\n            {\n                return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/ModelExporter.cs",
    "content": "﻿namespace AssetStudio\n{\n    public static class ModelExporter\n    {\n        public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision,\n            bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii)\n        {\n            Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allNodes, skins, animation, blendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, versionIndex, isAscii);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/MonoBehaviourConverter.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace AssetStudio\n{\n    public static class MonoBehaviourConverter\n    {\n        public static TypeTree ConvertToTypeTree(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader)\n        {\n            var m_Type = new TypeTree();\n            m_Type.m_Nodes = new List<TypeTreeNode>();\n            var helper = new SerializedTypeHelper(m_MonoBehaviour.version);\n            helper.AddMonoBehaviour(m_Type.m_Nodes, 0);\n            if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))\n            {\n                var typeDef = assemblyLoader.GetTypeDefinition(m_Script.m_AssemblyName, string.IsNullOrEmpty(m_Script.m_Namespace) ? m_Script.m_ClassName : $\"{m_Script.m_Namespace}.{m_Script.m_ClassName}\");\n                if (typeDef != null)\n                {\n                    var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, helper, 1);\n                    m_Type.m_Nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes());\n                }\n            }\n            return m_Type;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/MyAssemblyResolver.cs",
    "content": "﻿using Mono.Cecil;\n\nnamespace AssetStudio\n{\n    public class MyAssemblyResolver : DefaultAssemblyResolver\n    {\n        public void Register(AssemblyDefinition assembly)\n        {\n            RegisterAssembly(assembly);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/SerializedTypeHelper.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace AssetStudio\n{\n    public class SerializedTypeHelper\n    {\n        private readonly int[] version;\n\n        public SerializedTypeHelper(int[] version)\n        {\n            this.version = version;\n        }\n\n        public void AddMonoBehaviour(List<TypeTreeNode> nodes, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"MonoBehaviour\", \"Base\", indent, false));\n            AddPPtr(nodes, \"GameObject\", \"m_GameObject\", indent + 1);\n            nodes.Add(new TypeTreeNode(\"UInt8\", \"m_Enabled\", indent + 1, true));\n            AddPPtr(nodes, \"MonoScript\", \"m_Script\", indent + 1);\n            AddString(nodes, \"m_Name\", indent + 1);\n        }\n\n        public void AddPPtr(List<TypeTreeNode> nodes, string type, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode($\"PPtr<{type}>\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"int\", \"m_FileID\", indent + 1, false));\n            if (version[0] >= 5) //5.0 and up\n            {\n                nodes.Add(new TypeTreeNode(\"SInt64\", \"m_PathID\", indent + 1, false));\n            }\n            else\n            {\n                nodes.Add(new TypeTreeNode(\"int\", \"m_PathID\", indent + 1, false));\n            }\n        }\n\n        public void AddString(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"string\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"Array\", \"Array\", indent + 1, true));\n            nodes.Add(new TypeTreeNode(\"int\", \"size\", indent + 2, false));\n            nodes.Add(new TypeTreeNode(\"char\", \"data\", indent + 2, false));\n        }\n\n        public void AddArray(List<TypeTreeNode> nodes, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"Array\", \"Array\", indent, false));\n            nodes.Add(new TypeTreeNode(\"int\", \"size\", indent + 1, false));\n        }\n\n        public void AddAnimationCurve(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"AnimationCurve\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"vector\", \"m_Curve\", indent + 1, false));\n            AddArray(nodes, indent + 2); //TODO 2017 and up Array align but no effect \n            nodes.Add(new TypeTreeNode(\"Keyframe\", \"data\", indent + 3, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"time\", indent + 4, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"value\", indent + 4, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"inSlope\", indent + 4, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"outSlope\", indent + 4, false));\n            if (version[0] >= 2018) //2018 and up\n            {\n                nodes.Add(new TypeTreeNode(\"int\", \"weightedMode\", indent + 4, false));\n                nodes.Add(new TypeTreeNode(\"float\", \"inWeight\", indent + 4, false));\n                nodes.Add(new TypeTreeNode(\"float\", \"outWeight\", indent + 4, false));\n            }\n            nodes.Add(new TypeTreeNode(\"int\", \"m_PreInfinity\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"int\", \"m_PostInfinity\", indent + 1, false));\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up\n            {\n                nodes.Add(new TypeTreeNode(\"int\", \"m_RotationOrder\", indent + 1, false));\n            }\n        }\n\n        public void AddGradient(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"Gradient\", name, indent, false));\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up\n            {\n                AddColorRGBA(nodes, \"key0\", indent + 1);\n                AddColorRGBA(nodes, \"key1\", indent + 1);\n                AddColorRGBA(nodes, \"key2\", indent + 1);\n                AddColorRGBA(nodes, \"key3\", indent + 1);\n                AddColorRGBA(nodes, \"key4\", indent + 1);\n                AddColorRGBA(nodes, \"key5\", indent + 1);\n                AddColorRGBA(nodes, \"key6\", indent + 1);\n                AddColorRGBA(nodes, \"key7\", indent + 1);\n            }\n            else\n            {\n                AddColor32(nodes, \"key0\", indent + 1);\n                AddColor32(nodes, \"key1\", indent + 1);\n                AddColor32(nodes, \"key2\", indent + 1);\n                AddColor32(nodes, \"key3\", indent + 1);\n                AddColor32(nodes, \"key4\", indent + 1);\n                AddColor32(nodes, \"key5\", indent + 1);\n                AddColor32(nodes, \"key6\", indent + 1);\n                AddColor32(nodes, \"key7\", indent + 1);\n            }\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime0\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime1\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime2\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime3\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime4\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime5\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime6\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"ctime7\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime0\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime1\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime2\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime3\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime4\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime5\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime6\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt16\", \"atime7\", indent + 1, false));\n            if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up\n            {\n                nodes.Add(new TypeTreeNode(\"int\", \"m_Mode\", indent + 1, false));\n            }\n            nodes.Add(new TypeTreeNode(\"UInt8\", \"m_NumColorKeys\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"UInt8\", \"m_NumAlphaKeys\", indent + 1, true));\n        }\n\n        public void AddGUIStyle(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"GUIStyle\", name, indent, false));\n            AddString(nodes, \"m_Name\", indent + 1);\n            AddGUIStyleState(nodes, \"m_Normal\", indent + 1);\n            AddGUIStyleState(nodes, \"m_Hover\", indent + 1);\n            AddGUIStyleState(nodes, \"m_Active\", indent + 1);\n            AddGUIStyleState(nodes, \"m_Focused\", indent + 1);\n            AddGUIStyleState(nodes, \"m_OnNormal\", indent + 1);\n            AddGUIStyleState(nodes, \"m_OnHover\", indent + 1);\n            AddGUIStyleState(nodes, \"m_OnActive\", indent + 1);\n            AddGUIStyleState(nodes, \"m_OnFocused\", indent + 1);\n            AddRectOffset(nodes, \"m_Border\", indent + 1);\n            if (version[0] >= 4) //4 and up\n            {\n                AddRectOffset(nodes, \"m_Margin\", indent + 1);\n                AddRectOffset(nodes, \"m_Padding\", indent + 1);\n            }\n            else\n            {\n                AddRectOffset(nodes, \"m_Padding\", indent + 1);\n                AddRectOffset(nodes, \"m_Margin\", indent + 1);\n            }\n            AddRectOffset(nodes, \"m_Overflow\", indent + 1);\n            AddPPtr(nodes, \"Font\", \"m_Font\", indent + 1);\n            if (version[0] >= 4) //4 and up\n            {\n                nodes.Add(new TypeTreeNode(\"int\", \"m_FontSize\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"int\", \"m_FontStyle\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"int\", \"m_Alignment\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"bool\", \"m_WordWrap\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"bool\", \"m_RichText\", indent + 1, true));\n                nodes.Add(new TypeTreeNode(\"int\", \"m_TextClipping\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"int\", \"m_ImagePosition\", indent + 1, false));\n                AddVector2f(nodes, \"m_ContentOffset\", indent + 1);\n                nodes.Add(new TypeTreeNode(\"float\", \"m_FixedWidth\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"float\", \"m_FixedHeight\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"bool\", \"m_StretchWidth\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"bool\", \"m_StretchHeight\", indent + 1, true));\n            }\n            else\n            {\n                nodes.Add(new TypeTreeNode(\"int\", \"m_ImagePosition\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"int\", \"m_Alignment\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"bool\", \"m_WordWrap\", indent + 1, true));\n                nodes.Add(new TypeTreeNode(\"int\", \"m_TextClipping\", indent + 1, false));\n                AddVector2f(nodes, \"m_ContentOffset\", indent + 1);\n                AddVector2f(nodes, \"m_ClipOffset\", indent + 1);\n                nodes.Add(new TypeTreeNode(\"float\", \"m_FixedWidth\", indent + 1, false));\n                nodes.Add(new TypeTreeNode(\"float\", \"m_FixedHeight\", indent + 1, false));\n                if (version[0] >= 3) //3 and up\n                {\n                    nodes.Add(new TypeTreeNode(\"int\", \"m_FontSize\", indent + 1, false));\n                    nodes.Add(new TypeTreeNode(\"int\", \"m_FontStyle\", indent + 1, false));\n                }\n                nodes.Add(new TypeTreeNode(\"bool\", \"m_StretchWidth\", indent + 1, true));\n                nodes.Add(new TypeTreeNode(\"bool\", \"m_StretchHeight\", indent + 1, true));\n            }\n        }\n\n        public void AddGUIStyleState(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"GUIStyleState\", name, indent, false));\n            AddPPtr(nodes, \"Texture2D\", \"m_Background\", indent + 1);\n            AddColorRGBA(nodes, \"m_TextColor\", indent + 1);\n        }\n\n        public void AddVector2f(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"Vector2f\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"x\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"y\", indent + 1, false));\n        }\n\n        public void AddRectOffset(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"RectOffset\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"int\", \"m_Left\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"int\", \"m_Right\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"int\", \"m_Top\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"int\", \"m_Bottom\", indent + 1, false));\n        }\n\n        public void AddColorRGBA(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"ColorRGBA\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"r\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"g\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"b\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"a\", indent + 1, false));\n        }\n\n        public void AddColor32(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"ColorRGBA\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"unsigned int\", \"rgba\", indent + 1, false));\n        }\n\n        public void AddMatrix4x4(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"Matrix4x4f\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e00\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e01\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e02\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e03\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e10\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e11\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e12\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e13\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e20\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e21\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e22\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e23\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e30\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e31\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e32\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"e33\", indent + 1, false));\n        }\n\n        public void AddSphericalHarmonicsL2(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"SphericalHarmonicsL2\", name, indent, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 0]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 1]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 2]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 3]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 4]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 5]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 6]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 7]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 8]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[ 9]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[10]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[11]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[12]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[13]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[14]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[15]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[16]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[17]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[18]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[19]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[20]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[21]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[22]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[23]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[24]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[25]\", indent + 1, false));\n            nodes.Add(new TypeTreeNode(\"float\", \"sh[26]\", indent + 1, false));\n        }\n\n        public void AddPropertyName(List<TypeTreeNode> nodes, string name, int indent)\n        {\n            nodes.Add(new TypeTreeNode(\"PropertyName\", name, indent, false));\n            AddString(nodes, \"id\", indent + 1);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/ShaderConverter.cs",
    "content": "﻿using K4os.Compression.LZ4;\nusing System;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Text.RegularExpressions;\n\nnamespace AssetStudio\n{\n    public static class ShaderConverter\n    {\n        public static string Convert(this Shader shader)\n        {\n            if (shader.m_SubProgramBlob != null) //5.3 - 5.4\n            {\n                var decompressedBytes = new byte[shader.decompressedSize];\n                LZ4Codec.Decode(shader.m_SubProgramBlob, decompressedBytes);\n                using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))\n                {\n                    var program = new ShaderProgram(blobReader, shader.version);\n                    program.Read(blobReader, 0);\n                    return header + program.Export(Encoding.UTF8.GetString(shader.m_Script));\n                }\n            }\n\n            if (shader.compressedBlob != null) //5.5 and up\n            {\n                return header + ConvertSerializedShader(shader);\n            }\n\n            return header + Encoding.UTF8.GetString(shader.m_Script);\n        }\n\n        private static string ConvertSerializedShader(Shader shader)\n        {\n            var length = shader.platforms.Length;\n            var shaderPrograms = new ShaderProgram[length];\n            for (var i = 0; i < length; i++)\n            {\n                for (var j = 0; j < shader.offsets[i].Length; j++)\n                {\n                    var offset = shader.offsets[i][j];\n                    var compressedLength = shader.compressedLengths[i][j];\n                    var decompressedLength = shader.decompressedLengths[i][j];\n                    var decompressedBytes = new byte[decompressedLength];\n                    LZ4Codec.Decode(shader.compressedBlob, (int)offset, (int)compressedLength, decompressedBytes, 0, (int)decompressedLength);\n                    using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))\n                    {\n                        if (j == 0)\n                        {\n                            shaderPrograms[i] = new ShaderProgram(blobReader, shader.version);\n                        }\n                        shaderPrograms[i].Read(blobReader, j);\n                    }\n                }\n            }\n\n            return ConvertSerializedShader(shader.m_ParsedForm, shader.platforms, shaderPrograms);\n        }\n\n        private static string ConvertSerializedShader(SerializedShader m_ParsedForm, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)\n        {\n            var sb = new StringBuilder();\n            sb.Append($\"Shader \\\"{m_ParsedForm.m_Name}\\\" {{\\n\");\n\n            sb.Append(ConvertSerializedProperties(m_ParsedForm.m_PropInfo));\n\n            foreach (var m_SubShader in m_ParsedForm.m_SubShaders)\n            {\n                sb.Append(ConvertSerializedSubShader(m_SubShader, platforms, shaderPrograms));\n            }\n\n            if (!string.IsNullOrEmpty(m_ParsedForm.m_FallbackName))\n            {\n                sb.Append($\"Fallback \\\"{m_ParsedForm.m_FallbackName}\\\"\\n\");\n            }\n\n            if (!string.IsNullOrEmpty(m_ParsedForm.m_CustomEditorName))\n            {\n                sb.Append($\"CustomEditor \\\"{m_ParsedForm.m_CustomEditorName}\\\"\\n\");\n            }\n\n            sb.Append(\"}\");\n            return sb.ToString();\n        }\n\n        private static string ConvertSerializedSubShader(SerializedSubShader m_SubShader, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)\n        {\n            var sb = new StringBuilder();\n            sb.Append(\"SubShader {\\n\");\n            if (m_SubShader.m_LOD != 0)\n            {\n                sb.Append($\" LOD {m_SubShader.m_LOD}\\n\");\n            }\n\n            sb.Append(ConvertSerializedTagMap(m_SubShader.m_Tags, 1));\n\n            foreach (var m_Passe in m_SubShader.m_Passes)\n            {\n                sb.Append(ConvertSerializedPass(m_Passe, platforms, shaderPrograms));\n            }\n            sb.Append(\"}\\n\");\n            return sb.ToString();\n        }\n\n        private static string ConvertSerializedPass(SerializedPass m_Passe, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)\n        {\n            var sb = new StringBuilder();\n            switch (m_Passe.m_Type)\n            {\n                case PassType.Normal:\n                    sb.Append(\" Pass \");\n                    break;\n                case PassType.Use:\n                    sb.Append(\" UsePass \");\n                    break;\n                case PassType.Grab:\n                    sb.Append(\" GrabPass \");\n                    break;\n            }\n            if (m_Passe.m_Type == PassType.Use)\n            {\n                sb.Append($\"\\\"{m_Passe.m_UseName}\\\"\\n\");\n            }\n            else\n            {\n                sb.Append(\"{\\n\");\n\n                if (m_Passe.m_Type == PassType.Grab)\n                {\n                    if (!string.IsNullOrEmpty(m_Passe.m_TextureName))\n                    {\n                        sb.Append($\"  \\\"{m_Passe.m_TextureName}\\\"\\n\");\n                    }\n                }\n                else\n                {\n                    sb.Append(ConvertSerializedShaderState(m_Passe.m_State));\n\n                    if (m_Passe.progVertex.m_SubPrograms.Length > 0)\n                    {\n                        sb.Append(\"Program \\\"vp\\\" {\\n\");\n                        sb.Append(ConvertSerializedSubPrograms(m_Passe.progVertex.m_SubPrograms, platforms, shaderPrograms));\n                        sb.Append(\"}\\n\");\n                    }\n\n                    if (m_Passe.progFragment.m_SubPrograms.Length > 0)\n                    {\n                        sb.Append(\"Program \\\"fp\\\" {\\n\");\n                        sb.Append(ConvertSerializedSubPrograms(m_Passe.progFragment.m_SubPrograms, platforms, shaderPrograms));\n                        sb.Append(\"}\\n\");\n                    }\n\n                    if (m_Passe.progGeometry.m_SubPrograms.Length > 0)\n                    {\n                        sb.Append(\"Program \\\"gp\\\" {\\n\");\n                        sb.Append(ConvertSerializedSubPrograms(m_Passe.progGeometry.m_SubPrograms, platforms, shaderPrograms));\n                        sb.Append(\"}\\n\");\n                    }\n\n                    if (m_Passe.progHull.m_SubPrograms.Length > 0)\n                    {\n                        sb.Append(\"Program \\\"hp\\\" {\\n\");\n                        sb.Append(ConvertSerializedSubPrograms(m_Passe.progHull.m_SubPrograms, platforms, shaderPrograms));\n                        sb.Append(\"}\\n\");\n                    }\n\n                    if (m_Passe.progDomain.m_SubPrograms.Length > 0)\n                    {\n                        sb.Append(\"Program \\\"dp\\\" {\\n\");\n                        sb.Append(ConvertSerializedSubPrograms(m_Passe.progDomain.m_SubPrograms, platforms, shaderPrograms));\n                        sb.Append(\"}\\n\");\n                    }\n\n                    if (m_Passe.progRayTracing?.m_SubPrograms.Length > 0)\n                    {\n                        sb.Append(\"Program \\\"rtp\\\" {\\n\");\n                        sb.Append(ConvertSerializedSubPrograms(m_Passe.progRayTracing.m_SubPrograms, platforms, shaderPrograms));\n                        sb.Append(\"}\\n\");\n                    }\n                }\n                sb.Append(\"}\\n\");\n            }\n            return sb.ToString();\n        }\n\n        private static string ConvertSerializedSubPrograms(SerializedSubProgram[] m_SubPrograms, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)\n        {\n            var sb = new StringBuilder();\n            var groups = m_SubPrograms.GroupBy(x => x.m_BlobIndex);\n            foreach (var group in groups)\n            {\n                var programs = group.GroupBy(x => x.m_GpuProgramType);\n                foreach (var program in programs)\n                {\n                    for (int i = 0; i < platforms.Length; i++)\n                    {\n                        var platform = platforms[i];\n                        if (CheckGpuProgramUsable(platform, program.Key))\n                        {\n                            var subPrograms = program.ToList();\n                            var isTier = subPrograms.Count > 1;\n                            foreach (var subProgram in subPrograms)\n                            {\n                                sb.Append($\"SubProgram \\\"{GetPlatformString(platform)} \");\n                                if (isTier)\n                                {\n                                    sb.Append($\"hw_tier{subProgram.m_ShaderHardwareTier:00} \");\n                                }\n                                sb.Append(\"\\\" {\\n\");\n                                sb.Append(shaderPrograms[i].m_SubPrograms[subProgram.m_BlobIndex].Export());\n                                sb.Append(\"\\n}\\n\");\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n            return sb.ToString();\n        }\n\n        private static string ConvertSerializedShaderState(SerializedShaderState m_State)\n        {\n            var sb = new StringBuilder();\n            if (!string.IsNullOrEmpty(m_State.m_Name))\n            {\n                sb.Append($\"  Name \\\"{m_State.m_Name}\\\"\\n\");\n            }\n            if (m_State.m_LOD != 0)\n            {\n                sb.Append($\"  LOD {m_State.m_LOD}\\n\");\n            }\n\n            sb.Append(ConvertSerializedTagMap(m_State.m_Tags, 2));\n\n            sb.Append(ConvertSerializedShaderRTBlendState(m_State.rtBlend, m_State.rtSeparateBlend));\n\n            if (m_State.alphaToMask.val > 0f)\n            {\n                sb.Append(\"  AlphaToMask On\\n\");\n            }\n\n            if (m_State.zClip?.val != 1f) //ZClip On\n            {\n                sb.Append(\"  ZClip Off\\n\");\n            }\n\n            if (m_State.zTest.val != 4f) //ZTest LEqual\n            {\n                sb.Append(\"  ZTest \");\n                switch (m_State.zTest.val) //enum CompareFunction\n                {\n                    case 0f: //kFuncDisabled\n                        sb.Append(\"Off\");\n                        break;\n                    case 1f: //kFuncNever\n                        sb.Append(\"Never\");\n                        break;\n                    case 2f: //kFuncLess\n                        sb.Append(\"Less\");\n                        break;\n                    case 3f: //kFuncEqual\n                        sb.Append(\"Equal\");\n                        break;\n                    case 5f: //kFuncGreater\n                        sb.Append(\"Greater\");\n                        break;\n                    case 6f: //kFuncNotEqual\n                        sb.Append(\"NotEqual\");\n                        break;\n                    case 7f: //kFuncGEqual\n                        sb.Append(\"GEqual\");\n                        break;\n                    case 8f: //kFuncAlways\n                        sb.Append(\"Always\");\n                        break;\n                }\n\n                sb.Append(\"\\n\");\n            }\n\n            if (m_State.zWrite.val != 1f) //ZWrite On\n            {\n                sb.Append(\"  ZWrite Off\\n\");\n            }\n\n            if (m_State.culling.val != 2f) //Cull Back\n            {\n                sb.Append(\"  Cull \");\n                switch (m_State.culling.val) //enum CullMode\n                {\n                    case 0f: //kCullOff\n                        sb.Append(\"Off\");\n                        break;\n                    case 1f: //kCullFront\n                        sb.Append(\"Front\");\n                        break;\n                }\n                sb.Append(\"\\n\");\n            }\n\n            if (m_State.offsetFactor.val != 0f || m_State.offsetUnits.val != 0f)\n            {\n                sb.Append($\"  Offset {m_State.offsetFactor.val}, {m_State.offsetUnits.val}\\n\");\n            }\n\n            if (m_State.stencilRef.val != 0f ||\n                m_State.stencilReadMask.val != 255f ||\n                m_State.stencilWriteMask.val != 255f ||\n                m_State.stencilOp.pass.val != 0f ||\n                m_State.stencilOp.fail.val != 0f ||\n                m_State.stencilOp.zFail.val != 0f ||\n                m_State.stencilOp.comp.val != 8f ||\n                m_State.stencilOpFront.pass.val != 0f ||\n                m_State.stencilOpFront.fail.val != 0f ||\n                m_State.stencilOpFront.zFail.val != 0f ||\n                m_State.stencilOpFront.comp.val != 8f ||\n                m_State.stencilOpBack.pass.val != 0f ||\n                m_State.stencilOpBack.fail.val != 0f ||\n                m_State.stencilOpBack.zFail.val != 0f ||\n                m_State.stencilOpBack.comp.val != 8f)\n            {\n                sb.Append(\"  Stencil {\\n\");\n                if (m_State.stencilRef.val != 0f)\n                {\n                    sb.Append($\"   Ref {m_State.stencilRef.val}\\n\");\n                }\n                if (m_State.stencilReadMask.val != 255f)\n                {\n                    sb.Append($\"   ReadMask {m_State.stencilReadMask.val}\\n\");\n                }\n                if (m_State.stencilWriteMask.val != 255f)\n                {\n                    sb.Append($\"   WriteMask {m_State.stencilWriteMask.val}\\n\");\n                }\n                if (m_State.stencilOp.pass.val != 0f ||\n                    m_State.stencilOp.fail.val != 0f ||\n                    m_State.stencilOp.zFail.val != 0f ||\n                    m_State.stencilOp.comp.val != 8f)\n                {\n                    sb.Append(ConvertSerializedStencilOp(m_State.stencilOp, \"\"));\n                }\n                if (m_State.stencilOpFront.pass.val != 0f ||\n                    m_State.stencilOpFront.fail.val != 0f ||\n                    m_State.stencilOpFront.zFail.val != 0f ||\n                    m_State.stencilOpFront.comp.val != 8f)\n                {\n                    sb.Append(ConvertSerializedStencilOp(m_State.stencilOpFront, \"Front\"));\n                }\n                if (m_State.stencilOpBack.pass.val != 0f ||\n                    m_State.stencilOpBack.fail.val != 0f ||\n                    m_State.stencilOpBack.zFail.val != 0f ||\n                    m_State.stencilOpBack.comp.val != 8f)\n                {\n                    sb.Append(ConvertSerializedStencilOp(m_State.stencilOpBack, \"Back\"));\n                }\n                sb.Append(\"  }\\n\");\n            }\n\n            if (m_State.fogMode != FogMode.Unknown ||\n                m_State.fogColor.x.val != 0f ||\n                m_State.fogColor.y.val != 0f ||\n                m_State.fogColor.z.val != 0f ||\n                m_State.fogColor.w.val != 0f ||\n                m_State.fogDensity.val != 0f ||\n                m_State.fogStart.val != 0f ||\n                m_State.fogEnd.val != 0f)\n            {\n                sb.Append(\"  Fog {\\n\");\n                if (m_State.fogMode != FogMode.Unknown)\n                {\n                    sb.Append(\"   Mode \");\n                    switch (m_State.fogMode)\n                    {\n                        case FogMode.Disabled:\n                            sb.Append(\"Off\");\n                            break;\n                        case FogMode.Linear:\n                            sb.Append(\"Linear\");\n                            break;\n                        case FogMode.Exp:\n                            sb.Append(\"Exp\");\n                            break;\n                        case FogMode.Exp2:\n                            sb.Append(\"Exp2\");\n                            break;\n                    }\n                    sb.Append(\"\\n\");\n                }\n                if (m_State.fogColor.x.val != 0f ||\n                    m_State.fogColor.y.val != 0f ||\n                    m_State.fogColor.z.val != 0f ||\n                    m_State.fogColor.w.val != 0f)\n                {\n                    sb.AppendFormat(\"   Color ({0},{1},{2},{3})\\n\",\n                        m_State.fogColor.x.val.ToString(CultureInfo.InvariantCulture),\n                        m_State.fogColor.y.val.ToString(CultureInfo.InvariantCulture),\n                        m_State.fogColor.z.val.ToString(CultureInfo.InvariantCulture),\n                        m_State.fogColor.w.val.ToString(CultureInfo.InvariantCulture));\n                }\n                if (m_State.fogDensity.val != 0f)\n                {\n                    sb.Append($\"   Density {m_State.fogDensity.val.ToString(CultureInfo.InvariantCulture)}\\n\");\n                }\n                if (m_State.fogStart.val != 0f ||\n                    m_State.fogEnd.val != 0f)\n                {\n                    sb.Append($\"   Range {m_State.fogStart.val.ToString(CultureInfo.InvariantCulture)}, {m_State.fogEnd.val.ToString(CultureInfo.InvariantCulture)}\\n\");\n                }\n                sb.Append(\"  }\\n\");\n            }\n\n            if (m_State.lighting)\n            {\n                sb.Append($\"  Lighting {(m_State.lighting ? \"On\" : \"Off\")}\\n\");\n            }\n\n            sb.Append($\"  GpuProgramID {m_State.gpuProgramID}\\n\");\n\n            return sb.ToString();\n        }\n\n        private static string ConvertSerializedStencilOp(SerializedStencilOp stencilOp, string suffix)\n        {\n            var sb = new StringBuilder();\n            sb.Append($\"   Comp{suffix} {ConvertStencilComp(stencilOp.comp)}\\n\");\n            sb.Append($\"   Pass{suffix} {ConvertStencilOp(stencilOp.pass)}\\n\");\n            sb.Append($\"   Fail{suffix} {ConvertStencilOp(stencilOp.fail)}\\n\");\n            sb.Append($\"   ZFail{suffix} {ConvertStencilOp(stencilOp.zFail)}\\n\");\n            return sb.ToString();\n        }\n\n        private static string ConvertStencilOp(SerializedShaderFloatValue op)\n        {\n            switch (op.val)\n            {\n                case 0f:\n                default:\n                    return \"Keep\";\n                case 1f:\n                    return \"Zero\";\n                case 2f:\n                    return \"Replace\";\n                case 3f:\n                    return \"IncrSat\";\n                case 4f:\n                    return \"DecrSat\";\n                case 5f:\n                    return \"Invert\";\n                case 6f:\n                    return \"IncrWrap\";\n                case 7f:\n                    return \"DecrWrap\";\n            }\n        }\n\n        private static string ConvertStencilComp(SerializedShaderFloatValue comp)\n        {\n            switch (comp.val)\n            {\n                case 0f:\n                    return \"Disabled\";\n                case 1f:\n                    return \"Never\";\n                case 2f:\n                    return \"Less\";\n                case 3f:\n                    return \"Equal\";\n                case 4f:\n                    return \"LEqual\";\n                case 5f:\n                    return \"Greater\";\n                case 6f:\n                    return \"NotEqual\";\n                case 7f:\n                    return \"GEqual\";\n                case 8f:\n                default:\n                    return \"Always\";\n            }\n        }\n\n        private static string ConvertSerializedShaderRTBlendState(SerializedShaderRTBlendState[] rtBlend, bool rtSeparateBlend)\n        {\n            var sb = new StringBuilder();\n            for (var i = 0; i < rtBlend.Length; i++)\n            {\n                var blend = rtBlend[i];\n                if (blend.srcBlend.val != 1f ||\n                    blend.destBlend.val != 0f ||\n                    blend.srcBlendAlpha.val != 1f ||\n                    blend.destBlendAlpha.val != 0f)\n                {\n                    sb.Append(\"  Blend \");\n                    if (i != 0 || rtSeparateBlend)\n                    {\n                        sb.Append($\"{i} \");\n                    }\n                    sb.Append($\"{ConvertBlendFactor(blend.srcBlend)} {ConvertBlendFactor(blend.destBlend)}\");\n                    if (blend.srcBlendAlpha.val != 1f ||\n                        blend.destBlendAlpha.val != 0f)\n                    {\n                        sb.Append($\", {ConvertBlendFactor(blend.srcBlendAlpha)} {ConvertBlendFactor(blend.destBlendAlpha)}\");\n                    }\n                    sb.Append(\"\\n\");\n                }\n\n                if (blend.blendOp.val != 0f ||\n                    blend.blendOpAlpha.val != 0f)\n                {\n                    sb.Append(\"  BlendOp \");\n                    if (i != 0 || rtSeparateBlend)\n                    {\n                        sb.Append($\"{i} \");\n                    }\n                    sb.Append(ConvertBlendOp(blend.blendOp));\n                    if (blend.blendOpAlpha.val != 0f)\n                    {\n                        sb.Append($\", {ConvertBlendOp(blend.blendOpAlpha)}\");\n                    }\n                    sb.Append(\"\\n\");\n                }\n\n                var val = (int)blend.colMask.val;\n                if (val != 0xf)\n                {\n                    sb.Append(\"  ColorMask \");\n                    if (val == 0)\n                    {\n                        sb.Append(0);\n                    }\n                    else\n                    {\n                        if ((val & 0x2) != 0)\n                        {\n                            sb.Append(\"R\");\n                        }\n                        if ((val & 0x4) != 0)\n                        {\n                            sb.Append(\"G\");\n                        }\n                        if ((val & 0x8) != 0)\n                        {\n                            sb.Append(\"B\");\n                        }\n                        if ((val & 0x1) != 0)\n                        {\n                            sb.Append(\"A\");\n                        }\n                    }\n                    sb.Append($\" {i}\\n\");\n                }\n            }\n            return sb.ToString();\n        }\n\n        private static string ConvertBlendOp(SerializedShaderFloatValue op)\n        {\n            switch (op.val)\n            {\n                case 0f:\n                default:\n                    return \"Add\";\n                case 1f:\n                    return \"Sub\";\n                case 2f:\n                    return \"RevSub\";\n                case 3f:\n                    return \"Min\";\n                case 4f:\n                    return \"Max\";\n                case 5f:\n                    return \"LogicalClear\";\n                case 6f:\n                    return \"LogicalSet\";\n                case 7f:\n                    return \"LogicalCopy\";\n                case 8f:\n                    return \"LogicalCopyInverted\";\n                case 9f:\n                    return \"LogicalNoop\";\n                case 10f:\n                    return \"LogicalInvert\";\n                case 11f:\n                    return \"LogicalAnd\";\n                case 12f:\n                    return \"LogicalNand\";\n                case 13f:\n                    return \"LogicalOr\";\n                case 14f:\n                    return \"LogicalNor\";\n                case 15f:\n                    return \"LogicalXor\";\n                case 16f:\n                    return \"LogicalEquiv\";\n                case 17f:\n                    return \"LogicalAndReverse\";\n                case 18f:\n                    return \"LogicalAndInverted\";\n                case 19f:\n                    return \"LogicalOrReverse\";\n                case 20f:\n                    return \"LogicalOrInverted\";\n            }\n        }\n\n        private static string ConvertBlendFactor(SerializedShaderFloatValue factor)\n        {\n            switch (factor.val)\n            {\n                case 0f:\n                    return \"Zero\";\n                case 1f:\n                default:\n                    return \"One\";\n                case 2f:\n                    return \"DstColor\";\n                case 3f:\n                    return \"SrcColor\";\n                case 4f:\n                    return \"OneMinusDstColor\";\n                case 5f:\n                    return \"SrcAlpha\";\n                case 6f:\n                    return \"OneMinusSrcColor\";\n                case 7f:\n                    return \"DstAlpha\";\n                case 8f:\n                    return \"OneMinusDstAlpha\";\n                case 9f:\n                    return \"SrcAlphaSaturate\";\n                case 10f:\n                    return \"OneMinusSrcAlpha\";\n            }\n        }\n\n        private static string ConvertSerializedTagMap(SerializedTagMap m_Tags, int intent)\n        {\n            var sb = new StringBuilder();\n            if (m_Tags.tags.Length > 0)\n            {\n                sb.Append(new string(' ', intent));\n                sb.Append(\"Tags { \");\n                foreach (var pair in m_Tags.tags)\n                {\n                    sb.Append($\"\\\"{pair.Key}\\\" = \\\"{pair.Value}\\\" \");\n                }\n                sb.Append(\"}\\n\");\n            }\n            return sb.ToString();\n        }\n\n        private static string ConvertSerializedProperties(SerializedProperties m_PropInfo)\n        {\n            var sb = new StringBuilder();\n            sb.Append(\"Properties {\\n\");\n            foreach (var m_Prop in m_PropInfo.m_Props)\n            {\n                sb.Append(ConvertSerializedProperty(m_Prop));\n            }\n            sb.Append(\"}\\n\");\n            return sb.ToString();\n        }\n\n        private static string ConvertSerializedProperty(SerializedProperty m_Prop)\n        {\n            var sb = new StringBuilder();\n            foreach (var m_Attribute in m_Prop.m_Attributes)\n            {\n                sb.Append($\"[{m_Attribute}] \");\n            }\n            //TODO Flag\n            sb.Append($\"{m_Prop.m_Name} (\\\"{m_Prop.m_Description}\\\", \");\n            switch (m_Prop.m_Type)\n            {\n                case SerializedPropertyType.Color:\n                    sb.Append(\"Color\");\n                    break;\n                case SerializedPropertyType.Vector:\n                    sb.Append(\"Vector\");\n                    break;\n                case SerializedPropertyType.Float:\n                    sb.Append(\"Float\");\n                    break;\n                case SerializedPropertyType.Range:\n                    sb.Append($\"Range({m_Prop.m_DefValue[1]}, {m_Prop.m_DefValue[2]})\");\n                    break;\n                case SerializedPropertyType.Texture:\n                    switch (m_Prop.m_DefTexture.m_TexDim)\n                    {\n                        case TextureDimension.Any:\n                            sb.Append(\"any\");\n                            break;\n                        case TextureDimension.Tex2D:\n                            sb.Append(\"2D\");\n                            break;\n                        case TextureDimension.Tex3D:\n                            sb.Append(\"3D\");\n                            break;\n                        case TextureDimension.Cube:\n                            sb.Append(\"Cube\");\n                            break;\n                        case TextureDimension.Tex2DArray:\n                            sb.Append(\"2DArray\");\n                            break;\n                        case TextureDimension.CubeArray:\n                            sb.Append(\"CubeArray\");\n                            break;\n                    }\n                    break;\n            }\n            sb.Append(\") = \");\n            switch (m_Prop.m_Type)\n            {\n                case SerializedPropertyType.Color:\n                case SerializedPropertyType.Vector:\n                    sb.Append($\"({m_Prop.m_DefValue[0]},{m_Prop.m_DefValue[1]},{m_Prop.m_DefValue[2]},{m_Prop.m_DefValue[3]})\");\n                    break;\n                case SerializedPropertyType.Float:\n                case SerializedPropertyType.Range:\n                    sb.Append(m_Prop.m_DefValue[0]);\n                    break;\n                case SerializedPropertyType.Texture:\n                    sb.Append($\"\\\"{m_Prop.m_DefTexture.m_DefaultName}\\\" {{ }}\");\n                    break;\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n            sb.Append(\"\\n\");\n            return sb.ToString();\n        }\n\n        private static bool CheckGpuProgramUsable(ShaderCompilerPlatform platform, ShaderGpuProgramType programType)\n        {\n            switch (platform)\n            {\n                case ShaderCompilerPlatform.GL:\n                    return programType == ShaderGpuProgramType.GLLegacy;\n                case ShaderCompilerPlatform.D3D9:\n                    return programType == ShaderGpuProgramType.DX9VertexSM20\n                        || programType == ShaderGpuProgramType.DX9VertexSM30\n                        || programType == ShaderGpuProgramType.DX9PixelSM20\n                        || programType == ShaderGpuProgramType.DX9PixelSM30;\n                case ShaderCompilerPlatform.Xbox360:\n                case ShaderCompilerPlatform.PS3:\n                case ShaderCompilerPlatform.PSP2:\n                case ShaderCompilerPlatform.PS4:\n                case ShaderCompilerPlatform.XboxOne:\n                case ShaderCompilerPlatform.N3DS:\n                case ShaderCompilerPlatform.WiiU:\n                case ShaderCompilerPlatform.Switch:\n                case ShaderCompilerPlatform.XboxOneD3D12:\n                case ShaderCompilerPlatform.GameCoreXboxOne:\n                case ShaderCompilerPlatform.GameCoreScarlett:\n                case ShaderCompilerPlatform.PS5:\n                    return programType == ShaderGpuProgramType.ConsoleVS\n                        || programType == ShaderGpuProgramType.ConsoleFS\n                        || programType == ShaderGpuProgramType.ConsoleHS\n                        || programType == ShaderGpuProgramType.ConsoleDS\n                        || programType == ShaderGpuProgramType.ConsoleGS;\n                case ShaderCompilerPlatform.PS5NGGC:\n                    return programType == ShaderGpuProgramType.PS5NGGC;\n                case ShaderCompilerPlatform.D3D11:\n                    return programType == ShaderGpuProgramType.DX11VertexSM40\n                        || programType == ShaderGpuProgramType.DX11VertexSM50\n                        || programType == ShaderGpuProgramType.DX11PixelSM40\n                        || programType == ShaderGpuProgramType.DX11PixelSM50\n                        || programType == ShaderGpuProgramType.DX11GeometrySM40\n                        || programType == ShaderGpuProgramType.DX11GeometrySM50\n                        || programType == ShaderGpuProgramType.DX11HullSM50\n                        || programType == ShaderGpuProgramType.DX11DomainSM50;\n                case ShaderCompilerPlatform.GLES20:\n                    return programType == ShaderGpuProgramType.GLES;\n                case ShaderCompilerPlatform.NaCl: //Obsolete\n                    throw new NotSupportedException();\n                case ShaderCompilerPlatform.Flash: //Obsolete\n                    throw new NotSupportedException();\n                case ShaderCompilerPlatform.D3D11_9x:\n                    return programType == ShaderGpuProgramType.DX10Level9Vertex\n                        || programType == ShaderGpuProgramType.DX10Level9Pixel;\n                case ShaderCompilerPlatform.GLES3Plus:\n                    return programType == ShaderGpuProgramType.GLES31AEP\n                        || programType == ShaderGpuProgramType.GLES31\n                        || programType == ShaderGpuProgramType.GLES3;\n                case ShaderCompilerPlatform.PSM: //Unknown\n                    throw new NotSupportedException();\n                case ShaderCompilerPlatform.Metal:\n                    return programType == ShaderGpuProgramType.MetalVS\n                        || programType == ShaderGpuProgramType.MetalFS;\n                case ShaderCompilerPlatform.OpenGLCore:\n                    return programType == ShaderGpuProgramType.GLCore32\n                        || programType == ShaderGpuProgramType.GLCore41\n                        || programType == ShaderGpuProgramType.GLCore43;\n                case ShaderCompilerPlatform.Vulkan:\n                    return programType == ShaderGpuProgramType.SPIRV;\n                default:\n                    throw new NotSupportedException();\n            }\n        }\n\n        public static string GetPlatformString(ShaderCompilerPlatform platform)\n        {\n            switch (platform)\n            {\n                case ShaderCompilerPlatform.GL:\n                    return \"openGL\";\n                case ShaderCompilerPlatform.D3D9:\n                    return \"d3d9\";\n                case ShaderCompilerPlatform.Xbox360:\n                    return \"xbox360\";\n                case ShaderCompilerPlatform.PS3:\n                    return \"ps3\";\n                case ShaderCompilerPlatform.D3D11:\n                    return \"d3d11\";\n                case ShaderCompilerPlatform.GLES20:\n                    return \"gles\";\n                case ShaderCompilerPlatform.NaCl:\n                    return \"glesdesktop\";\n                case ShaderCompilerPlatform.Flash:\n                    return \"flash\";\n                case ShaderCompilerPlatform.D3D11_9x:\n                    return \"d3d11_9x\";\n                case ShaderCompilerPlatform.GLES3Plus:\n                    return \"gles3\";\n                case ShaderCompilerPlatform.PSP2:\n                    return \"psp2\";\n                case ShaderCompilerPlatform.PS4:\n                    return \"ps4\";\n                case ShaderCompilerPlatform.XboxOne:\n                    return \"xboxone\";\n                case ShaderCompilerPlatform.PSM:\n                    return \"psm\";\n                case ShaderCompilerPlatform.Metal:\n                    return \"metal\";\n                case ShaderCompilerPlatform.OpenGLCore:\n                    return \"glcore\";\n                case ShaderCompilerPlatform.N3DS:\n                    return \"n3ds\";\n                case ShaderCompilerPlatform.WiiU:\n                    return \"wiiu\";\n                case ShaderCompilerPlatform.Vulkan:\n                    return \"vulkan\";\n                case ShaderCompilerPlatform.Switch:\n                    return \"switch\";\n                case ShaderCompilerPlatform.XboxOneD3D12:\n                    return \"xboxone_d3d12\";\n                case ShaderCompilerPlatform.GameCoreXboxOne:\n                    return \"xboxone\";\n                case ShaderCompilerPlatform.GameCoreScarlett:\n                    return \"xbox_scarlett\";\n                case ShaderCompilerPlatform.PS5:\n                    return \"ps5\";\n                case ShaderCompilerPlatform.PS5NGGC:\n                    return \"ps5_nggc\";\n                default:\n                    return \"unknown\";\n            }\n        }\n\n        private static string header = \"//////////////////////////////////////////\\n\" +\n                                      \"//\\n\" +\n                                      \"// NOTE: This is *not* a valid shader file\\n\" +\n                                      \"//\\n\" +\n                                      \"///////////////////////////////////////////\\n\";\n    }\n\n    public class ShaderSubProgramEntry\n    {\n        public int Offset;\n        public int Length;\n        public int Segment;\n\n        public ShaderSubProgramEntry(BinaryReader reader, int[] version)\n        {\n            Offset = reader.ReadInt32();\n            Length = reader.ReadInt32();\n            if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up\n            {\n                Segment = reader.ReadInt32();\n            }\n        }\n    }\n\n    public class ShaderProgram\n    {\n        public ShaderSubProgramEntry[] entries;\n        public ShaderSubProgram[] m_SubPrograms;\n\n        public ShaderProgram(BinaryReader reader, int[] version)\n        {\n            var subProgramsCapacity = reader.ReadInt32();\n            entries = new ShaderSubProgramEntry[subProgramsCapacity];\n            for (int i = 0; i < subProgramsCapacity; i++)\n            {\n                entries[i] = new ShaderSubProgramEntry(reader, version);\n            }\n            m_SubPrograms = new ShaderSubProgram[subProgramsCapacity];\n        }\n\n        public void Read(BinaryReader reader, int segment)\n        {\n            for (int i = 0; i < entries.Length; i++)\n            {\n                var entry = entries[i];\n                if (entry.Segment == segment)\n                {\n                    reader.BaseStream.Position = entry.Offset;\n                    m_SubPrograms[i] = new ShaderSubProgram(reader);\n                }\n            }\n        }\n\n        public string Export(string shader)\n        {\n            var evaluator = new MatchEvaluator(match =>\n            {\n                var index = int.Parse(match.Groups[1].Value);\n                return m_SubPrograms[index].Export();\n            });\n            shader = Regex.Replace(shader, \"GpuProgramIndex (.+)\", evaluator);\n            return shader;\n        }\n    }\n\n    public class ShaderSubProgram\n    {\n        private int m_Version;\n        public ShaderGpuProgramType m_ProgramType;\n        public string[] m_Keywords;\n        public string[] m_LocalKeywords;\n        public byte[] m_ProgramCode;\n\n        public ShaderSubProgram(BinaryReader reader)\n        {\n            //LoadGpuProgramFromData\n            //201509030 - Unity 5.3\n            //201510240 - Unity 5.4\n            //201608170 - Unity 5.5\n            //201609010 - Unity 5.6, 2017.1 & 2017.2\n            //201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1\n            //201802150 - Unity 2018.2 & Unity 2018.3\n            //201806140 - Unity 2019.1~2021.1\n            //202012090 - Unity 2021.2\n            m_Version = reader.ReadInt32();\n            m_ProgramType = (ShaderGpuProgramType)reader.ReadInt32();\n            reader.BaseStream.Position += 12;\n            if (m_Version >= 201608170)\n            {\n                reader.BaseStream.Position += 4;\n            }\n            var m_KeywordsSize = reader.ReadInt32();\n            m_Keywords = new string[m_KeywordsSize];\n            for (int i = 0; i < m_KeywordsSize; i++)\n            {\n                m_Keywords[i] = reader.ReadAlignedString();\n            }\n            if (m_Version >= 201806140 && m_Version < 202012090)\n            {\n                var m_LocalKeywordsSize = reader.ReadInt32();\n                m_LocalKeywords = new string[m_LocalKeywordsSize];\n                for (int i = 0; i < m_LocalKeywordsSize; i++)\n                {\n                    m_LocalKeywords[i] = reader.ReadAlignedString();\n                }\n            }\n            m_ProgramCode = reader.ReadUInt8Array();\n            reader.AlignStream();\n\n            //TODO\n        }\n\n        public string Export()\n        {\n            var sb = new StringBuilder();\n            if (m_Keywords.Length > 0)\n            {\n                sb.Append(\"Keywords { \");\n                foreach (string keyword in m_Keywords)\n                {\n                    sb.Append($\"\\\"{keyword}\\\" \");\n                }\n                sb.Append(\"}\\n\");\n            }\n            if (m_LocalKeywords != null && m_LocalKeywords.Length > 0)\n            {\n                sb.Append(\"Local Keywords { \");\n                foreach (string keyword in m_LocalKeywords)\n                {\n                    sb.Append($\"\\\"{keyword}\\\" \");\n                }\n                sb.Append(\"}\\n\");\n            }\n\n            sb.Append(\"\\\"\");\n            if (m_ProgramCode.Length > 0)\n            {\n                switch (m_ProgramType)\n                {\n                    case ShaderGpuProgramType.GLLegacy:\n                    case ShaderGpuProgramType.GLES31AEP:\n                    case ShaderGpuProgramType.GLES31:\n                    case ShaderGpuProgramType.GLES3:\n                    case ShaderGpuProgramType.GLES:\n                    case ShaderGpuProgramType.GLCore32:\n                    case ShaderGpuProgramType.GLCore41:\n                    case ShaderGpuProgramType.GLCore43:\n                        sb.Append(Encoding.UTF8.GetString(m_ProgramCode));\n                        break;\n                    case ShaderGpuProgramType.DX9VertexSM20:\n                    case ShaderGpuProgramType.DX9VertexSM30:\n                    case ShaderGpuProgramType.DX9PixelSM20:\n                    case ShaderGpuProgramType.DX9PixelSM30:\n                        {\n                            /*var shaderBytecode = new ShaderBytecode(m_ProgramCode);\n                            sb.Append(shaderBytecode.Disassemble());*/\n                            sb.Append(\"// shader disassembly not supported on DXBC\");\n                            break;\n                        }\n                    case ShaderGpuProgramType.DX10Level9Vertex:\n                    case ShaderGpuProgramType.DX10Level9Pixel:\n                    case ShaderGpuProgramType.DX11VertexSM40:\n                    case ShaderGpuProgramType.DX11VertexSM50:\n                    case ShaderGpuProgramType.DX11PixelSM40:\n                    case ShaderGpuProgramType.DX11PixelSM50:\n                    case ShaderGpuProgramType.DX11GeometrySM40:\n                    case ShaderGpuProgramType.DX11GeometrySM50:\n                    case ShaderGpuProgramType.DX11HullSM50:\n                    case ShaderGpuProgramType.DX11DomainSM50:\n                        {\n                            /*int start = 6;\n                            if (m_Version == 201509030) // 5.3\n                            {\n                                start = 5;\n                            }\n                            var buff = new byte[m_ProgramCode.Length - start];\n                            Buffer.BlockCopy(m_ProgramCode, start, buff, 0, buff.Length);\n                            var shaderBytecode = new ShaderBytecode(buff);\n                            sb.Append(shaderBytecode.Disassemble());*/\n                            sb.Append(\"// shader disassembly not supported on DXBC\");\n                            break;\n                        }\n                    case ShaderGpuProgramType.MetalVS:\n                    case ShaderGpuProgramType.MetalFS:\n                        using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode)))\n                        {\n                            var fourCC = reader.ReadUInt32();\n                            if (fourCC == 0xf00dcafe)\n                            {\n                                int offset = reader.ReadInt32();\n                                reader.BaseStream.Position = offset;\n                            }\n                            var entryName = reader.ReadStringToNull();\n                            var buff = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));\n                            sb.Append(Encoding.UTF8.GetString(buff));\n                        }\n                        break;\n                    case ShaderGpuProgramType.SPIRV:\n                        try\n                        {\n                            sb.Append(SpirVShaderConverter.Convert(m_ProgramCode));\n                        }\n                        catch (Exception e)\n                        {\n                            sb.Append($\"// disassembly error {e.Message}\\n\");\n                        }\n                        break;\n                    case ShaderGpuProgramType.ConsoleVS:\n                    case ShaderGpuProgramType.ConsoleFS:\n                    case ShaderGpuProgramType.ConsoleHS:\n                    case ShaderGpuProgramType.ConsoleDS:\n                    case ShaderGpuProgramType.ConsoleGS:\n                        sb.Append(Encoding.UTF8.GetString(m_ProgramCode));\n                        break;\n                    default:\n                        sb.Append($\"//shader disassembly not supported on {m_ProgramType}\");\n                        break;\n                }\n            }\n            sb.Append('\"');\n            return sb.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Smolv/OpData.cs",
    "content": "namespace Smolv\n{\n\tpublic struct OpData\n\t{\n\t\tpublic OpData(byte hasResult, byte hasType, sbyte deltaFromResult, byte varrest)\n\t\t{\n\t\t\tthis.hasResult = hasResult;\n\t\t\tthis.hasType = hasType;\n\t\t\tthis.deltaFromResult = deltaFromResult;\n\t\t\tthis.varrest = varrest;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Does it have result ID?\n\t\t/// </summary>\n\t\tpublic byte hasResult;\n\t\t/// <summary>\n\t\t/// Does it have type ID?\n\t\t/// </summary>\n\t\tpublic byte hasType;\n\t\t/// <summary>\n\t\t/// How many words after (optional) type+result to write out as deltas from result?\n\t\t/// </summary>\n\t\tpublic sbyte deltaFromResult;\n\t\t/// <summary>\n\t\t/// Should the rest of words be written in varint encoding?\n\t\t/// </summary>\n\t\tpublic byte varrest;\n\n\t\tpublic static readonly OpData[] SpirvOpData =\n\t\t{\n\t\t\tnew OpData(0, 0, 0, 0), // Nop\n\t\t\tnew OpData(1, 1, 0, 0), // Undef\n\t\t\tnew OpData(0, 0, 0, 0), // SourceContinued\n\t\t\tnew OpData(0, 0, 0, 1), // Source\n\t\t\tnew OpData(0, 0, 0, 0), // SourceExtension\n\t\t\tnew OpData(0, 0, 0, 0), // Name\n\t\t\tnew OpData(0, 0, 0, 0), // MemberName\n\t\t\tnew OpData(0, 0, 0, 0), // String\n\t\t\tnew OpData(0, 0, 0, 1), // Line\n\t\t\tnew OpData(1, 1, 0, 0), // #9\n\t\t\tnew OpData(0, 0, 0, 0), // Extension\n\t\t\tnew OpData(1, 0, 0, 0), // ExtInstImport\n\t\t\tnew OpData(1, 1, 0, 1), // ExtInst\n\t\t\tnew OpData(1, 1, 2, 1), // VectorShuffleCompact - new in SMOLV\n\t\t\tnew OpData(0, 0, 0, 1), // MemoryModel\n\t\t\tnew OpData(0, 0, 0, 1), // EntryPoint\n\t\t\tnew OpData(0, 0, 0, 1), // ExecutionMode\n\t\t\tnew OpData(0, 0, 0, 1), // Capability\n\t\t\tnew OpData(1, 1, 0, 0), // #18\n\t\t\tnew OpData(1, 0, 0, 1), // TypeVoid\n\t\t\tnew OpData(1, 0, 0, 1), // TypeBool\n\t\t\tnew OpData(1, 0, 0, 1), // TypeInt\n\t\t\tnew OpData(1, 0, 0, 1), // TypeFloat\n\t\t\tnew OpData(1, 0, 0, 1), // TypeVector\n\t\t\tnew OpData(1, 0, 0, 1), // TypeMatrix\n\t\t\tnew OpData(1, 0, 0, 1), // TypeImage\n\t\t\tnew OpData(1, 0, 0, 1), // TypeSampler\n\t\t\tnew OpData(1, 0, 0, 1), // TypeSampledImage\n\t\t\tnew OpData(1, 0, 0, 1), // TypeArray\n\t\t\tnew OpData(1, 0, 0, 1), // TypeRuntimeArray\n\t\t\tnew OpData(1, 0, 0, 1), // TypeStruct\n\t\t\tnew OpData(1, 0, 0, 1), // TypeOpaque\n\t\t\tnew OpData(1, 0, 0, 1), // TypePointer\n\t\t\tnew OpData(1, 0, 0, 1), // TypeFunction\n\t\t\tnew OpData(1, 0, 0, 1), // TypeEvent\n\t\t\tnew OpData(1, 0, 0, 1), // TypeDeviceEvent\n\t\t\tnew OpData(1, 0, 0, 1), // TypeReserveId\n\t\t\tnew OpData(1, 0, 0, 1), // TypeQueue\n\t\t\tnew OpData(1, 0, 0, 1), // TypePipe\n\t\t\tnew OpData(0, 0, 0, 1), // TypeForwardPointer\n\t\t\tnew OpData(1, 1, 0, 0), // #40\n\t\t\tnew OpData(1, 1, 0, 0), // ConstantTrue\n\t\t\tnew OpData(1, 1, 0, 0), // ConstantFalse\n\t\t\tnew OpData(1, 1, 0, 0), // Constant\n\t\t\tnew OpData(1, 1, 9, 0), // ConstantComposite\n\t\t\tnew OpData(1, 1, 0, 1), // ConstantSampler\n\t\t\tnew OpData(1, 1, 0, 0), // ConstantNull\n\t\t\tnew OpData(1, 1, 0, 0), // #47\n\t\t\tnew OpData(1, 1, 0, 0), // SpecConstantTrue\n\t\t\tnew OpData(1, 1, 0, 0), // SpecConstantFalse\n\t\t\tnew OpData(1, 1, 0, 0), // SpecConstant\n\t\t\tnew OpData(1, 1, 9, 0), // SpecConstantComposite\n\t\t\tnew OpData(1, 1, 0, 0), // SpecConstantOp\n\t\t\tnew OpData(1, 1, 0, 0), // #53\n\t\t\tnew OpData(1, 1, 0, 1), // Function\n\t\t\tnew OpData(1, 1, 0, 0), // FunctionParameter\n\t\t\tnew OpData(0, 0, 0, 0), // FunctionEnd\n\t\t\tnew OpData(1, 1, 9, 0), // FunctionCall\n\t\t\tnew OpData(1, 1, 0, 0), // #58\n\t\t\tnew OpData(1, 1, 0, 1), // Variable\n\t\t\tnew OpData(1, 1, 0, 0), // ImageTexelPointer\n\t\t\tnew OpData(1, 1, 1, 1), // Load\n\t\t\tnew OpData(0, 0, 2, 1), // Store\n\t\t\tnew OpData(0, 0, 0, 0), // CopyMemory\n\t\t\tnew OpData(0, 0, 0, 0), // CopyMemorySized\n\t\t\tnew OpData(1, 1, 0, 1), // AccessChain\n\t\t\tnew OpData(1, 1, 0, 0), // InBoundsAccessChain\n\t\t\tnew OpData(1, 1, 0, 0), // PtrAccessChain\n\t\t\tnew OpData(1, 1, 0, 0), // ArrayLength\n\t\t\tnew OpData(1, 1, 0, 0), // GenericPtrMemSemantics\n\t\t\tnew OpData(1, 1, 0, 0), // InBoundsPtrAccessChain\n\t\t\tnew OpData(0, 0, 0, 1), // Decorate\n\t\t\tnew OpData(0, 0, 0, 1), // MemberDecorate\n\t\t\tnew OpData(1, 0, 0, 0), // DecorationGroup\n\t\t\tnew OpData(0, 0, 0, 0), // GroupDecorate\n\t\t\tnew OpData(0, 0, 0, 0), // GroupMemberDecorate\n\t\t\tnew OpData(1, 1, 0, 0), // #76\n\t\t\tnew OpData(1, 1, 1, 1), // VectorExtractDynamic\n\t\t\tnew OpData(1, 1, 2, 1), // VectorInsertDynamic\n\t\t\tnew OpData(1, 1, 2, 1), // VectorShuffle\n\t\t\tnew OpData(1, 1, 9, 0), // CompositeConstruct\n\t\t\tnew OpData(1, 1, 1, 1), // CompositeExtract\n\t\t\tnew OpData(1, 1, 2, 1), // CompositeInsert\n\t\t\tnew OpData(1, 1, 1, 0), // CopyObject\n\t\t\tnew OpData(1, 1, 0, 0), // Transpose\n\t\t\tnew OpData(1, 1, 0, 0), // #85\n\t\t\tnew OpData(1, 1, 0, 0), // SampledImage\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSampleImplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSampleExplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSampleDrefImplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSampleDrefExplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSampleProjImplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSampleProjExplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSampleProjDrefImplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSampleProjDrefExplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageFetch\n\t\t\tnew OpData(1, 1, 3, 1), // ImageGather\n\t\t\tnew OpData(1, 1, 3, 1), // ImageDrefGather\n\t\t\tnew OpData(1, 1, 2, 1), // ImageRead\n\t\t\tnew OpData(0, 0, 3, 1), // ImageWrite\n\t\t\tnew OpData(1, 1, 1, 0), // Image\n\t\t\tnew OpData(1, 1, 1, 0), // ImageQueryFormat\n\t\t\tnew OpData(1, 1, 1, 0), // ImageQueryOrder\n\t\t\tnew OpData(1, 1, 2, 0), // ImageQuerySizeLod\n\t\t\tnew OpData(1, 1, 1, 0), // ImageQuerySize\n\t\t\tnew OpData(1, 1, 2, 0), // ImageQueryLod\n\t\t\tnew OpData(1, 1, 1, 0), // ImageQueryLevels\n\t\t\tnew OpData(1, 1, 1, 0), // ImageQuerySamples\n\t\t\tnew OpData(1, 1, 0, 0), // #108\n\t\t\tnew OpData(1, 1, 1, 0), // ConvertFToU\n\t\t\tnew OpData(1, 1, 1, 0), // ConvertFToS\n\t\t\tnew OpData(1, 1, 1, 0), // ConvertSToF\n\t\t\tnew OpData(1, 1, 1, 0), // ConvertUToF\n\t\t\tnew OpData(1, 1, 1, 0), // UConvert\n\t\t\tnew OpData(1, 1, 1, 0), // SConvert\n\t\t\tnew OpData(1, 1, 1, 0), // FConvert\n\t\t\tnew OpData(1, 1, 1, 0), // QuantizeToF16\n\t\t\tnew OpData(1, 1, 1, 0), // ConvertPtrToU\n\t\t\tnew OpData(1, 1, 1, 0), // SatConvertSToU\n\t\t\tnew OpData(1, 1, 1, 0), // SatConvertUToS\n\t\t\tnew OpData(1, 1, 1, 0), // ConvertUToPtr\n\t\t\tnew OpData(1, 1, 1, 0), // PtrCastToGeneric\n\t\t\tnew OpData(1, 1, 1, 0), // GenericCastToPtr\n\t\t\tnew OpData(1, 1, 1, 1), // GenericCastToPtrExplicit\n\t\t\tnew OpData(1, 1, 1, 0), // Bitcast\n\t\t\tnew OpData(1, 1, 0, 0), // #125\n\t\t\tnew OpData(1, 1, 1, 0), // SNegate\n\t\t\tnew OpData(1, 1, 1, 0), // FNegate\n\t\t\tnew OpData(1, 1, 2, 0), // IAdd\n\t\t\tnew OpData(1, 1, 2, 0), // FAdd\n\t\t\tnew OpData(1, 1, 2, 0), // ISub\n\t\t\tnew OpData(1, 1, 2, 0), // FSub\n\t\t\tnew OpData(1, 1, 2, 0), // IMul\n\t\t\tnew OpData(1, 1, 2, 0), // FMul\n\t\t\tnew OpData(1, 1, 2, 0), // UDiv\n\t\t\tnew OpData(1, 1, 2, 0), // SDiv\n\t\t\tnew OpData(1, 1, 2, 0), // FDiv\n\t\t\tnew OpData(1, 1, 2, 0), // UMod\n\t\t\tnew OpData(1, 1, 2, 0), // SRem\n\t\t\tnew OpData(1, 1, 2, 0), // SMod\n\t\t\tnew OpData(1, 1, 2, 0), // FRem\n\t\t\tnew OpData(1, 1, 2, 0), // FMod\n\t\t\tnew OpData(1, 1, 2, 0), // VectorTimesScalar\n\t\t\tnew OpData(1, 1, 2, 0), // MatrixTimesScalar\n\t\t\tnew OpData(1, 1, 2, 0), // VectorTimesMatrix\n\t\t\tnew OpData(1, 1, 2, 0), // MatrixTimesVector\n\t\t\tnew OpData(1, 1, 2, 0), // MatrixTimesMatrix\n\t\t\tnew OpData(1, 1, 2, 0), // OuterProduct\n\t\t\tnew OpData(1, 1, 2, 0), // Dot\n\t\t\tnew OpData(1, 1, 2, 0), // IAddCarry\n\t\t\tnew OpData(1, 1, 2, 0), // ISubBorrow\n\t\t\tnew OpData(1, 1, 2, 0), // UMulExtended\n\t\t\tnew OpData(1, 1, 2, 0), // SMulExtended\n\t\t\tnew OpData(1, 1, 0, 0), // #153\n\t\t\tnew OpData(1, 1, 1, 0), // Any\n\t\t\tnew OpData(1, 1, 1, 0), // All\n\t\t\tnew OpData(1, 1, 1, 0), // IsNan\n\t\t\tnew OpData(1, 1, 1, 0), // IsInf\n\t\t\tnew OpData(1, 1, 1, 0), // IsFinite\n\t\t\tnew OpData(1, 1, 1, 0), // IsNormal\n\t\t\tnew OpData(1, 1, 1, 0), // SignBitSet\n\t\t\tnew OpData(1, 1, 2, 0), // LessOrGreater\n\t\t\tnew OpData(1, 1, 2, 0), // Ordered\n\t\t\tnew OpData(1, 1, 2, 0), // Unordered\n\t\t\tnew OpData(1, 1, 2, 0), // LogicalEqual\n\t\t\tnew OpData(1, 1, 2, 0), // LogicalNotEqual\n\t\t\tnew OpData(1, 1, 2, 0), // LogicalOr\n\t\t\tnew OpData(1, 1, 2, 0), // LogicalAnd\n\t\t\tnew OpData(1, 1, 1, 0), // LogicalNot\n\t\t\tnew OpData(1, 1, 3, 0), // Select\n\t\t\tnew OpData(1, 1, 2, 0), // IEqual\n\t\t\tnew OpData(1, 1, 2, 0), // INotEqual\n\t\t\tnew OpData(1, 1, 2, 0), // UGreaterThan\n\t\t\tnew OpData(1, 1, 2, 0), // SGreaterThan\n\t\t\tnew OpData(1, 1, 2, 0), // UGreaterThanEqual\n\t\t\tnew OpData(1, 1, 2, 0), // SGreaterThanEqual\n\t\t\tnew OpData(1, 1, 2, 0), // ULessThan\n\t\t\tnew OpData(1, 1, 2, 0), // SLessThan\n\t\t\tnew OpData(1, 1, 2, 0), // ULessThanEqual\n\t\t\tnew OpData(1, 1, 2, 0), // SLessThanEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FOrdEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FUnordEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FOrdNotEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FUnordNotEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FOrdLessThan\n\t\t\tnew OpData(1, 1, 2, 0), // FUnordLessThan\n\t\t\tnew OpData(1, 1, 2, 0), // FOrdGreaterThan\n\t\t\tnew OpData(1, 1, 2, 0), // FUnordGreaterThan\n\t\t\tnew OpData(1, 1, 2, 0), // FOrdLessThanEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FUnordLessThanEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FOrdGreaterThanEqual\n\t\t\tnew OpData(1, 1, 2, 0), // FUnordGreaterThanEqual\n\t\t\tnew OpData(1, 1, 0, 0), // #192\n\t\t\tnew OpData(1, 1, 0, 0), // #193\n\t\t\tnew OpData(1, 1, 2, 0), // ShiftRightLogical\n\t\t\tnew OpData(1, 1, 2, 0), // ShiftRightArithmetic\n\t\t\tnew OpData(1, 1, 2, 0), // ShiftLeftLogical\n\t\t\tnew OpData(1, 1, 2, 0), // BitwiseOr\n\t\t\tnew OpData(1, 1, 2, 0), // BitwiseXor\n\t\t\tnew OpData(1, 1, 2, 0), // BitwiseAnd\n\t\t\tnew OpData(1, 1, 1, 0), // Not\n\t\t\tnew OpData(1, 1, 4, 0), // BitFieldInsert\n\t\t\tnew OpData(1, 1, 3, 0), // BitFieldSExtract\n\t\t\tnew OpData(1, 1, 3, 0), // BitFieldUExtract\n\t\t\tnew OpData(1, 1, 1, 0), // BitReverse\n\t\t\tnew OpData(1, 1, 1, 0), // BitCount\n\t\t\tnew OpData(1, 1, 0, 0), // #206\n\t\t\tnew OpData(1, 1, 0, 0), // DPdx\n\t\t\tnew OpData(1, 1, 0, 0), // DPdy\n\t\t\tnew OpData(1, 1, 0, 0), // Fwidth\n\t\t\tnew OpData(1, 1, 0, 0), // DPdxFine\n\t\t\tnew OpData(1, 1, 0, 0), // DPdyFine\n\t\t\tnew OpData(1, 1, 0, 0), // FwidthFine\n\t\t\tnew OpData(1, 1, 0, 0), // DPdxCoarse\n\t\t\tnew OpData(1, 1, 0, 0), // DPdyCoarse\n\t\t\tnew OpData(1, 1, 0, 0), // FwidthCoarse\n\t\t\tnew OpData(1, 1, 0, 0), // #216\n\t\t\tnew OpData(1, 1, 0, 0), // #217\n\t\t\tnew OpData(0, 0, 0, 0), // EmitVertex\n\t\t\tnew OpData(0, 0, 0, 0), // EndPrimitive\n\t\t\tnew OpData(0, 0, 0, 0), // EmitStreamVertex\n\t\t\tnew OpData(0, 0, 0, 0), // EndStreamPrimitive\n\t\t\tnew OpData(1, 1, 0, 0), // #222\n\t\t\tnew OpData(1, 1, 0, 0), // #223\n\t\t\tnew OpData(0, 0, -3, 0), // ControlBarrier\n\t\t\tnew OpData(0, 0, -2, 0), // MemoryBarrier\n\t\t\tnew OpData(1, 1, 0, 0), // #226\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicLoad\n\t\t\tnew OpData(0, 0, 0, 0), // AtomicStore\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicExchange\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicCompareExchange\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicCompareExchangeWeak\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicIIncrement\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicIDecrement\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicIAdd\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicISub\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicSMin\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicUMin\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicSMax\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicUMax\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicAnd\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicOr\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicXor\n\t\t\tnew OpData(1, 1, 0, 0), // #243\n\t\t\tnew OpData(1, 1, 0, 0), // #244\n\t\t\tnew OpData(1, 1, 0, 0), // Phi\n\t\t\tnew OpData(0, 0, -2, 1), // LoopMerge\n\t\t\tnew OpData(0, 0, -1, 1), // SelectionMerge\n\t\t\tnew OpData(1, 0, 0, 0), // Label\n\t\t\tnew OpData(0, 0, -1, 0), // Branch\n\t\t\tnew OpData(0, 0, -3, 1), // BranchConditional\n\t\t\tnew OpData(0, 0, 0, 0), // Switch\n\t\t\tnew OpData(0, 0, 0, 0), // Kill\n\t\t\tnew OpData(0, 0, 0, 0), // Return\n\t\t\tnew OpData(0, 0, 0, 0), // ReturnValue\n\t\t\tnew OpData(0, 0, 0, 0), // Unreachable\n\t\t\tnew OpData(0, 0, 0, 0), // LifetimeStart\n\t\t\tnew OpData(0, 0, 0, 0), // LifetimeStop\n\t\t\tnew OpData(1, 1, 0, 0), // #258\n\t\t\tnew OpData(1, 1, 0, 0), // GroupAsyncCopy\n\t\t\tnew OpData(0, 0, 0, 0), // GroupWaitEvents\n\t\t\tnew OpData(1, 1, 0, 0), // GroupAll\n\t\t\tnew OpData(1, 1, 0, 0), // GroupAny\n\t\t\tnew OpData(1, 1, 0, 0), // GroupBroadcast\n\t\t\tnew OpData(1, 1, 0, 0), // GroupIAdd\n\t\t\tnew OpData(1, 1, 0, 0), // GroupFAdd\n\t\t\tnew OpData(1, 1, 0, 0), // GroupFMin\n\t\t\tnew OpData(1, 1, 0, 0), // GroupUMin\n\t\t\tnew OpData(1, 1, 0, 0), // GroupSMin\n\t\t\tnew OpData(1, 1, 0, 0), // GroupFMax\n\t\t\tnew OpData(1, 1, 0, 0), // GroupUMax\n\t\t\tnew OpData(1, 1, 0, 0), // GroupSMax\n\t\t\tnew OpData(1, 1, 0, 0), // #272\n\t\t\tnew OpData(1, 1, 0, 0), // #273\n\t\t\tnew OpData(1, 1, 0, 0), // ReadPipe\n\t\t\tnew OpData(1, 1, 0, 0), // WritePipe\n\t\t\tnew OpData(1, 1, 0, 0), // ReservedReadPipe\n\t\t\tnew OpData(1, 1, 0, 0), // ReservedWritePipe\n\t\t\tnew OpData(1, 1, 0, 0), // ReserveReadPipePackets\n\t\t\tnew OpData(1, 1, 0, 0), // ReserveWritePipePackets\n\t\t\tnew OpData(0, 0, 0, 0), // CommitReadPipe\n\t\t\tnew OpData(0, 0, 0, 0), // CommitWritePipe\n\t\t\tnew OpData(1, 1, 0, 0), // IsValidReserveId\n\t\t\tnew OpData(1, 1, 0, 0), // GetNumPipePackets\n\t\t\tnew OpData(1, 1, 0, 0), // GetMaxPipePackets\n\t\t\tnew OpData(1, 1, 0, 0), // GroupReserveReadPipePackets\n\t\t\tnew OpData(1, 1, 0, 0), // GroupReserveWritePipePackets\n\t\t\tnew OpData(0, 0, 0, 0), // GroupCommitReadPipe\n\t\t\tnew OpData(0, 0, 0, 0), // GroupCommitWritePipe\n\t\t\tnew OpData(1, 1, 0, 0), // #289\n\t\t\tnew OpData(1, 1, 0, 0), // #290\n\t\t\tnew OpData(1, 1, 0, 0), // EnqueueMarker\n\t\t\tnew OpData(1, 1, 0, 0), // EnqueueKernel\n\t\t\tnew OpData(1, 1, 0, 0), // GetKernelNDrangeSubGroupCount\n\t\t\tnew OpData(1, 1, 0, 0), // GetKernelNDrangeMaxSubGroupSize\n\t\t\tnew OpData(1, 1, 0, 0), // GetKernelWorkGroupSize\n\t\t\tnew OpData(1, 1, 0, 0), // GetKernelPreferredWorkGroupSizeMultiple\n\t\t\tnew OpData(0, 0, 0, 0), // RetainEvent\n\t\t\tnew OpData(0, 0, 0, 0), // ReleaseEvent\n\t\t\tnew OpData(1, 1, 0, 0), // CreateUserEvent\n\t\t\tnew OpData(1, 1, 0, 0), // IsValidEvent\n\t\t\tnew OpData(0, 0, 0, 0), // SetUserEventStatus\n\t\t\tnew OpData(0, 0, 0, 0), // CaptureEventProfilingInfo\n\t\t\tnew OpData(1, 1, 0, 0), // GetDefaultQueue\n\t\t\tnew OpData(1, 1, 0, 0), // BuildNDRange\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSparseSampleImplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSparseSampleExplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSparseSampleDrefImplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSparseSampleDrefExplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSparseSampleProjImplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSparseSampleProjExplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSparseSampleProjDrefImplicitLod\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSparseSampleProjDrefExplicitLod\n\t\t\tnew OpData(1, 1, 2, 1), // ImageSparseFetch\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSparseGather\n\t\t\tnew OpData(1, 1, 3, 1), // ImageSparseDrefGather\n\t\t\tnew OpData(1, 1, 1, 0), // ImageSparseTexelsResident\n\t\t\tnew OpData(0, 0, 0, 0), // NoLine\n\t\t\tnew OpData(1, 1, 0, 0), // AtomicFlagTestAndSet\n\t\t\tnew OpData(0, 0, 0, 0), // AtomicFlagClear\n\t\t\tnew OpData(1, 1, 0, 0), // ImageSparseRead\n\t\t\tnew OpData(1, 1, 0, 0), // SizeOf\n\t\t\tnew OpData(1, 1, 0, 0), // TypePipeStorage\n\t\t\tnew OpData(1, 1, 0, 0), // ConstantPipeStorage\n\t\t\tnew OpData(1, 1, 0, 0), // CreatePipeFromPipeStorage\n\t\t\tnew OpData(1, 1, 0, 0), // GetKernelLocalSizeForSubgroupCount\n\t\t\tnew OpData(1, 1, 0, 0), // GetKernelMaxNumSubgroups\n\t\t\tnew OpData(1, 1, 0, 0), // TypeNamedBarrier\n\t\t\tnew OpData(1, 1, 0, 1), // NamedBarrierInitialize\n\t\t\tnew OpData(0, 0, -2, 1), // MemoryNamedBarrier\n\t\t\tnew OpData(1, 1, 0, 0), // ModuleProcessed\n\t\t};\n\t};\n}\n"
  },
  {
    "path": "AssetStudioUtility/Smolv/SmolvDecoder.cs",
    "content": "using System;\nusing System.IO;\nusing System.Text;\n\nnamespace Smolv\n{\n\tpublic static class SmolvDecoder\n\t{\n\t\tpublic static int GetDecodedBufferSize(byte[] data)\n\t\t{\n\t\t\tif (data == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(data));\n\t\t\t}\n\n\t\t\tif (!CheckSmolHeader(data))\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tint size = BitConverter.ToInt32(data, 5 * sizeof(uint));\n\t\t\treturn size;\n\t\t}\n\n\t\tpublic static int GetDecodedBufferSize(Stream stream)\n\t\t{\n\t\t\tif (stream == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(stream));\n\t\t\t}\n\t\t\tif (!stream.CanSeek)\n\t\t\t{\n\t\t\t\tthrow new ArgumentException(nameof(stream));\n\t\t\t}\n\t\t\tif (stream.Position + HeaderSize > stream.Length)\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tlong initPosition = stream.Position;\n\t\t\tstream.Position += HeaderSize - sizeof(uint);\n\t\t\tint size = stream.ReadByte() | stream.ReadByte() << 8 | stream.ReadByte() << 16 | stream.ReadByte() << 24;\n\t\t\tstream.Position = initPosition;\n\t\t\treturn size;\n\t\t}\n\n\t\tpublic static byte[] Decode(byte[] data)\n\t\t{\n\t\t\tif (data == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(data));\n\t\t\t}\n\n\t\t\tint bufferSize = GetDecodedBufferSize(data);\n\t\t\tif (bufferSize == 0)\n\t\t\t{\n\t\t\t\t// invalid SMOL-V\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tbyte[] output = new byte[bufferSize];\n\t\t\tif (Decode(data, output))\n\t\t\t{\n\t\t\t\treturn output;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\n\t\tpublic static bool Decode(byte[] data, byte[] output)\n\t\t{\n\t\t\tif (data == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(data));\n\t\t\t}\n\t\t\tif (output == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(output));\n\t\t\t}\n\n\t\t\tint bufferSize = GetDecodedBufferSize(data);\n\t\t\tif (bufferSize > output.Length)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tusing (MemoryStream outputStream = new MemoryStream(output))\n\t\t\t{\n\t\t\t\treturn Decode(data, outputStream);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool Decode(byte[] data, Stream outputStream)\n\t\t{\n\t\t\tif (data == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(data));\n\t\t\t}\n\t\t\tusing (MemoryStream inputStream = new MemoryStream(data))\n\t\t\t{\n\t\t\t\treturn Decode(inputStream, data.Length, outputStream);\n\t\t\t}\n\t\t}\n\n\t\tpublic static bool Decode(Stream inputStream, int inputSize, Stream outputStream)\n\t\t{\n\t\t\tif (inputStream == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(inputStream));\n\t\t\t}\n\t\t\tif (outputStream == null)\n\t\t\t{\n\t\t\t\tthrow new ArgumentNullException(nameof(outputStream));\n\t\t\t}\n\t\t\tif (inputStream.Length < HeaderSize)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tusing (BinaryReader input = new BinaryReader(inputStream, Encoding.UTF8, true))\n\t\t\t{\n\t\t\t\tusing (BinaryWriter output = new BinaryWriter(outputStream, Encoding.UTF8, true))\n\t\t\t\t{\n\t\t\t\t\tlong inputEndPosition = input.BaseStream.Position + inputSize;\n\t\t\t\t\tlong outputStartPosition = output.BaseStream.Position;\n\n\t\t\t\t\t// Header\n\t\t\t\t\toutput.Write(SpirVHeaderMagic);\n\t\t\t\t\tinput.BaseStream.Position += sizeof(uint);\n\t\t\t\t\tuint version = input.ReadUInt32();\n\t\t\t\t\toutput.Write(version);\n\t\t\t\t\tuint generator = input.ReadUInt32();\n\t\t\t\t\toutput.Write(generator);\n\t\t\t\t\tint bound = input.ReadInt32();\n\t\t\t\t\toutput.Write(bound);\n\t\t\t\t\tuint schema = input.ReadUInt32();\n\t\t\t\t\toutput.Write(schema);\n\t\t\t\t\tint decodedSize = input.ReadInt32();\n\n\t\t\t\t\t// Body\n\t\t\t\t\tint prevResult = 0;\n\t\t\t\t\tint prevDecorate = 0;\n\t\t\t\t\twhile (input.BaseStream.Position < inputEndPosition)\n\t\t\t\t\t{\n\t\t\t\t\t\t// read length + opcode\n\t\t\t\t\t\tif (!ReadLengthOp(input, out uint instrLen, out SpvOp op))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbool wasSwizzle = op == SpvOp.VectorShuffleCompact;\n\t\t\t\t\t\tif (wasSwizzle)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top = SpvOp.VectorShuffle;\n\t\t\t\t\t\t}\n\t\t\t\t\t\toutput.Write((instrLen << 16) | (uint)op);\n\n\t\t\t\t\t\tuint ioffs = 1;\n\t\t\t\t\t\t// read type as varint, if we have it\n\t\t\t\t\t\tif (op.OpHasType())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!ReadVarint(input, out uint value))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\toutput.Write(value);\n\t\t\t\t\t\t\tioffs++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// read result as delta+varint, if we have it\n\t\t\t\t\t\tif (op.OpHasResult())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!ReadVarint(input, out uint value))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tint zds = prevResult + ZigDecode(value);\n\t\t\t\t\t\t\toutput.Write(zds);\n\t\t\t\t\t\t\tprevResult = zds;\n\t\t\t\t\t\t\tioffs++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Decorate: IDs relative to previous decorate\n\t\t\t\t\t\tif (op == SpvOp.Decorate || op == SpvOp.MemberDecorate)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!ReadVarint(input, out uint value))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tint zds = prevDecorate + unchecked((int)value);\n\t\t\t\t\t\t\toutput.Write(zds);\n\t\t\t\t\t\t\tprevDecorate = zds;\n\t\t\t\t\t\t\tioffs++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read this many IDs, that are relative to result ID\n\t\t\t\t\t\tint relativeCount = op.OpDeltaFromResult();\n\t\t\t\t\t\tbool inverted = false;\n\t\t\t\t\t\tif (relativeCount < 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinverted = true;\n\t\t\t\t\t\t\trelativeCount = -relativeCount;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!ReadVarint(input, out uint value))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tint zd = inverted ? ZigDecode(value) : unchecked((int)value);\n\t\t\t\t\t\t\toutput.Write(prevResult - zd);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (wasSwizzle && instrLen <= 9)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tuint swizzle = input.ReadByte();\n\t\t\t\t\t\t\tif (instrLen > 5) output.Write(swizzle >> 6);\n\t\t\t\t\t\t\tif (instrLen > 6) output.Write((swizzle >> 4) & 3);\n\t\t\t\t\t\t\tif (instrLen > 7) output.Write((swizzle >> 2) & 3);\n\t\t\t\t\t\t\tif (instrLen > 8) output.Write(swizzle & 3);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (op.OpVarRest())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// read rest of words with variable encoding\n\t\t\t\t\t\t\tfor (; ioffs < instrLen; ++ioffs)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (!ReadVarint(input, out uint value))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\toutput.Write(value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// read rest of words without any encoding\n\t\t\t\t\t\t\tfor (; ioffs < instrLen; ++ioffs)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (input.BaseStream.Position + 4 > input.BaseStream.Length)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tuint val = input.ReadUInt32();\n\t\t\t\t\t\t\t\toutput.Write(val);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (output.BaseStream.Position != outputStartPosition + decodedSize)\n\t\t\t\t\t{\n\t\t\t\t\t\t// something went wrong during decoding? we should have decoded to exact output size\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate static bool CheckSmolHeader(byte[] data)\n\t\t{\n\t\t\tif (!CheckGenericHeader(data, SmolHeaderMagic))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\tprivate static bool CheckGenericHeader(byte[] data, uint expectedMagic)\n\t\t{\n\t\t\tif (data == null)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (data.Length < HeaderSize)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tuint headerMagic = BitConverter.ToUInt32(data, 0 * sizeof(uint));\n\t\t\tif (headerMagic != expectedMagic)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tuint headerVersion = BitConverter.ToUInt32(data, 1 * sizeof(uint));\n\t\t\tif (headerVersion < 0x00010000 || headerVersion > 0x00010300)\n\t\t\t{\n\t\t\t\t// only support 1.0 through 1.3\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\tprivate static bool ReadVarint(BinaryReader input, out uint value)\n\t\t{\n\t\t\tuint v = 0;\n\t\t\tint shift = 0;\n\t\t\twhile (input.BaseStream.Position < input.BaseStream.Length)\n\t\t\t{\n\t\t\t\tbyte b = input.ReadByte();\n\t\t\t\tv |= unchecked((uint)(b & 127) << shift);\n\t\t\t\tshift += 7;\n\t\t\t\tif ((b & 128) == 0)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvalue = v;\n\t\t\t// @TODO: report failures\n\t\t\treturn true;\n\t\t}\n\n\t\tprivate static bool ReadLengthOp(BinaryReader input, out uint len, out SpvOp op)\n\t\t{\n\t\t\tlen = default;\n\t\t\top = default;\n\t\t\tif (!ReadVarint(input, out uint value))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tlen = ((value >> 20) << 4) | ((value >> 4) & 0xF);\n\t\t\top = (SpvOp) (((value >> 4) & 0xFFF0) | (value & 0xF));\n\n\t\t\top = RemapOp(op);\n\t\t\tlen = DecodeLen(op, len);\n\t\t\treturn true;\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Remap most common Op codes (Load, Store, Decorate, VectorShuffle etc.) to be in &lt; 16 range, for \n\t\t/// more compact varint encoding. This basically swaps rarely used op values that are &lt; 16 with the\n\t\t/// ones that are common.\n\t\t/// </summary>\n\t\tprivate static SpvOp RemapOp(SpvOp op)\n\t\t{\n\t\t\tswitch (op)\n\t\t\t{\n\t\t\t\t// 0: 24%\n\t\t\t\tcase SpvOp.Decorate:\n\t\t\t\t\treturn SpvOp.Nop;\n\t\t\t\tcase SpvOp.Nop:\n\t\t\t\t\treturn SpvOp.Decorate;\n\n\t\t\t\t// 1: 17%\n\t\t\t\tcase SpvOp.Load:\n\t\t\t\t\treturn SpvOp.Undef;\n\t\t\t\tcase SpvOp.Undef:\n\t\t\t\t\treturn SpvOp.Load;\n\n\t\t\t\t// 2: 9%\n\t\t\t\tcase SpvOp.Store:\n\t\t\t\t\treturn SpvOp.SourceContinued;\n\t\t\t\tcase SpvOp.SourceContinued:\n\t\t\t\t\treturn SpvOp.Store;\n\n\t\t\t\t// 3: 7.2%\n\t\t\t\tcase SpvOp.AccessChain:\n\t\t\t\t\treturn SpvOp.Source;\n\t\t\t\tcase SpvOp.Source:\n\t\t\t\t\treturn SpvOp.AccessChain;\n\n\t\t\t\t// 4: 5.0%\n\t\t\t\t// Name - already small enum value - 5: 4.4%\n\t\t\t\t// MemberName - already small enum value - 6: 2.9% \n\t\t\t\tcase SpvOp.VectorShuffle:\n\t\t\t\t\treturn SpvOp.SourceExtension;\n\t\t\t\tcase SpvOp.SourceExtension:\n\t\t\t\t\treturn SpvOp.VectorShuffle;\n\n\t\t\t\t// 7: 4.0%\n\t\t\t\tcase SpvOp.MemberDecorate:\n\t\t\t\t\treturn SpvOp.String;\n\t\t\t\tcase SpvOp.String:\n\t\t\t\t\treturn SpvOp.MemberDecorate;\n\n\t\t\t\t// 8: 0.9%\n\t\t\t\tcase SpvOp.Label:\n\t\t\t\t\treturn SpvOp.Line;\n\t\t\t\tcase SpvOp.Line:\n\t\t\t\t\treturn SpvOp.Label;\n\n\t\t\t\t// 9: 3.9%\n\t\t\t\tcase SpvOp.Variable:\n\t\t\t\t\treturn (SpvOp)9;\n\t\t\t\tcase (SpvOp)9:\n\t\t\t\t\treturn SpvOp.Variable;\n\n\t\t\t\t// 10: 3.9%\n\t\t\t\tcase SpvOp.FMul:\n\t\t\t\t\treturn SpvOp.Extension;\n\t\t\t\tcase SpvOp.Extension:\n\t\t\t\t\treturn SpvOp.FMul;\n\n\t\t\t\t// 11: 2.5%\n\t\t\t\t// ExtInst - already small enum value - 12: 1.2%\n\t\t\t\t// VectorShuffleCompact - already small enum value - used for compact shuffle encoding\n\t\t\t\tcase SpvOp.FAdd:\n\t\t\t\t\treturn SpvOp.ExtInstImport;\n\t\t\t\tcase SpvOp.ExtInstImport:\n\t\t\t\t\treturn SpvOp.FAdd;\n\n\t\t\t\t// 14: 2.2%\n\t\t\t\tcase SpvOp.TypePointer:\n\t\t\t\t\treturn SpvOp.MemoryModel;\n\t\t\t\tcase SpvOp.MemoryModel:\n\t\t\t\t\treturn SpvOp.TypePointer;\n\n\t\t\t\t// 15: 1.1%\n\t\t\t\tcase SpvOp.FNegate:\n\t\t\t\t\treturn SpvOp.EntryPoint;\n\t\t\t\tcase SpvOp.EntryPoint:\n\t\t\t\t\treturn SpvOp.FNegate;\n\t\t\t}\n\t\t\treturn op;\n\t\t}\n\n\t\tprivate static uint DecodeLen(SpvOp op, uint len)\n\t\t{\n\t\t\tlen++;\n\t\t\tswitch (op)\n\t\t\t{\n\t\t\t\tcase SpvOp.VectorShuffle:\n\t\t\t\t\tlen += 4;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SpvOp.VectorShuffleCompact:\n\t\t\t\t\tlen += 4;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SpvOp.Decorate:\n\t\t\t\t\tlen += 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SpvOp.Load:\n\t\t\t\t\tlen += 3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SpvOp.AccessChain:\n\t\t\t\t\tlen += 3;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn len;\n\t\t}\n\n\t\tprivate static int DecorationExtraOps(int dec)\n\t\t{\n\t\t\t// RelaxedPrecision, Block..ColMajor\n\t\t\tif (dec == 0 || (dec >= 2 && dec <= 5))\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t// Stream..XfbStride\n\t\t\tif (dec >= 29 && dec <= 37)\n\t\t\t{\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// unknown, encode length\n\t\t\treturn -1;\n\t\t}\n\n\t\tprivate static int ZigDecode(uint u)\n\t\t{\n\t\t\treturn (u & 1) != 0 ? unchecked((int)(~(u >> 1))) : unchecked((int)(u >> 1));\n\t\t}\n\n\t\tpublic const uint SpirVHeaderMagic = 0x07230203;\n\t\t/// <summary>\n\t\t/// 'SMOL' ascii\n\t\t/// </summary>\n\t\tpublic const uint SmolHeaderMagic = 0x534D4F4C;\n\n\t\tprivate const int HeaderSize = 6 * sizeof(uint);\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/Smolv/SpvOp.cs",
    "content": "namespace Smolv\n{\n\tpublic enum SpvOp\n\t{\n\t\tNop = 0,\n\t\tUndef = 1,\n\t\tSourceContinued = 2,\n\t\tSource = 3,\n\t\tSourceExtension = 4,\n\t\tName = 5,\n\t\tMemberName = 6,\n\t\tString = 7,\n\t\tLine = 8,\n\t\tExtension = 10,\n\t\tExtInstImport = 11,\n\t\tExtInst = 12,\n\t\t/// <summary>\n\t\t/// Not in SPIR-V, added for SMOL-V!\n\t\t/// </summary>\n\t\tVectorShuffleCompact = 13,\n\t\tMemoryModel = 14,\n\t\tEntryPoint = 15,\n\t\tExecutionMode = 16,\n\t\tCapability = 17,\n\t\tTypeVoid = 19,\n\t\tTypeBool = 20,\n\t\tTypeInt = 21,\n\t\tTypeFloat = 22,\n\t\tTypeVector = 23,\n\t\tTypeMatrix = 24,\n\t\tTypeImage = 25,\n\t\tTypeSampler = 26,\n\t\tTypeSampledImage = 27,\n\t\tTypeArray = 28,\n\t\tTypeRuntimeArray = 29,\n\t\tTypeStruct = 30,\n\t\tTypeOpaque = 31,\n\t\tTypePointer = 32,\n\t\tTypeFunction = 33,\n\t\tTypeEvent = 34,\n\t\tTypeDeviceEvent = 35,\n\t\tTypeReserveId = 36,\n\t\tTypeQueue = 37,\n\t\tTypePipe = 38,\n\t\tTypeForwardPointer = 39,\n\t\tConstantTrue = 41,\n\t\tConstantFalse = 42,\n\t\tConstant = 43,\n\t\tConstantComposite = 44,\n\t\tConstantSampler = 45,\n\t\tConstantNull = 46,\n\t\tSpecConstantTrue = 48,\n\t\tSpecConstantFalse = 49,\n\t\tSpecConstant = 50,\n\t\tSpecConstantComposite = 51,\n\t\tSpecConstantOp = 52,\n\t\tFunction = 54,\n\t\tFunctionParameter = 55,\n\t\tFunctionEnd = 56,\n\t\tFunctionCall = 57,\n\t\tVariable = 59,\n\t\tImageTexelPointer = 60,\n\t\tLoad = 61,\n\t\tStore = 62,\n\t\tCopyMemory = 63,\n\t\tCopyMemorySized = 64,\n\t\tAccessChain = 65,\n\t\tInBoundsAccessChain = 66,\n\t\tPtrAccessChain = 67,\n\t\tArrayLength = 68,\n\t\tGenericPtrMemSemantics = 69,\n\t\tInBoundsPtrAccessChain = 70,\n\t\tDecorate = 71,\n\t\tMemberDecorate = 72,\n\t\tDecorationGroup = 73,\n\t\tGroupDecorate = 74,\n\t\tGroupMemberDecorate = 75,\n\t\tVectorExtractDynamic = 77,\n\t\tVectorInsertDynamic = 78,\n\t\tVectorShuffle = 79,\n\t\tCompositeConstruct = 80,\n\t\tCompositeExtract = 81,\n\t\tCompositeInsert = 82,\n\t\tCopyObject = 83,\n\t\tTranspose = 84,\n\t\tSampledImage = 86,\n\t\tImageSampleImplicitLod = 87,\n\t\tImageSampleExplicitLod = 88,\n\t\tImageSampleDrefImplicitLod = 89,\n\t\tImageSampleDrefExplicitLod = 90,\n\t\tImageSampleProjImplicitLod = 91,\n\t\tImageSampleProjExplicitLod = 92,\n\t\tImageSampleProjDrefImplicitLod = 93,\n\t\tImageSampleProjDrefExplicitLod = 94,\n\t\tImageFetch = 95,\n\t\tImageGather = 96,\n\t\tImageDrefGather = 97,\n\t\tImageRead = 98,\n\t\tImageWrite = 99,\n\t\tImage = 100,\n\t\tImageQueryFormat = 101,\n\t\tImageQueryOrder = 102,\n\t\tImageQuerySizeLod = 103,\n\t\tImageQuerySize = 104,\n\t\tImageQueryLod = 105,\n\t\tImageQueryLevels = 106,\n\t\tImageQuerySamples = 107,\n\t\tConvertFToU = 109,\n\t\tConvertFToS = 110,\n\t\tConvertSToF = 111,\n\t\tConvertUToF = 112,\n\t\tUConvert = 113,\n\t\tSConvert = 114,\n\t\tFConvert = 115,\n\t\tQuantizeToF16 = 116,\n\t\tConvertPtrToU = 117,\n\t\tSatConvertSToU = 118,\n\t\tSatConvertUToS = 119,\n\t\tConvertUToPtr = 120,\n\t\tPtrCastToGeneric = 121,\n\t\tGenericCastToPtr = 122,\n\t\tGenericCastToPtrExplicit = 123,\n\t\tBitcast = 124,\n\t\tSNegate = 126,\n\t\tFNegate = 127,\n\t\tIAdd = 128,\n\t\tFAdd = 129,\n\t\tISub = 130,\n\t\tFSub = 131,\n\t\tIMul = 132,\n\t\tFMul = 133,\n\t\tUDiv = 134,\n\t\tSDiv = 135,\n\t\tFDiv = 136,\n\t\tUMod = 137,\n\t\tSRem = 138,\n\t\tSMod = 139,\n\t\tFRem = 140,\n\t\tFMod = 141,\n\t\tVectorTimesScalar = 142,\n\t\tMatrixTimesScalar = 143,\n\t\tVectorTimesMatrix = 144,\n\t\tMatrixTimesVector = 145,\n\t\tMatrixTimesMatrix = 146,\n\t\tOuterProduct = 147,\n\t\tDot = 148,\n\t\tIAddCarry = 149,\n\t\tISubBorrow = 150,\n\t\tUMulExtended = 151,\n\t\tSMulExtended = 152,\n\t\tAny = 154,\n\t\tAll = 155,\n\t\tIsNan = 156,\n\t\tIsInf = 157,\n\t\tIsFinite = 158,\n\t\tIsNormal = 159,\n\t\tSignBitSet = 160,\n\t\tLessOrGreater = 161,\n\t\tOrdered = 162,\n\t\tUnordered = 163,\n\t\tLogicalEqual = 164,\n\t\tLogicalNotEqual = 165,\n\t\tLogicalOr = 166,\n\t\tLogicalAnd = 167,\n\t\tLogicalNot = 168,\n\t\tSelect = 169,\n\t\tIEqual = 170,\n\t\tINotEqual = 171,\n\t\tUGreaterThan = 172,\n\t\tSGreaterThan = 173,\n\t\tUGreaterThanEqual = 174,\n\t\tSGreaterThanEqual = 175,\n\t\tULessThan = 176,\n\t\tSLessThan = 177,\n\t\tULessThanEqual = 178,\n\t\tSLessThanEqual = 179,\n\t\tFOrdEqual = 180,\n\t\tFUnordEqual = 181,\n\t\tFOrdNotEqual = 182,\n\t\tFUnordNotEqual = 183,\n\t\tFOrdLessThan = 184,\n\t\tFUnordLessThan = 185,\n\t\tFOrdGreaterThan = 186,\n\t\tFUnordGreaterThan = 187,\n\t\tFOrdLessThanEqual = 188,\n\t\tFUnordLessThanEqual = 189,\n\t\tFOrdGreaterThanEqual = 190,\n\t\tFUnordGreaterThanEqual = 191,\n\t\tShiftRightLogical = 194,\n\t\tShiftRightArithmetic = 195,\n\t\tShiftLeftLogical = 196,\n\t\tBitwiseOr = 197,\n\t\tBitwiseXor = 198,\n\t\tBitwiseAnd = 199,\n\t\tNot = 200,\n\t\tBitFieldInsert = 201,\n\t\tBitFieldSExtract = 202,\n\t\tBitFieldUExtract = 203,\n\t\tBitReverse = 204,\n\t\tBitCount = 205,\n\t\tDPdx = 207,\n\t\tDPdy = 208,\n\t\tFwidth = 209,\n\t\tDPdxFine = 210,\n\t\tDPdyFine = 211,\n\t\tFwidthFine = 212,\n\t\tDPdxCoarse = 213,\n\t\tDPdyCoarse = 214,\n\t\tFwidthCoarse = 215,\n\t\tEmitVertex = 218,\n\t\tEndPrimitive = 219,\n\t\tEmitStreamVertex = 220,\n\t\tEndStreamPrimitive = 221,\n\t\tControlBarrier = 224,\n\t\tMemoryBarrier = 225,\n\t\tAtomicLoad = 227,\n\t\tAtomicStore = 228,\n\t\tAtomicExchange = 229,\n\t\tAtomicCompareExchange = 230,\n\t\tAtomicCompareExchangeWeak = 231,\n\t\tAtomicIIncrement = 232,\n\t\tAtomicIDecrement = 233,\n\t\tAtomicIAdd = 234,\n\t\tAtomicISub = 235,\n\t\tAtomicSMin = 236,\n\t\tAtomicUMin = 237,\n\t\tAtomicSMax = 238,\n\t\tAtomicUMax = 239,\n\t\tAtomicAnd = 240,\n\t\tAtomicOr = 241,\n\t\tAtomicXor = 242,\n\t\tPhi = 245,\n\t\tLoopMerge = 246,\n\t\tSelectionMerge = 247,\n\t\tLabel = 248,\n\t\tBranch = 249,\n\t\tBranchConditional = 250,\n\t\tSwitch = 251,\n\t\tKill = 252,\n\t\tReturn = 253,\n\t\tReturnValue = 254,\n\t\tUnreachable = 255,\n\t\tLifetimeStart = 256,\n\t\tLifetimeStop = 257,\n\t\tGroupAsyncCopy = 259,\n\t\tGroupWaitEvents = 260,\n\t\tGroupAll = 261,\n\t\tGroupAny = 262,\n\t\tGroupBroadcast = 263,\n\t\tGroupIAdd = 264,\n\t\tGroupFAdd = 265,\n\t\tGroupFMin = 266,\n\t\tGroupUMin = 267,\n\t\tGroupSMin = 268,\n\t\tGroupFMax = 269,\n\t\tGroupUMax = 270,\n\t\tGroupSMax = 271,\n\t\tReadPipe = 274,\n\t\tWritePipe = 275,\n\t\tReservedReadPipe = 276,\n\t\tReservedWritePipe = 277,\n\t\tReserveReadPipePackets = 278,\n\t\tReserveWritePipePackets = 279,\n\t\tCommitReadPipe = 280,\n\t\tCommitWritePipe = 281,\n\t\tIsValidReserveId = 282,\n\t\tGetNumPipePackets = 283,\n\t\tGetMaxPipePackets = 284,\n\t\tGroupReserveReadPipePackets = 285,\n\t\tGroupReserveWritePipePackets = 286,\n\t\tGroupCommitReadPipe = 287,\n\t\tGroupCommitWritePipe = 288,\n\t\tEnqueueMarker = 291,\n\t\tEnqueueKernel = 292,\n\t\tGetKernelNDrangeSubGroupCount = 293,\n\t\tGetKernelNDrangeMaxSubGroupSize = 294,\n\t\tGetKernelWorkGroupSize = 295,\n\t\tGetKernelPreferredWorkGroupSizeMultiple = 296,\n\t\tRetainEvent = 297,\n\t\tReleaseEvent = 298,\n\t\tCreateUserEvent = 299,\n\t\tIsValidEvent = 300,\n\t\tSetUserEventStatus = 301,\n\t\tCaptureEventProfilingInfo = 302,\n\t\tGetDefaultQueue = 303,\n\t\tBuildNDRange = 304,\n\t\tImageSparseSampleImplicitLod = 305,\n\t\tImageSparseSampleExplicitLod = 306,\n\t\tImageSparseSampleDrefImplicitLod = 307,\n\t\tImageSparseSampleDrefExplicitLod = 308,\n\t\tImageSparseSampleProjImplicitLod = 309,\n\t\tImageSparseSampleProjExplicitLod = 310,\n\t\tImageSparseSampleProjDrefImplicitLod = 311,\n\t\tImageSparseSampleProjDrefExplicitLod = 312,\n\t\tImageSparseFetch = 313,\n\t\tImageSparseGather = 314,\n\t\tImageSparseDrefGather = 315,\n\t\tImageSparseTexelsResident = 316,\n\t\tNoLine = 317,\n\t\tAtomicFlagTestAndSet = 318,\n\t\tAtomicFlagClear = 319,\n\t\tImageSparseRead = 320,\n\t\tSizeOf = 321,\n\t\tTypePipeStorage = 322,\n\t\tConstantPipeStorage = 323,\n\t\tCreatePipeFromPipeStorage = 324,\n\t\tGetKernelLocalSizeForSubgroupCount = 325,\n\t\tGetKernelMaxNumSubgroups = 326,\n\t\tTypeNamedBarrier = 327,\n\t\tNamedBarrierInitialize = 328,\n\t\tMemoryNamedBarrier = 329,\n\t\tModuleProcessed = 330,\n\n\t\tKnownOpsCount,\n\t}\n\n\tpublic static class SpvOpExtensions\n\t{\n\t\tpublic static bool OpHasResult(this SpvOp _this)\n\t\t{\n\t\t\tif (_this < 0 || _this >= SpvOp.KnownOpsCount)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn OpData.SpirvOpData[(int)_this].hasResult != 0;\n\t\t}\n\n\t\tpublic static bool OpHasType(this SpvOp _this)\n\t\t{\n\t\t\tif (_this < 0 || _this >= SpvOp.KnownOpsCount)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn OpData.SpirvOpData[(int)_this].hasType != 0;\n\t\t}\n\n\t\tpublic static int OpDeltaFromResult(this SpvOp _this)\n\t\t{\n\t\t\tif (_this < 0 || _this >= SpvOp.KnownOpsCount)\n\t\t\t{\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn OpData.SpirvOpData[(int)_this].deltaFromResult;\n\t\t}\n\n\t\tpublic static bool OpVarRest(this SpvOp _this)\n\t\t{\n\t\t\tif (_this < 0 || _this >= SpvOp.KnownOpsCount)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn OpData.SpirvOpData[(int)_this].varrest != 0;\n\t\t}\n\n\t\tpublic static bool OpDebugInfo(this SpvOp _this)\n\t\t{\n\t\t\treturn\n\t\t\t\t_this == SpvOp.SourceContinued ||\n\t\t\t\t_this == SpvOp.Source ||\n\t\t\t\t_this == SpvOp.SourceExtension ||\n\t\t\t\t_this == SpvOp.Name ||\n\t\t\t\t_this == SpvOp.MemberName ||\n\t\t\t\t_this == SpvOp.String ||\n\t\t\t\t_this == SpvOp.Line ||\n\t\t\t\t_this == SpvOp.NoLine ||\n\t\t\t\t_this == SpvOp.ModuleProcessed;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "AssetStudioUtility/SpirVShaderConverter.cs",
    "content": "﻿using Smolv;\nusing SpirV;\nusing System;\nusing System.IO;\nusing System.Text;\n\nnamespace AssetStudio\n{\n    public static class SpirVShaderConverter\n    {\n        public static string Convert(byte[] m_ProgramCode)\n        {\n            var sb = new StringBuilder();\n            using (var ms = new MemoryStream(m_ProgramCode))\n            {\n                using (var reader = new BinaryReader(ms))\n                {\n                    int requirements = reader.ReadInt32();\n                    int minOffset = m_ProgramCode.Length;\n                    int snippetCount = 5;\n                    /*if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up\n                    {\n                        snippetCount = 6;\n                    }*/\n                    for (int i = 0; i < snippetCount; i++)\n                    {\n                        if (reader.BaseStream.Position >= minOffset)\n                        {\n                            break;\n                        }\n\n                        int offset = reader.ReadInt32();\n                        int size = reader.ReadInt32();\n                        if (size > 0)\n                        {\n                            if (offset < minOffset)\n                            {\n                                minOffset = offset;\n                            }\n                            var pos = ms.Position;\n                            sb.Append(ExportSnippet(ms, offset, size));\n                            ms.Position = pos;\n                        }\n                    }\n                }\n            }\n            return sb.ToString();\n        }\n\n        private static string ExportSnippet(Stream stream, int offset, int size)\n        {\n            stream.Position = offset;\n            int decodedSize = SmolvDecoder.GetDecodedBufferSize(stream);\n            if (decodedSize == 0)\n            {\n                throw new Exception(\"Invalid SMOL-V shader header\");\n            }\n            using (var decodedStream = new MemoryStream(new byte[decodedSize]))\n            {\n                if (SmolvDecoder.Decode(stream, size, decodedStream))\n                {\n                    decodedStream.Position = 0;\n                    var module = Module.ReadFrom(decodedStream);\n                    var disassembler = new Disassembler();\n                    return disassembler.Disassemble(module, DisassemblyOptions.Default).Replace(\"\\r\\n\", \"\\n\");\n                }\n                else\n                {\n                    throw new Exception(\"Unable to decode SMOL-V shader\");\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/SpriteHelper.cs",
    "content": "﻿using SixLabors.ImageSharp;\nusing SixLabors.ImageSharp.Drawing;\nusing SixLabors.ImageSharp.Drawing.Processing;\nusing SixLabors.ImageSharp.PixelFormats;\nusing SixLabors.ImageSharp.Processing;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Numerics;\n\nnamespace AssetStudio\n{\n    public static class SpriteHelper\n    {\n        public static Image<Bgra32> GetImage(this Sprite m_Sprite)\n        {\n            if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))\n            {\n                if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out var m_Texture2D))\n                {\n                    return CutImage(m_Sprite, m_Texture2D, spriteAtlasData.textureRect, spriteAtlasData.textureRectOffset, spriteAtlasData.downscaleMultiplier, spriteAtlasData.settingsRaw);\n                }\n            }\n            else\n            {\n                if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D))\n                {\n                    return CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);\n                }\n            }\n            return null;\n        }\n\n        private static Image<Bgra32> CutImage(Sprite m_Sprite, Texture2D m_Texture2D, Rectf textureRect, Vector2 textureRectOffset, float downscaleMultiplier, SpriteSettings settingsRaw)\n        {\n            var originalImage = m_Texture2D.ConvertToImage(false);\n            if (originalImage != null)\n            {\n                using (originalImage)\n                {\n                    if (downscaleMultiplier > 0f && downscaleMultiplier != 1f)\n                    {\n                        var width = (int)(m_Texture2D.m_Width / downscaleMultiplier);\n                        var height = (int)(m_Texture2D.m_Height / downscaleMultiplier);\n                        originalImage.Mutate(x => x.Resize(width, height));\n                    }\n                    var rectX = (int)Math.Floor(textureRect.x);\n                    var rectY = (int)Math.Floor(textureRect.y);\n                    var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);\n                    var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);\n                    rectRight = Math.Min(rectRight, originalImage.Width);\n                    rectBottom = Math.Min(rectBottom, originalImage.Height);\n                    var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);\n                    var spriteImage = originalImage.Clone(x => x.Crop(rect));\n                    if (settingsRaw.packed == 1)\n                    {\n                        //RotateAndFlip\n                        switch (settingsRaw.packingRotation)\n                        {\n                            case SpritePackingRotation.FlipHorizontal:\n                                spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal));\n                                break;\n                            case SpritePackingRotation.FlipVertical:\n                                spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));\n                                break;\n                            case SpritePackingRotation.Rotate180:\n                                spriteImage.Mutate(x => x.Rotate(180));\n                                break;\n                            case SpritePackingRotation.Rotate90:\n                                spriteImage.Mutate(x => x.Rotate(270));\n                                break;\n                        }\n                    }\n\n                    //Tight\n                    if (settingsRaw.packingMode == SpritePackingMode.Tight)\n                    {\n                        try\n                        {\n                            var triangles = GetTriangles(m_Sprite.m_RD);\n                            var polygons = triangles.Select(x => new Polygon(new LinearLineSegment(x.Select(y => new PointF(y.X, y.Y)).ToArray()))).ToArray();\n                            IPathCollection path = new PathCollection(polygons);\n                            var matrix = Matrix3x2.CreateScale(m_Sprite.m_PixelsToUnits);\n                            matrix *= Matrix3x2.CreateTranslation(m_Sprite.m_Rect.width * m_Sprite.m_Pivot.X - textureRectOffset.X, m_Sprite.m_Rect.height * m_Sprite.m_Pivot.Y - textureRectOffset.Y);\n                            path = path.Transform(matrix);\n                            var graphicsOptions = new GraphicsOptions\n                            {\n                                Antialias = false,\n                                AlphaCompositionMode = PixelAlphaCompositionMode.DestOut\n                            };\n                            var options = new DrawingOptions\n                            {\n                                GraphicsOptions = graphicsOptions\n                            };\n                            using (var mask = new Image<Bgra32>(rect.Width, rect.Height, SixLabors.ImageSharp.Color.Black))\n                            {\n                                mask.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, path));\n                                var bursh = new ImageBrush(mask);\n                                spriteImage.Mutate(x => x.Fill(graphicsOptions, bursh));\n                                spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));\n                                return spriteImage;\n                            }\n                        }\n                        catch\n                        {\n                            // ignored\n                        }\n                    }\n\n                    //Rectangle\n                    spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));\n                    return spriteImage;\n                }\n            }\n\n            return null;\n        }\n\n        private static Vector2[][] GetTriangles(SpriteRenderData m_RD)\n        {\n            if (m_RD.vertices != null) //5.6 down\n            {\n                var vertices = m_RD.vertices.Select(x => (Vector2)x.pos).ToArray();\n                var triangleCount = m_RD.indices.Length / 3;\n                var triangles = new Vector2[triangleCount][];\n                for (int i = 0; i < triangleCount; i++)\n                {\n                    var first = m_RD.indices[i * 3];\n                    var second = m_RD.indices[i * 3 + 1];\n                    var third = m_RD.indices[i * 3 + 2];\n                    var triangle = new[] { vertices[first], vertices[second], vertices[third] };\n                    triangles[i] = triangle;\n                }\n                return triangles;\n            }\n            else //5.6 and up\n            {\n                var triangles = new List<Vector2[]>();\n                var m_VertexData = m_RD.m_VertexData;\n                var m_Channel = m_VertexData.m_Channels[0]; //kShaderChannelVertex\n                var m_Stream = m_VertexData.m_Streams[m_Channel.stream];\n                using (var vertexReader = new BinaryReader(new MemoryStream(m_VertexData.m_DataSize)))\n                {\n                    using (var indexReader = new BinaryReader(new MemoryStream(m_RD.m_IndexBuffer)))\n                    {\n                        foreach (var subMesh in m_RD.m_SubMeshes)\n                        {\n                            vertexReader.BaseStream.Position = m_Stream.offset + subMesh.firstVertex * m_Stream.stride + m_Channel.offset;\n\n                            var vertices = new Vector2[subMesh.vertexCount];\n                            for (int v = 0; v < subMesh.vertexCount; v++)\n                            {\n                                vertices[v] = vertexReader.ReadVector3();\n                                vertexReader.BaseStream.Position += m_Stream.stride - 12;\n                            }\n\n                            indexReader.BaseStream.Position = subMesh.firstByte;\n\n                            var triangleCount = subMesh.indexCount / 3u;\n                            for (int i = 0; i < triangleCount; i++)\n                            {\n                                var first = indexReader.ReadUInt16() - subMesh.firstVertex;\n                                var second = indexReader.ReadUInt16() - subMesh.firstVertex;\n                                var third = indexReader.ReadUInt16() - subMesh.firstVertex;\n                                var triangle = new[] { vertices[first], vertices[second], vertices[third] };\n                                triangles.Add(triangle);\n                            }\n                        }\n                    }\n                }\n                return triangles.ToArray();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Texture2DConverter.cs",
    "content": "﻿using System;\nusing System.Runtime.CompilerServices;\nusing Texture2DDecoder;\n\nnamespace AssetStudio\n{\n    public class Texture2DConverter\n    {\n        private ResourceReader reader;\n        private int m_Width;\n        private int m_Height;\n        private TextureFormat m_TextureFormat;\n        private int[] version;\n        private BuildTarget platform;\n        private int outPutSize;\n\n        public Texture2DConverter(Texture2D m_Texture2D)\n        {\n            reader = m_Texture2D.image_data;\n            m_Width = m_Texture2D.m_Width;\n            m_Height = m_Texture2D.m_Height;\n            m_TextureFormat = m_Texture2D.m_TextureFormat;\n            version = m_Texture2D.version;\n            platform = m_Texture2D.platform;\n            outPutSize = m_Width * m_Height * 4;\n        }\n\n        public bool DecodeTexture2D(byte[] bytes)\n        {\n            if (reader.Size == 0 || m_Width == 0 || m_Height == 0)\n            {\n                return false;\n            }\n            var flag = false;\n            var buff = BigArrayPool<byte>.Shared.Rent(reader.Size);\n            reader.GetData(buff);\n            switch (m_TextureFormat)\n            {\n                case TextureFormat.Alpha8: //test pass\n                    flag = DecodeAlpha8(buff, bytes);\n                    break;\n                case TextureFormat.ARGB4444: //test pass\n                    SwapBytesForXbox(buff);\n                    flag = DecodeARGB4444(buff, bytes);\n                    break;\n                case TextureFormat.RGB24: //test pass\n                    flag = DecodeRGB24(buff, bytes);\n                    break;\n                case TextureFormat.RGBA32: //test pass\n                    flag = DecodeRGBA32(buff, bytes);\n                    break;\n                case TextureFormat.ARGB32: //test pass\n                    flag = DecodeARGB32(buff, bytes);\n                    break;\n                case TextureFormat.RGB565: //test pass\n                    SwapBytesForXbox(buff);\n                    flag = DecodeRGB565(buff, bytes);\n                    break;\n                case TextureFormat.R16: //test pass\n                    flag = DecodeR16(buff, bytes);\n                    break;\n                case TextureFormat.DXT1: //test pass\n                    SwapBytesForXbox(buff);\n                    flag = DecodeDXT1(buff, bytes);\n                    break;\n                case TextureFormat.DXT3:\n                    break;\n                case TextureFormat.DXT5: //test pass\n                    SwapBytesForXbox(buff);\n                    flag = DecodeDXT5(buff, bytes);\n                    break;\n                case TextureFormat.RGBA4444: //test pass\n                    flag = DecodeRGBA4444(buff, bytes);\n                    break;\n                case TextureFormat.BGRA32: //test pass\n                    flag = DecodeBGRA32(buff, bytes);\n                    break;\n                case TextureFormat.RHalf:\n                    flag = DecodeRHalf(buff, bytes);\n                    break;\n                case TextureFormat.RGHalf:\n                    flag = DecodeRGHalf(buff, bytes);\n                    break;\n                case TextureFormat.RGBAHalf: //test pass\n                    flag = DecodeRGBAHalf(buff, bytes);\n                    break;\n                case TextureFormat.RFloat:\n                    flag = DecodeRFloat(buff, bytes);\n                    break;\n                case TextureFormat.RGFloat:\n                    flag = DecodeRGFloat(buff, bytes);\n                    break;\n                case TextureFormat.RGBAFloat:\n                    flag = DecodeRGBAFloat(buff, bytes);\n                    break;\n                case TextureFormat.YUY2: //test pass\n                    flag = DecodeYUY2(buff, bytes);\n                    break;\n                case TextureFormat.RGB9e5Float: //test pass\n                    flag = DecodeRGB9e5Float(buff, bytes);\n                    break;\n                case TextureFormat.BC6H: //test pass\n                    flag = DecodeBC6H(buff, bytes);\n                    break;\n                case TextureFormat.BC7: //test pass\n                    flag = DecodeBC7(buff, bytes);\n                    break;\n                case TextureFormat.BC4: //test pass\n                    flag = DecodeBC4(buff, bytes);\n                    break;\n                case TextureFormat.BC5: //test pass\n                    flag = DecodeBC5(buff, bytes);\n                    break;\n                case TextureFormat.DXT1Crunched: //test pass\n                    flag = DecodeDXT1Crunched(buff, bytes);\n                    break;\n                case TextureFormat.DXT5Crunched: //test pass\n                    flag = DecodeDXT5Crunched(buff, bytes);\n                    break;\n                case TextureFormat.PVRTC_RGB2: //test pass\n                case TextureFormat.PVRTC_RGBA2: //test pass\n                    flag = DecodePVRTC(buff, bytes, true);\n                    break;\n                case TextureFormat.PVRTC_RGB4: //test pass\n                case TextureFormat.PVRTC_RGBA4: //test pass\n                    flag = DecodePVRTC(buff, bytes, false);\n                    break;\n                case TextureFormat.ETC_RGB4: //test pass\n                case TextureFormat.ETC_RGB4_3DS:\n                    flag = DecodeETC1(buff, bytes);\n                    break;\n                case TextureFormat.ATC_RGB4: //test pass\n                    flag = DecodeATCRGB4(buff, bytes);\n                    break;\n                case TextureFormat.ATC_RGBA8: //test pass\n                    flag = DecodeATCRGBA8(buff, bytes);\n                    break;\n                case TextureFormat.EAC_R: //test pass\n                    flag = DecodeEACR(buff, bytes);\n                    break;\n                case TextureFormat.EAC_R_SIGNED:\n                    flag = DecodeEACRSigned(buff, bytes);\n                    break;\n                case TextureFormat.EAC_RG: //test pass\n                    flag = DecodeEACRG(buff, bytes);\n                    break;\n                case TextureFormat.EAC_RG_SIGNED:\n                    flag = DecodeEACRGSigned(buff, bytes);\n                    break;\n                case TextureFormat.ETC2_RGB: //test pass\n                    flag = DecodeETC2(buff, bytes);\n                    break;\n                case TextureFormat.ETC2_RGBA1: //test pass\n                    flag = DecodeETC2A1(buff, bytes);\n                    break;\n                case TextureFormat.ETC2_RGBA8: //test pass\n                case TextureFormat.ETC_RGBA8_3DS:\n                    flag = DecodeETC2A8(buff, bytes);\n                    break;\n                case TextureFormat.ASTC_RGB_4x4: //test pass\n                case TextureFormat.ASTC_RGBA_4x4: //test pass\n                case TextureFormat.ASTC_HDR_4x4: //test pass\n                    flag = DecodeASTC(buff, bytes, 4);\n                    break;\n                case TextureFormat.ASTC_RGB_5x5: //test pass\n                case TextureFormat.ASTC_RGBA_5x5: //test pass\n                case TextureFormat.ASTC_HDR_5x5: //test pass\n                    flag = DecodeASTC(buff, bytes, 5);\n                    break;\n                case TextureFormat.ASTC_RGB_6x6: //test pass\n                case TextureFormat.ASTC_RGBA_6x6: //test pass\n                case TextureFormat.ASTC_HDR_6x6: //test pass\n                    flag = DecodeASTC(buff, bytes, 6);\n                    break;\n                case TextureFormat.ASTC_RGB_8x8: //test pass\n                case TextureFormat.ASTC_RGBA_8x8: //test pass\n                case TextureFormat.ASTC_HDR_8x8: //test pass\n                    flag = DecodeASTC(buff, bytes, 8);\n                    break;\n                case TextureFormat.ASTC_RGB_10x10: //test pass\n                case TextureFormat.ASTC_RGBA_10x10: //test pass\n                case TextureFormat.ASTC_HDR_10x10: //test pass\n                    flag = DecodeASTC(buff, bytes, 10);\n                    break;\n                case TextureFormat.ASTC_RGB_12x12: //test pass\n                case TextureFormat.ASTC_RGBA_12x12: //test pass\n                case TextureFormat.ASTC_HDR_12x12: //test pass\n                    flag = DecodeASTC(buff, bytes, 12);\n                    break;\n                case TextureFormat.RG16: //test pass\n                    flag = DecodeRG16(buff, bytes);\n                    break;\n                case TextureFormat.R8: //test pass\n                    flag = DecodeR8(buff, bytes);\n                    break;\n                case TextureFormat.ETC_RGB4Crunched: //test pass\n                    flag = DecodeETC1Crunched(buff, bytes);\n                    break;\n                case TextureFormat.ETC2_RGBA8Crunched: //test pass\n                    flag = DecodeETC2A8Crunched(buff, bytes);\n                    break;\n                case TextureFormat.RG32: //test pass\n                    flag = DecodeRG32(buff, bytes);\n                    break;\n                case TextureFormat.RGB48: //test pass\n                    flag = DecodeRGB48(buff, bytes);\n                    break;\n                case TextureFormat.RGBA64: //test pass\n                    flag = DecodeRGBA64(buff, bytes);\n                    break;\n            }\n            BigArrayPool<byte>.Shared.Return(buff);\n            return flag;\n        }\n\n        private void SwapBytesForXbox(byte[] image_data)\n        {\n            if (platform == BuildTarget.XBOX360)\n            {\n                for (var i = 0; i < reader.Size / 2; i++)\n                {\n                    var b = image_data[i * 2];\n                    image_data[i * 2] = image_data[i * 2 + 1];\n                    image_data[i * 2 + 1] = b;\n                }\n            }\n        }\n\n        private bool DecodeAlpha8(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            var span = new Span<byte>(buff);\n            span.Fill(0xFF);\n            for (var i = 0; i < size; i++)\n            {\n                buff[i * 4 + 3] = image_data[i];\n            }\n            return true;\n        }\n\n        private bool DecodeARGB4444(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            var pixelNew = new byte[4];\n            for (var i = 0; i < size; i++)\n            {\n                var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);\n                pixelNew[0] = (byte)(pixelOldShort & 0x000f);\n                pixelNew[1] = (byte)((pixelOldShort & 0x00f0) >> 4);\n                pixelNew[2] = (byte)((pixelOldShort & 0x0f00) >> 8);\n                pixelNew[3] = (byte)((pixelOldShort & 0xf000) >> 12);\n                for (var j = 0; j < 4; j++)\n                    pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);\n                pixelNew.CopyTo(buff, i * 4);\n            }\n            return true;\n        }\n\n        private bool DecodeRGB24(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            for (var i = 0; i < size; i++)\n            {\n                buff[i * 4] = image_data[i * 3 + 2];\n                buff[i * 4 + 1] = image_data[i * 3 + 1];\n                buff[i * 4 + 2] = image_data[i * 3 + 0];\n                buff[i * 4 + 3] = 255;\n            }\n            return true;\n        }\n\n        private bool DecodeRGBA32(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = image_data[i + 2];\n                buff[i + 1] = image_data[i + 1];\n                buff[i + 2] = image_data[i + 0];\n                buff[i + 3] = image_data[i + 3];\n            }\n            return true;\n        }\n\n        private bool DecodeARGB32(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = image_data[i + 3];\n                buff[i + 1] = image_data[i + 2];\n                buff[i + 2] = image_data[i + 1];\n                buff[i + 3] = image_data[i + 0];\n            }\n            return true;\n        }\n\n        private bool DecodeRGB565(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            for (var i = 0; i < size; i++)\n            {\n                var p = BitConverter.ToUInt16(image_data, i * 2);\n                buff[i * 4] = (byte)((p << 3) | (p >> 2 & 7));\n                buff[i * 4 + 1] = (byte)((p >> 3 & 0xfc) | (p >> 9 & 3));\n                buff[i * 4 + 2] = (byte)((p >> 8 & 0xf8) | (p >> 13));\n                buff[i * 4 + 3] = 255;\n            }\n            return true;\n        }\n\n        private bool DecodeR16(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            for (var i = 0; i < size; i++)\n            {\n                buff[i * 4] = 0; //b\n                buff[i * 4 + 1] = 0; //g\n                buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r\n                buff[i * 4 + 3] = 255; //a\n            }\n            return true;\n        }\n\n        private bool DecodeDXT1(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeDXT1(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeDXT5(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeDXT5(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeRGBA4444(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            var pixelNew = new byte[4];\n            for (var i = 0; i < size; i++)\n            {\n                var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);\n                pixelNew[0] = (byte)((pixelOldShort & 0x00f0) >> 4);\n                pixelNew[1] = (byte)((pixelOldShort & 0x0f00) >> 8);\n                pixelNew[2] = (byte)((pixelOldShort & 0xf000) >> 12);\n                pixelNew[3] = (byte)(pixelOldShort & 0x000f);\n                for (var j = 0; j < 4; j++)\n                    pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);\n                pixelNew.CopyTo(buff, i * 4);\n            }\n            return true;\n        }\n\n        private bool DecodeBGRA32(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = image_data[i];\n                buff[i + 1] = image_data[i + 1];\n                buff[i + 2] = image_data[i + 2];\n                buff[i + 3] = image_data[i + 3];\n            }\n            return true;\n        }\n\n        private bool DecodeRHalf(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = 0;\n                buff[i + 1] = 0;\n                buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i / 2) * 255f);\n                buff[i + 3] = 255;\n            }\n            return true;\n        }\n\n        private bool DecodeRGHalf(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = 0;\n                buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i + 2) * 255f);\n                buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i) * 255f);\n                buff[i + 3] = 255;\n            }\n            return true;\n        }\n\n        private bool DecodeRGBAHalf(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f);\n                buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f);\n                buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i * 2) * 255f);\n                buff[i + 3] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 6) * 255f);\n            }\n            return true;\n        }\n\n        private bool DecodeRFloat(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = 0;\n                buff[i + 1] = 0;\n                buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i) * 255f);\n                buff[i + 3] = 255;\n            }\n            return true;\n        }\n\n        private bool DecodeRGFloat(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = 0;\n                buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2 + 4) * 255f);\n                buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2) * 255f);\n                buff[i + 3] = 255;\n            }\n            return true;\n        }\n\n        private bool DecodeRGBAFloat(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 8) * 255f);\n                buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 4) * 255f);\n                buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4) * 255f);\n                buff[i + 3] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 12) * 255f);\n            }\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static byte ClampByte(int x)\n        {\n            return (byte)(byte.MaxValue < x ? byte.MaxValue : (x > byte.MinValue ? x : byte.MinValue));\n        }\n\n        private bool DecodeYUY2(byte[] image_data, byte[] buff)\n        {\n            int p = 0;\n            int o = 0;\n            int halfWidth = m_Width / 2;\n            for (int j = 0; j < m_Height; j++)\n            {\n                for (int i = 0; i < halfWidth; ++i)\n                {\n                    int y0 = image_data[p++];\n                    int u0 = image_data[p++];\n                    int y1 = image_data[p++];\n                    int v0 = image_data[p++];\n                    int c = y0 - 16;\n                    int d = u0 - 128;\n                    int e = v0 - 128;\n                    buff[o++] = ClampByte((298 * c + 516 * d + 128) >> 8);            // b\n                    buff[o++] = ClampByte((298 * c - 100 * d - 208 * e + 128) >> 8);  // g\n                    buff[o++] = ClampByte((298 * c + 409 * e + 128) >> 8);            // r\n                    buff[o++] = 255;\n                    c = y1 - 16;\n                    buff[o++] = ClampByte((298 * c + 516 * d + 128) >> 8);            // b\n                    buff[o++] = ClampByte((298 * c - 100 * d - 208 * e + 128) >> 8);  // g\n                    buff[o++] = ClampByte((298 * c + 409 * e + 128) >> 8);            // r\n                    buff[o++] = 255;\n                }\n            }\n            return true;\n        }\n\n        private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                var n = BitConverter.ToInt32(image_data, i);\n                var scale = n >> 27 & 0x1f;\n                var scalef = Math.Pow(2, scale - 24);\n                var b = n >> 18 & 0x1ff;\n                var g = n >> 9 & 0x1ff;\n                var r = n & 0x1ff;\n                buff[i] = (byte)Math.Round(b * scalef * 255f);\n                buff[i + 1] = (byte)Math.Round(g * scalef * 255f);\n                buff[i + 2] = (byte)Math.Round(r * scalef * 255f);\n                buff[i + 3] = 255;\n            }\n            return true;\n        }\n\n        private bool DecodeBC4(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeBC4(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeBC5(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeBC5(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeBC6H(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeBC6(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeBC7(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeBC7(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeDXT1Crunched(byte[] image_data, byte[] buff)\n        {\n            if (UnpackCrunch(image_data, out var result))\n            {\n                if (DecodeDXT1(result, buff))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private bool DecodeDXT5Crunched(byte[] image_data, byte[] buff)\n        {\n            if (UnpackCrunch(image_data, out var result))\n            {\n                if (DecodeDXT5(result, buff))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private bool DecodePVRTC(byte[] image_data, byte[] buff, bool is2bpp)\n        {\n            return TextureDecoder.DecodePVRTC(image_data, m_Width, m_Height, buff, is2bpp);\n        }\n\n        private bool DecodeETC1(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeETC1(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeATCRGB4(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeATCRGB4(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeATCRGBA8(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeATCRGBA8(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeEACR(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeEACR(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeEACRSigned(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeEACRSigned(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeEACRG(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeEACRG(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeEACRGSigned(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeEACRGSigned(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeETC2(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeETC2(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeETC2A1(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeETC2A1(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeETC2A8(byte[] image_data, byte[] buff)\n        {\n            return TextureDecoder.DecodeETC2A8(image_data, m_Width, m_Height, buff);\n        }\n\n        private bool DecodeASTC(byte[] image_data, byte[] buff, int blocksize)\n        {\n            return TextureDecoder.DecodeASTC(image_data, m_Width, m_Height, blocksize, blocksize, buff);\n        }\n\n        private bool DecodeRG16(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            for (var i = 0; i < size; i++)\n            {\n                buff[i * 4] = 0; //B\n                buff[i * 4 + 1] = image_data[i * 2 + 1];//G\n                buff[i * 4 + 2] = image_data[i * 2];//R\n                buff[i * 4 + 3] = 255;//A\n            }\n            return true;\n        }\n\n        private bool DecodeR8(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            for (var i = 0; i < size; i++)\n            {\n                buff[i * 4] = 0; //B\n                buff[i * 4 + 1] = 0; //G\n                buff[i * 4 + 2] = image_data[i];//R\n                buff[i * 4 + 3] = 255;//A\n            }\n            return true;\n        }\n\n        private bool DecodeETC1Crunched(byte[] image_data, byte[] buff)\n        {\n            if (UnpackCrunch(image_data, out var result))\n            {\n                if (DecodeETC1(result, buff))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private bool DecodeETC2A8Crunched(byte[] image_data, byte[] buff)\n        {\n            if (UnpackCrunch(image_data, out var result))\n            {\n                if (DecodeETC2A8(result, buff))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte DownScaleFrom16BitTo8Bit(ushort component)\n        {\n            return (byte)(((component * 255) + 32895) >> 16);\n        }\n\n        private bool DecodeRG32(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = 0;                                                                          //b\n                buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i + 2));     //g\n                buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i));         //r\n                buff[i + 3] = byte.MaxValue;                                                          //a\n            }\n            return true;\n        }\n\n        private bool DecodeRGB48(byte[] image_data, byte[] buff)\n        {\n            var size = m_Width * m_Height;\n            for (var i = 0; i < size; i++)\n            {\n                buff[i * 4] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 4));     //b\n                buff[i * 4 + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 2)); //g\n                buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6));     //r\n                buff[i * 4 + 3] = byte.MaxValue;                                                          //a\n            }\n            return true;\n        }\n\n        private bool DecodeRGBA64(byte[] image_data, byte[] buff)\n        {\n            for (var i = 0; i < outPutSize; i += 4)\n            {\n                buff[i] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 4));     //b\n                buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 2)); //g\n                buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2));     //r\n                buff[i + 3] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 6)); //a\n            }\n            return true;\n        }\n\n        private bool UnpackCrunch(byte[] image_data, out byte[] result)\n        {\n            if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up\n                || m_TextureFormat == TextureFormat.ETC_RGB4Crunched\n                || m_TextureFormat == TextureFormat.ETC2_RGBA8Crunched)\n            {\n                result = TextureDecoder.UnpackUnityCrunch(image_data);\n            }\n            else\n            {\n                result = TextureDecoder.UnpackCrunch(image_data);\n            }\n            if (result != null)\n            {\n                return true;\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Texture2DExtensions.cs",
    "content": "﻿using SixLabors.ImageSharp;\nusing SixLabors.ImageSharp.PixelFormats;\nusing SixLabors.ImageSharp.Processing;\nusing System.IO;\n\nnamespace AssetStudio\n{\n    public static class Texture2DExtensions\n    {\n        public static Image<Bgra32> ConvertToImage(this Texture2D m_Texture2D, bool flip)\n        {\n            var converter = new Texture2DConverter(m_Texture2D);\n            var buff = BigArrayPool<byte>.Shared.Rent(m_Texture2D.m_Width * m_Texture2D.m_Height * 4);\n            try\n            {\n                if (converter.DecodeTexture2D(buff))\n                {\n                    var image = Image.LoadPixelData<Bgra32>(buff, m_Texture2D.m_Width, m_Texture2D.m_Height);\n                    if (flip)\n                    {\n                        image.Mutate(x => x.Flip(FlipMode.Vertical));\n                    }\n                    return image;\n                }\n                return null;\n            }\n            finally\n            {\n                BigArrayPool<byte>.Shared.Return(buff);\n            }\n        }\n\n        public static MemoryStream ConvertToStream(this Texture2D m_Texture2D, ImageFormat imageFormat, bool flip)\n        {\n            var image = ConvertToImage(m_Texture2D, flip);\n            if (image != null)\n            {\n                using (image)\n                {\n                    return image.ConvertToStream(imageFormat);\n                }\n            }\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/TypeDefinitionConverter.cs",
    "content": "﻿using Mono.Cecil;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Unity.CecilTools;\nusing Unity.SerializationLogic;\n\nnamespace AssetStudio\n{\n    public class TypeDefinitionConverter\n    {\n        private readonly TypeDefinition TypeDef;\n        private readonly TypeResolver TypeResolver;\n        private readonly SerializedTypeHelper Helper;\n        private readonly int Indent;\n\n        public TypeDefinitionConverter(TypeDefinition typeDef, SerializedTypeHelper helper, int indent)\n        {\n            TypeDef = typeDef;\n            TypeResolver = new TypeResolver(null);\n            Helper = helper;\n            Indent = indent;\n        }\n\n        public List<TypeTreeNode> ConvertToTypeTreeNodes()\n        {\n            var nodes = new List<TypeTreeNode>();\n\n            var baseTypes = new Stack<TypeReference>();\n            var lastBaseType = TypeDef.BaseType;\n            while (!UnitySerializationLogic.IsNonSerialized(lastBaseType))\n            {\n                var genericInstanceType = lastBaseType as GenericInstanceType;\n                if (genericInstanceType != null)\n                {\n                    TypeResolver.Add(genericInstanceType);\n                }\n                baseTypes.Push(lastBaseType);\n                lastBaseType = lastBaseType.Resolve().BaseType;\n            }\n            while (baseTypes.Count > 0)\n            {\n                var typeReference = baseTypes.Pop();\n                var typeDefinition = typeReference.Resolve();\n                foreach (var fieldDefinition in typeDefinition.Fields.Where(WillUnitySerialize))\n                {\n                    if (!IsHiddenByParentClass(baseTypes, fieldDefinition, TypeDef))\n                    {\n                        nodes.AddRange(ProcessingFieldRef(ResolveGenericFieldReference(fieldDefinition)));\n                    }\n                }\n\n                var genericInstanceType = typeReference as GenericInstanceType;\n                if (genericInstanceType != null)\n                {\n                    TypeResolver.Remove(genericInstanceType);\n                }\n            }\n            foreach (var field in FilteredFields())\n            {\n                nodes.AddRange(ProcessingFieldRef(field));\n            }\n\n            return nodes;\n        }\n\n        private bool WillUnitySerialize(FieldDefinition fieldDefinition)\n        {\n            try\n            {\n                var resolvedFieldType = TypeResolver.Resolve(fieldDefinition.FieldType);\n                if (UnitySerializationLogic.ShouldNotTryToResolve(resolvedFieldType))\n                {\n                    return false;\n                }\n                if (!UnityEngineTypePredicates.IsUnityEngineObject(resolvedFieldType))\n                {\n                    if (resolvedFieldType.FullName == fieldDefinition.DeclaringType.FullName)\n                    {\n                        return false;\n                    }\n                }\n                return UnitySerializationLogic.WillUnitySerialize(fieldDefinition, TypeResolver);\n            }\n            catch (Exception ex)\n            {\n                throw new Exception(string.Format(\"Exception while processing {0} {1}, error {2}\", fieldDefinition.FieldType.FullName, fieldDefinition.FullName, ex.Message));\n            }\n        }\n\n        private static bool IsHiddenByParentClass(IEnumerable<TypeReference> parentTypes, FieldDefinition fieldDefinition, TypeDefinition processingType)\n        {\n            return processingType.Fields.Any(f => f.Name == fieldDefinition.Name) || parentTypes.Any(t => t.Resolve().Fields.Any(f => f.Name == fieldDefinition.Name));\n        }\n\n        private IEnumerable<FieldDefinition> FilteredFields()\n        {\n            return TypeDef.Fields.Where(WillUnitySerialize).Where(f =>\n                UnitySerializationLogic.IsSupportedCollection(f.FieldType) ||\n                !f.FieldType.IsGenericInstance ||\n                UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve()));\n        }\n\n        private FieldReference ResolveGenericFieldReference(FieldReference fieldRef)\n        {\n            var field = new FieldReference(fieldRef.Name, fieldRef.FieldType, ResolveDeclaringType(fieldRef.DeclaringType));\n            return TypeDef.Module.ImportReference(field);\n        }\n\n        private TypeReference ResolveDeclaringType(TypeReference declaringType)\n        {\n            var typeDefinition = declaringType.Resolve();\n            if (typeDefinition == null || !typeDefinition.HasGenericParameters)\n            {\n                return typeDefinition;\n            }\n            var genericInstanceType = new GenericInstanceType(typeDefinition);\n            foreach (var genericParameter in typeDefinition.GenericParameters)\n            {\n                genericInstanceType.GenericArguments.Add(genericParameter);\n            }\n            return TypeResolver.Resolve(genericInstanceType);\n        }\n\n        private List<TypeTreeNode> ProcessingFieldRef(FieldReference fieldDef)\n        {\n            var typeRef = TypeResolver.Resolve(fieldDef.FieldType);\n            return TypeRefToTypeTreeNodes(typeRef, fieldDef.Name, Indent, false);\n        }\n\n        private static bool IsStruct(TypeReference typeRef)\n        {\n            return typeRef.IsValueType && !IsEnum(typeRef) && !typeRef.IsPrimitive;\n        }\n\n        private static bool IsEnum(TypeReference typeRef)\n        {\n            return !typeRef.IsArray && typeRef.Resolve().IsEnum;\n        }\n\n        private static bool RequiresAlignment(TypeReference typeRef)\n        {\n            switch (typeRef.MetadataType)\n            {\n                case MetadataType.Boolean:\n                case MetadataType.Char:\n                case MetadataType.SByte:\n                case MetadataType.Byte:\n                case MetadataType.Int16:\n                case MetadataType.UInt16:\n                    return true;\n                default:\n                    return UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef));\n            }\n        }\n\n        private static bool IsSystemString(TypeReference typeRef)\n        {\n            return typeRef.FullName == \"System.String\";\n        }\n\n        private List<TypeTreeNode> TypeRefToTypeTreeNodes(TypeReference typeRef, string name, int indent, bool isElement)\n        {\n            var align = false;\n\n            if (!IsStruct(TypeDef) || !UnityEngineTypePredicates.IsUnityEngineValueType(TypeDef))\n            {\n                if (IsStruct(typeRef) || RequiresAlignment(typeRef))\n                {\n                    align = true;\n                }\n            }\n\n            var nodes = new List<TypeTreeNode>();\n            if (typeRef.IsPrimitive)\n            {\n                var primitiveName = typeRef.Name;\n                switch (primitiveName)\n                {\n                    case \"Boolean\":\n                        primitiveName = \"bool\";\n                        break;\n                    case \"Byte\":\n                        primitiveName = \"UInt8\";\n                        break;\n                    case \"SByte\":\n                        primitiveName = \"SInt8\";\n                        break;\n                    case \"Int16\":\n                        primitiveName = \"SInt16\";\n                        break;\n                    case \"UInt16\":\n                        primitiveName = \"UInt16\";\n                        break;\n                    case \"Int32\":\n                        primitiveName = \"SInt32\";\n                        break;\n                    case \"UInt32\":\n                        primitiveName = \"UInt32\";\n                        break;\n                    case \"Int64\":\n                        primitiveName = \"SInt64\";\n                        break;\n                    case \"UInt64\":\n                        primitiveName = \"UInt64\";\n                        break;\n                    case \"Char\":\n                        primitiveName = \"char\";\n                        break;\n                    case \"Double\":\n                        primitiveName = \"double\";\n                        break;\n                    case \"Single\":\n                        primitiveName = \"float\";\n                        break;\n                    default:\n                        throw new NotSupportedException();\n                }\n                if (isElement)\n                {\n                    align = false;\n                }\n                nodes.Add(new TypeTreeNode(primitiveName, name, indent, align));\n            }\n            else if (IsSystemString(typeRef))\n            {\n                Helper.AddString(nodes, name, indent);\n            }\n            else if (IsEnum(typeRef))\n            {\n                nodes.Add(new TypeTreeNode(\"SInt32\", name, indent, align));\n            }\n            else if (CecilUtils.IsGenericList(typeRef))\n            {\n                var elementRef = CecilUtils.ElementTypeOfCollection(typeRef);\n                nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align));\n                Helper.AddArray(nodes, indent + 1);\n                nodes.AddRange(TypeRefToTypeTreeNodes(elementRef, \"data\", indent + 2, true));\n            }\n            else if (typeRef.IsArray)\n            {\n                var elementRef = typeRef.GetElementType();\n                nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align));\n                Helper.AddArray(nodes, indent + 1);\n                nodes.AddRange(TypeRefToTypeTreeNodes(elementRef, \"data\", indent + 2, true));\n            }\n            else if (UnityEngineTypePredicates.IsUnityEngineObject(typeRef))\n            {\n                Helper.AddPPtr(nodes, typeRef.Name, name, indent);\n            }\n            else if (UnityEngineTypePredicates.IsSerializableUnityClass(typeRef) || UnityEngineTypePredicates.IsSerializableUnityStruct(typeRef))\n            {\n                switch (typeRef.FullName)\n                {\n                    case \"UnityEngine.AnimationCurve\":\n                        Helper.AddAnimationCurve(nodes, name, indent);\n                        break;\n                    case \"UnityEngine.Gradient\":\n                        Helper.AddGradient(nodes, name, indent);\n                        break;\n                    case \"UnityEngine.GUIStyle\":\n                        Helper.AddGUIStyle(nodes, name, indent);\n                        break;\n                    case \"UnityEngine.RectOffset\":\n                        Helper.AddRectOffset(nodes, name, indent);\n                        break;\n                    case \"UnityEngine.Color32\":\n                        Helper.AddColor32(nodes, name, indent);\n                        break;\n                    case \"UnityEngine.Matrix4x4\":\n                        Helper.AddMatrix4x4(nodes, name, indent);\n                        break;\n                    case \"UnityEngine.Rendering.SphericalHarmonicsL2\":\n                        Helper.AddSphericalHarmonicsL2(nodes, name, indent);\n                        break;\n                    case \"UnityEngine.PropertyName\":\n                        Helper.AddPropertyName(nodes, name, indent);\n                        break;\n                }\n            }\n            else\n            {\n                nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align));\n                var typeDef = typeRef.Resolve();\n                var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, Helper, indent + 1);\n                nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes());\n            }\n\n            return nodes;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.CecilTools/CecilUtils.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Mono.Cecil;\nusing Unity.CecilTools.Extensions;\n\nnamespace Unity.CecilTools\n{\n    public static class CecilUtils\n    {\n        public static MethodDefinition FindInTypeExplicitImplementationFor(MethodDefinition interfaceMethod, TypeDefinition typeDefinition)\n        {\n            return typeDefinition.Methods.SingleOrDefault(m => m.Overrides.Any(o => o.CheckedResolve().SameAs(interfaceMethod)));\n        }\n\n        public static IEnumerable<TypeDefinition> AllInterfacesImplementedBy(TypeDefinition typeDefinition)\n        {\n            return TypeAndBaseTypesOf(typeDefinition).SelectMany(t => t.Interfaces).Select(i => i.InterfaceType.CheckedResolve()).Distinct();\n        }\n\n        public static IEnumerable<TypeDefinition> TypeAndBaseTypesOf(TypeReference typeReference)\n        {\n            while (typeReference != null)\n            {\n                var typeDefinition = typeReference.CheckedResolve();\n                yield return typeDefinition;\n                typeReference = typeDefinition.BaseType;\n            }\n        }\n\n        public static IEnumerable<TypeDefinition> BaseTypesOf(TypeReference typeReference)\n        {\n            return TypeAndBaseTypesOf(typeReference).Skip(1);\n        }\n\n        public static bool IsGenericList(TypeReference type)\n        {\n            return type.Name == \"List`1\" && type.SafeNamespace() == \"System.Collections.Generic\";\n        }\n\n        public static bool IsGenericDictionary(TypeReference type)\n        {\n            if (type is GenericInstanceType)\n                type = ((GenericInstanceType)type).ElementType;\n\n            return type.Name == \"Dictionary`2\" && type.SafeNamespace() == \"System.Collections.Generic\";\n        }\n\n        public static TypeReference ElementTypeOfCollection(TypeReference type)\n        {\n            var at = type as ArrayType;\n            if (at != null)\n                return at.ElementType;\n\n            if (IsGenericList(type))\n                return ((GenericInstanceType)type).GenericArguments.Single();\n\n            throw new ArgumentException();\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.CecilTools/ElementType.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Mono.Cecil;\n\nnamespace Unity.CecilTools\n{\n    static public class ElementType\n    {\n        public static TypeReference For(TypeReference byRefType)\n        {\n            var refType = byRefType as TypeSpecification;\n            if (refType != null)\n                return refType.ElementType;\n\n            throw new ArgumentException(string.Format(\"TypeReference isn't a TypeSpecification {0} \", byRefType));\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.CecilTools/Extensions/MethodDefinitionExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing Mono.Cecil;\n\nnamespace Unity.CecilTools.Extensions\n{\n    static class MethodDefinitionExtensions\n    {\n        public static bool SameAs(this MethodDefinition self, MethodDefinition other)\n        {\n            // FIXME: should be able to compare MethodDefinition references directly\n            return self.FullName == other.FullName;\n        }\n\n        public static string PropertyName(this MethodDefinition self)\n        {\n            return self.Name.Substring(4);\n        }\n\n        public static bool IsConversionOperator(this MethodDefinition method)\n        {\n            if (!method.IsSpecialName)\n                return false;\n\n            return method.Name == \"op_Implicit\" || method.Name == \"op_Explicit\";\n        }\n\n        public static bool IsSimpleSetter(this MethodDefinition original)\n        {\n            return original.IsSetter && original.Parameters.Count == 1;\n        }\n\n        public static bool IsSimpleGetter(this MethodDefinition original)\n        {\n            return original.IsGetter && original.Parameters.Count == 0;\n        }\n\n        public static bool IsSimplePropertyAccessor(this MethodDefinition method)\n        {\n            return method.IsSimpleGetter() || method.IsSimpleSetter();\n        }\n\n        public static bool IsDefaultConstructor(MethodDefinition m)\n        {\n            return m.IsConstructor && !m.IsStatic && m.Parameters.Count == 0;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.CecilTools/Extensions/ResolutionExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing Mono.Cecil;\n\nnamespace Unity.CecilTools.Extensions\n{\n    public static class ResolutionExtensions\n    {\n        public static TypeDefinition CheckedResolve(this TypeReference type)\n        {\n            return Resolve(type, reference => reference.Resolve());\n        }\n\n        public static MethodDefinition CheckedResolve(this MethodReference method)\n        {\n            return Resolve(method, reference => reference.Resolve());\n        }\n\n        private static TDefinition Resolve<TReference, TDefinition>(TReference reference, Func<TReference, TDefinition> resolve)\n            where TReference : MemberReference\n            where TDefinition : class, IMemberDefinition\n        {\n            if (reference.Module == null)\n                throw new ResolutionException(reference);\n\n            var definition = resolve(reference);\n            if (definition == null)\n                throw new ResolutionException(reference);\n\n            return definition;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.CecilTools/Extensions/TypeDefinitionExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Mono.Cecil;\n\nnamespace Unity.CecilTools.Extensions\n{\n    public static class TypeDefinitionExtensions\n    {\n        public static bool IsSubclassOf(this TypeDefinition type, string baseTypeName)\n        {\n            var baseType = type.BaseType;\n            if (baseType == null)\n                return false;\n            if (baseType.FullName == baseTypeName)\n                return true;\n\n            var baseTypeDef = baseType.Resolve();\n            if (baseTypeDef == null)\n                return false;\n\n            return IsSubclassOf(baseTypeDef, baseTypeName);\n        }\n\n        public static bool IsSubclassOf(this TypeDefinition type, params string[] baseTypeNames)\n        {\n            var baseType = type.BaseType;\n            if (baseType == null)\n                return false;\n\n            for (int i = 0; i < baseTypeNames.Length; i++)\n                if (baseType.FullName == baseTypeNames[i])\n                    return true;\n\n            var baseTypeDef = baseType.Resolve();\n            if (baseTypeDef == null)\n                return false;\n\n            return IsSubclassOf(baseTypeDef, baseTypeNames);\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.CecilTools/Extensions/TypeReferenceExtensions.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing Mono.Cecil;\n\nnamespace Unity.CecilTools.Extensions\n{\n    public static class TypeReferenceExtensions\n    {\n        public static string SafeNamespace(this TypeReference type)\n        {\n            if (type.IsGenericInstance)\n                return ((GenericInstanceType)type).ElementType.SafeNamespace();\n            if (type.IsNested)\n                return type.DeclaringType.SafeNamespace();\n            return type.Namespace;\n        }\n\n        public static bool IsAssignableTo(this TypeReference typeRef, string typeName)\n        {\n            try\n            {\n                if (typeRef.IsGenericInstance)\n                    return ElementType.For(typeRef).IsAssignableTo(typeName);\n\n                if (typeRef.FullName == typeName)\n                    return true;\n\n                return typeRef.CheckedResolve().IsSubclassOf(typeName);\n            }\n            catch (AssemblyResolutionException) // If we can't resolve our typeref or one of its base types,\n            {                                   // let's assume it is not assignable to our target type\n                return false;\n            }\n        }\n\n        public static bool IsEnum(this TypeReference type)\n        {\n            return type.IsValueType && !type.IsPrimitive && type.CheckedResolve().IsEnum;\n        }\n\n        public static bool IsStruct(this TypeReference type)\n        {\n            return type.IsValueType && !type.IsPrimitive && !type.IsEnum() && !IsSystemDecimal(type);\n        }\n\n        private static bool IsSystemDecimal(TypeReference type)\n        {\n            return type.FullName == \"System.Decimal\";\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.SerializationLogic/UnityEngineTypePredicates.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System.Collections.Generic;\nusing Unity.CecilTools.Extensions;\nusing Mono.Cecil;\n\nnamespace Unity.SerializationLogic\n{\n    public class UnityEngineTypePredicates\n    {\n        private static readonly HashSet<string> TypesThatShouldHaveHadSerializableAttribute = new HashSet<string>\n        {\n            \"Vector3\",\n            \"Vector2\",\n            \"Vector4\",\n            \"Rect\",\n            \"RectInt\",\n            \"Quaternion\",\n            \"Matrix4x4\",\n            \"Color\",\n            \"Color32\",\n            \"LayerMask\",\n            \"Bounds\",\n            \"BoundsInt\",\n            \"Vector3Int\",\n            \"Vector2Int\",\n        };\n\n        private const string Gradient = \"UnityEngine.Gradient\";\n        private const string GUIStyle = \"UnityEngine.GUIStyle\";\n        private const string RectOffset = \"UnityEngine.RectOffset\";\n        protected const string UnityEngineObject = \"UnityEngine.Object\";\n        public const string MonoBehaviour = \"UnityEngine.MonoBehaviour\";\n        public const string ScriptableObject = \"UnityEngine.ScriptableObject\";\n        protected const string Matrix4x4 = \"UnityEngine.Matrix4x4\";\n        protected const string Color32 = \"UnityEngine.Color32\";\n        private const string SerializeFieldAttribute = \"UnityEngine.SerializeField\";\n        private const string SerializeReferenceAttribute = \"UnityEngine.SerializeReference\";\n\n        private static string[] serializableClasses = new[]\n        {\n            \"UnityEngine.AnimationCurve\",\n            \"UnityEngine.Gradient\",\n            \"UnityEngine.GUIStyle\",\n            \"UnityEngine.RectOffset\"\n        };\n\n        private static string[] serializableStructs = new[]\n        {\n            // NOTE: assumes all types here are NOT interfaces\n            \"UnityEngine.Color32\",\n            \"UnityEngine.Matrix4x4\",\n            \"UnityEngine.Rendering.SphericalHarmonicsL2\",\n            \"UnityEngine.PropertyName\",\n        };\n\n        public static bool IsMonoBehaviour(TypeReference type)\n        {\n            return IsMonoBehaviour(type.CheckedResolve());\n        }\n\n        private static bool IsMonoBehaviour(TypeDefinition typeDefinition)\n        {\n            return typeDefinition.IsSubclassOf(MonoBehaviour);\n        }\n\n        public static bool IsScriptableObject(TypeReference type)\n        {\n            return IsScriptableObject(type.CheckedResolve());\n        }\n\n        private static bool IsScriptableObject(TypeDefinition temp)\n        {\n            return temp.IsSubclassOf(ScriptableObject);\n        }\n\n        public static bool IsColor32(TypeReference type)\n        {\n            return type.IsAssignableTo(Color32);\n        }\n\n        //Do NOT remove these, cil2as still depends on these in 4.x\n        public static bool IsMatrix4x4(TypeReference type)\n        {\n            return type.IsAssignableTo(Matrix4x4);\n        }\n\n        public static bool IsGradient(TypeReference type)\n        {\n            return type.IsAssignableTo(Gradient);\n        }\n\n        public static bool IsGUIStyle(TypeReference type)\n        {\n            return type.IsAssignableTo(GUIStyle);\n        }\n\n        public static bool IsRectOffset(TypeReference type)\n        {\n            return type.IsAssignableTo(RectOffset);\n        }\n\n        public static bool IsSerializableUnityClass(TypeReference type)\n        {\n            foreach (var unityClasses in serializableClasses)\n            {\n                if (type.IsAssignableTo(unityClasses))\n                    return true;\n            }\n            return false;\n        }\n\n        public static bool IsSerializableUnityStruct(TypeReference type)\n        {\n            foreach (var unityStruct in serializableStructs)\n            {\n                // NOTE: structs cannot inherit from structs, and can only inherit from interfaces\n                //       since we know all types in serializableStructs are not interfaces,\n                //       we can just do a direct comparison.\n                if (type.FullName == unityStruct)\n                    return true;\n            }\n\n            if (type.FullName.IndexOf(\"UnityEngine.LazyLoadReference`1\") == 0)\n                return true;\n\n            return false;\n        }\n\n        public static bool IsUnityEngineObject(TypeReference type)\n        {\n            //todo: somehow solve this elegantly. CheckedResolve() drops the [] of a type.\n            if (type.IsArray)\n                return false;\n\n            if (type.FullName == UnityEngineObject)\n                return true;\n\n            var typeDefinition = type.Resolve();\n            if (typeDefinition == null)\n                return false;\n\n            return typeDefinition.IsSubclassOf(UnityEngineObject);\n        }\n\n        public static bool ShouldHaveHadSerializableAttribute(TypeReference type)\n        {\n            return IsUnityEngineValueType(type);\n        }\n\n        public static bool IsUnityEngineValueType(TypeReference type)\n        {\n            return type.SafeNamespace() == \"UnityEngine\" && TypesThatShouldHaveHadSerializableAttribute.Contains(type.Name);\n        }\n\n        public static bool IsSerializeFieldAttribute(TypeReference attributeType)\n        {\n            return attributeType.FullName == SerializeFieldAttribute;\n        }\n\n        public static bool IsSerializeReferenceAttribute(TypeReference attributeType)\n        {\n            return attributeType.FullName == SerializeReferenceAttribute;\n        }\n    }\n}\n"
  },
  {
    "path": "AssetStudioUtility/Unity.SerializationLogic/UnitySerializationLogic.cs",
    "content": "// Unity C# reference source\n// Copyright (c) Unity Technologies. For terms of use, see\n// https://unity3d.com/legal/licenses/Unity_Reference_Only_License\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Mono.Cecil;\nusing Mono.Collections.Generic;\nusing Unity.CecilTools;\nusing Unity.CecilTools.Extensions;\n\nnamespace Unity.SerializationLogic\n{\n    internal class GenericInstanceHolder\n    {\n        public int Count;\n        public IGenericInstance GenericInstance;\n    }\n\n    public class TypeResolver\n    {\n        private readonly IGenericInstance _typeDefinitionContext;\n        private readonly IGenericInstance _methodDefinitionContext;\n        private readonly Dictionary<string, GenericInstanceHolder> _context = new Dictionary<string, GenericInstanceHolder>();\n\n        public TypeResolver()\n        {\n        }\n\n        public TypeResolver(IGenericInstance typeDefinitionContext)\n        {\n            _typeDefinitionContext = typeDefinitionContext;\n        }\n\n        public TypeResolver(GenericInstanceMethod methodDefinitionContext)\n        {\n            _methodDefinitionContext = methodDefinitionContext;\n        }\n\n        public TypeResolver(IGenericInstance typeDefinitionContext, IGenericInstance methodDefinitionContext)\n        {\n            _typeDefinitionContext = typeDefinitionContext;\n            _methodDefinitionContext = methodDefinitionContext;\n        }\n\n        public void Add(GenericInstanceType genericInstanceType)\n        {\n            Add(ElementTypeFor(genericInstanceType).FullName, genericInstanceType);\n        }\n\n        public void Remove(GenericInstanceType genericInstanceType)\n        {\n            Remove(genericInstanceType.ElementType.FullName, genericInstanceType);\n        }\n\n        public void Add(GenericInstanceMethod genericInstanceMethod)\n        {\n            Add(ElementTypeFor(genericInstanceMethod).FullName, genericInstanceMethod);\n        }\n\n        private static MemberReference ElementTypeFor(TypeSpecification genericInstanceType)\n        {\n            return genericInstanceType.ElementType;\n        }\n\n        private static MemberReference ElementTypeFor(MethodSpecification genericInstanceMethod)\n        {\n            return genericInstanceMethod.ElementMethod;\n        }\n\n        public void Remove(GenericInstanceMethod genericInstanceMethod)\n        {\n            Remove(genericInstanceMethod.ElementMethod.FullName, genericInstanceMethod);\n        }\n\n        public TypeReference Resolve(TypeReference typeReference)\n        {\n            var genericParameter = typeReference as GenericParameter;\n            if (genericParameter != null)\n            {\n                var resolved = ResolveGenericParameter(genericParameter);\n                if (genericParameter == resolved) // Resolving failed, return what we have.\n                    return resolved;\n\n                return Resolve(resolved);\n            }\n\n            var arrayType = typeReference as ArrayType;\n            if (arrayType != null)\n                return new ArrayType(Resolve(arrayType.ElementType), arrayType.Rank);\n\n            var pointerType = typeReference as PointerType;\n            if (pointerType != null)\n                return new PointerType(Resolve(pointerType.ElementType));\n\n            var byReferenceType = typeReference as ByReferenceType;\n            if (byReferenceType != null)\n                return new ByReferenceType(Resolve(byReferenceType.ElementType));\n\n            var genericInstanceType = typeReference as GenericInstanceType;\n            if (genericInstanceType != null)\n            {\n                var newGenericInstanceType = new GenericInstanceType(Resolve(genericInstanceType.ElementType));\n                foreach (var genericArgument in genericInstanceType.GenericArguments)\n                    newGenericInstanceType.GenericArguments.Add(Resolve(genericArgument));\n                return newGenericInstanceType;\n            }\n\n            var pinnedType = typeReference as PinnedType;\n            if (pinnedType != null)\n                return new PinnedType(Resolve(pinnedType.ElementType));\n\n            var reqModifierType = typeReference as RequiredModifierType;\n            if (reqModifierType != null)\n                return Resolve(reqModifierType.ElementType);\n\n            var optModifierType = typeReference as OptionalModifierType;\n            if (optModifierType != null)\n                return new OptionalModifierType(Resolve(optModifierType.ModifierType), Resolve(optModifierType.ElementType));\n\n            var sentinelType = typeReference as SentinelType;\n            if (sentinelType != null)\n                return new SentinelType(Resolve(sentinelType.ElementType));\n\n            var funcPtrType = typeReference as FunctionPointerType;\n            if (funcPtrType != null)\n                throw new NotSupportedException(\"Function pointer types are not supported by the SerializationWeaver\");\n\n            if (typeReference is TypeSpecification)\n                throw new NotSupportedException();\n\n            return typeReference;\n        }\n\n        private TypeReference ResolveGenericParameter(GenericParameter genericParameter)\n        {\n            if (genericParameter.Owner == null)\n                throw new NotSupportedException();\n\n            var memberReference = genericParameter.Owner as MemberReference;\n            if (memberReference == null)\n                throw new NotSupportedException();\n\n            var key = memberReference.FullName;\n            if (!_context.ContainsKey(key))\n            {\n                if (genericParameter.Type == GenericParameterType.Type)\n                {\n                    if (_typeDefinitionContext != null)\n                        return _typeDefinitionContext.GenericArguments[genericParameter.Position];\n\n                    return genericParameter;\n                }\n\n                if (_methodDefinitionContext != null)\n                    return _methodDefinitionContext.GenericArguments[genericParameter.Position];\n\n                return genericParameter;\n            }\n\n            return GenericArgumentAt(key, genericParameter.Position);\n        }\n\n        private TypeReference GenericArgumentAt(string key, int position)\n        {\n            return _context[key].GenericInstance.GenericArguments[position];\n        }\n\n        private void Add(string key, IGenericInstance value)\n        {\n            GenericInstanceHolder oldValue;\n\n            if (_context.TryGetValue(key, out oldValue))\n            {\n                var memberReference = value as MemberReference;\n                if (memberReference == null)\n                    throw new NotSupportedException();\n\n                var storedValue = (MemberReference)oldValue.GenericInstance;\n\n                if (storedValue.FullName != memberReference.FullName)\n                    throw new ArgumentException(\"Duplicate key!\", \"key\");\n\n                oldValue.Count++;\n                return;\n            }\n\n            _context.Add(key, new GenericInstanceHolder { Count = 1, GenericInstance = value });\n        }\n\n        private void Remove(string key, IGenericInstance value)\n        {\n            GenericInstanceHolder oldValue;\n\n            if (_context.TryGetValue(key, out oldValue))\n            {\n                var memberReference = value as MemberReference;\n                if (memberReference == null)\n                    throw new NotSupportedException();\n\n                var storedValue = (MemberReference)oldValue.GenericInstance;\n\n                if (storedValue.FullName != memberReference.FullName)\n                    throw new ArgumentException(\"Invalid value!\", \"value\");\n\n                oldValue.Count--;\n                if (oldValue.Count == 0)\n                    _context.Remove(key);\n\n                return;\n            }\n\n            throw new ArgumentException(\"Invalid key!\", \"key\");\n        }\n    }\n\n    public static class UnitySerializationLogic\n    {\n        public static bool WillUnitySerialize(FieldDefinition fieldDefinition)\n        {\n            return WillUnitySerialize(fieldDefinition, new TypeResolver(null));\n        }\n\n        public static bool WillUnitySerialize(FieldDefinition fieldDefinition, TypeResolver typeResolver)\n        {\n            if (fieldDefinition == null)\n                return false;\n\n            //skip static, const and NotSerialized fields before even checking the type\n            if (fieldDefinition.IsStatic || IsConst(fieldDefinition) || fieldDefinition.IsNotSerialized || fieldDefinition.IsInitOnly)\n                return false;\n\n            // The field must have correct visibility/decoration to be serialized.\n            if (!fieldDefinition.IsPublic &&\n                !ShouldHaveHadAllFieldsPublic(fieldDefinition) &&\n                !HasSerializeFieldAttribute(fieldDefinition) &&\n                !HasSerializeReferenceAttribute(fieldDefinition))\n                return false;\n\n            // Don't try to resolve types that come from Windows assembly,\n            // as serialization weaver will fail to resolve that (due to it being in platform specific SDKs)\n            if (ShouldNotTryToResolve(fieldDefinition.FieldType))\n                return false;\n\n            if (IsFixedBuffer(fieldDefinition))\n                return true;\n\n            // Resolving types is more complex and slower than checking their names or attributes,\n            // thus keep those checks below\n            var typeReference = typeResolver.Resolve(fieldDefinition.FieldType);\n\n            //the type of the field must be serializable in the first place.\n\n            if (typeReference.MetadataType == MetadataType.String)\n                return true;\n\n            if (typeReference.IsValueType)\n                return IsValueTypeSerializable(typeReference);\n\n            if (typeReference is ArrayType || CecilUtils.IsGenericList(typeReference))\n            {\n                if (!HasSerializeReferenceAttribute(fieldDefinition))\n                    return IsSupportedCollection(typeReference);\n            }\n\n\n            if (!IsReferenceTypeSerializable(typeReference) && !HasSerializeReferenceAttribute(fieldDefinition))\n                return false;\n\n            if (IsDelegate(typeReference))\n                return false;\n\n            return true;\n        }\n\n        private static bool IsDelegate(TypeReference typeReference)\n        {\n            return typeReference.IsAssignableTo(\"System.Delegate\");\n        }\n\n        public static bool ShouldFieldBePPtrRemapped(FieldDefinition fieldDefinition)\n        {\n            return ShouldFieldBePPtrRemapped(fieldDefinition, new TypeResolver(null));\n        }\n\n        public static bool ShouldFieldBePPtrRemapped(FieldDefinition fieldDefinition, TypeResolver typeResolver)\n        {\n            if (!WillUnitySerialize(fieldDefinition, typeResolver))\n                return false;\n\n            return CanTypeContainUnityEngineObjectReference(typeResolver.Resolve(fieldDefinition.FieldType));\n        }\n\n        private static bool CanTypeContainUnityEngineObjectReference(TypeReference typeReference)\n        {\n            if (IsUnityEngineObject(typeReference))\n                return true;\n\n            if (typeReference.IsEnum())\n                return false;\n\n            if (IsSerializablePrimitive(typeReference))\n                return false;\n\n            if (IsSupportedCollection(typeReference))\n                return CanTypeContainUnityEngineObjectReference(CecilUtils.ElementTypeOfCollection(typeReference));\n\n            var definition = typeReference.Resolve();\n            if (definition == null)\n                return false;\n\n            return HasFieldsThatCanContainUnityEngineObjectReferences(definition, new TypeResolver(typeReference as GenericInstanceType));\n        }\n\n        private static bool HasFieldsThatCanContainUnityEngineObjectReferences(TypeDefinition definition, TypeResolver typeResolver)\n        {\n            return AllFieldsFor(definition, typeResolver).Where(kv => kv.Value.Resolve(kv.Key.FieldType).Resolve() != definition).Any(kv => CanFieldContainUnityEngineObjectReference(definition, kv.Key, kv.Value));\n        }\n\n        private static IEnumerable<KeyValuePair<FieldDefinition, TypeResolver>> AllFieldsFor(TypeDefinition definition, TypeResolver typeResolver)\n        {\n            var baseType = definition.BaseType;\n\n            if (baseType != null)\n            {\n                var genericBaseInstanceType = baseType as GenericInstanceType;\n                if (genericBaseInstanceType != null)\n                    typeResolver.Add(genericBaseInstanceType);\n                foreach (var kv in AllFieldsFor(baseType.Resolve(), typeResolver))\n                    yield return kv;\n                if (genericBaseInstanceType != null)\n                    typeResolver.Remove(genericBaseInstanceType);\n            }\n\n            foreach (var fieldDefinition in definition.Fields)\n                yield return new KeyValuePair<FieldDefinition, TypeResolver>(fieldDefinition, typeResolver);\n        }\n\n        private static bool CanFieldContainUnityEngineObjectReference(TypeReference typeReference, FieldDefinition t, TypeResolver typeResolver)\n        {\n            if (typeResolver.Resolve(t.FieldType) == typeReference)\n                return false;\n\n            if (!WillUnitySerialize(t, typeResolver))\n                return false;\n\n            if (UnityEngineTypePredicates.IsUnityEngineValueType(typeReference))\n                return false;\n\n            return true;\n        }\n\n        private static bool IsConst(FieldDefinition fieldDefinition)\n        {\n            return fieldDefinition.IsLiteral && !fieldDefinition.IsInitOnly;\n        }\n\n        public static bool HasSerializeFieldAttribute(FieldDefinition field)\n        {\n            //return FieldAttributes(field).Any(UnityEngineTypePredicates.IsSerializeFieldAttribute);\n            foreach (var attribute in FieldAttributes(field))\n                if (UnityEngineTypePredicates.IsSerializeFieldAttribute(attribute))\n                    return true;\n            return false;\n        }\n\n        public static bool HasSerializeReferenceAttribute(FieldDefinition field)\n        {\n            foreach (var attribute in FieldAttributes(field))\n                if (UnityEngineTypePredicates.IsSerializeReferenceAttribute(attribute))\n                    return true;\n            return false;\n        }\n\n        private static IEnumerable<TypeReference> FieldAttributes(FieldDefinition field)\n        {\n            return field.CustomAttributes.Select(_ => _.AttributeType);\n        }\n\n        public static bool ShouldNotTryToResolve(TypeReference typeReference)\n        {\n            var typeReferenceScopeName = typeReference.Scope.Name;\n            if (typeReferenceScopeName == \"Windows\")\n            {\n                return true;\n            }\n\n            if (typeReferenceScopeName == \"mscorlib\")\n            {\n                var resolved = typeReference.Resolve();\n                return resolved == null;\n            }\n\n            try\n            {   // This will throw an exception if typereference thinks it's referencing a .dll,\n                // but actually there's .winmd file in the current directory. RRW will fix this\n                // at a later step, so we will not try to resolve this type. This is OK, as any\n                // type defined in a winmd cannot be serialized.\n                typeReference.Resolve();\n            }\n            catch\n            {\n                return true;\n            }\n\n            return false;\n        }\n\n        private static bool IsFieldTypeSerializable(TypeReference typeReference, FieldDefinition fieldDefinition)\n        {\n            return IsTypeSerializable(typeReference) || IsSupportedCollection(typeReference) || IsFixedBuffer(fieldDefinition);\n        }\n\n        private static bool IsValueTypeSerializable(TypeReference typeReference)\n        {\n            if (typeReference.IsPrimitive)\n                return IsSerializablePrimitive(typeReference);\n            return UnityEngineTypePredicates.IsSerializableUnityStruct(typeReference) ||\n                typeReference.IsEnum() ||\n                ShouldImplementIDeserializable(typeReference);\n        }\n\n        private static bool IsReferenceTypeSerializable(TypeReference typeReference)\n        {\n            if (typeReference.MetadataType == MetadataType.String)\n                return IsSerializablePrimitive(typeReference);\n\n            if (IsGenericDictionary(typeReference))\n                return false;\n\n            if (IsUnityEngineObject(typeReference) ||\n                ShouldImplementIDeserializable(typeReference) ||\n                UnityEngineTypePredicates.IsSerializableUnityClass(typeReference))\n                return true;\n\n            return false;\n        }\n\n        private static bool IsTypeSerializable(TypeReference typeReference)\n        {\n            if (typeReference.MetadataType == MetadataType.String)\n                return true;\n            if (typeReference.IsValueType)\n                return IsValueTypeSerializable(typeReference);\n            return IsReferenceTypeSerializable(typeReference);\n        }\n\n        private static bool IsGenericDictionary(TypeReference typeReference)\n        {\n            var current = typeReference;\n\n            if (current != null)\n            {\n                if (CecilUtils.IsGenericDictionary(current))\n                    return true;\n            }\n\n            return false;\n        }\n\n        public static bool IsFixedBuffer(FieldDefinition fieldDefinition)\n        {\n            return GetFixedBufferAttribute(fieldDefinition) != null;\n        }\n\n        public static CustomAttribute GetFixedBufferAttribute(FieldDefinition fieldDefinition)\n        {\n            if (!fieldDefinition.HasCustomAttributes)\n                return null;\n\n            return fieldDefinition.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == \"System.Runtime.CompilerServices.FixedBufferAttribute\");\n        }\n\n        public static int GetFixedBufferLength(FieldDefinition fieldDefinition)\n        {\n            var fixedBufferAttribute = GetFixedBufferAttribute(fieldDefinition);\n\n            if (fixedBufferAttribute == null)\n                throw new ArgumentException(string.Format(\"Field '{0}' is not a fixed buffer field.\", fieldDefinition.FullName));\n\n            var size = (Int32)fixedBufferAttribute.ConstructorArguments[1].Value;\n\n            return size;\n        }\n\n        public static int PrimitiveTypeSize(TypeReference type)\n        {\n            switch (type.MetadataType)\n            {\n                case MetadataType.Boolean:\n                case MetadataType.Byte:\n                case MetadataType.SByte:\n                    return 1;\n\n                case MetadataType.Char:\n                case MetadataType.Int16:\n                case MetadataType.UInt16:\n                    return 2;\n\n                case MetadataType.Int32:\n                case MetadataType.UInt32:\n                case MetadataType.Single:\n                    return 4;\n\n                case MetadataType.Int64:\n                case MetadataType.UInt64:\n                case MetadataType.Double:\n                    return 8;\n\n                default:\n                    throw new ArgumentException(string.Format(\"Unsupported {0}\", type.MetadataType));\n            }\n        }\n\n        private static bool IsSerializablePrimitive(TypeReference typeReference)\n        {\n            switch (typeReference.MetadataType)\n            {\n                case MetadataType.SByte:\n                case MetadataType.Byte:\n                case MetadataType.Char:\n                case MetadataType.Int16:\n                case MetadataType.UInt16:\n                case MetadataType.Int64:\n                case MetadataType.UInt64:\n                case MetadataType.Int32:\n                case MetadataType.UInt32:\n                case MetadataType.Single:\n                case MetadataType.Double:\n                case MetadataType.Boolean:\n                case MetadataType.String:\n                    return true;\n            }\n            return false;\n        }\n\n        public static bool IsSupportedCollection(TypeReference typeReference)\n        {\n            if (!(typeReference is ArrayType || CecilUtils.IsGenericList(typeReference)))\n                return false;\n\n            // We don't support arrays like byte[,] etc\n            if (typeReference.IsArray && ((ArrayType)typeReference).Rank > 1)\n                return false;\n\n            return IsTypeSerializable(CecilUtils.ElementTypeOfCollection(typeReference));\n        }\n\n        private static bool ShouldHaveHadAllFieldsPublic(FieldDefinition field)\n        {\n            return UnityEngineTypePredicates.IsUnityEngineValueType(field.DeclaringType);\n        }\n\n        private static bool IsUnityEngineObject(TypeReference typeReference)\n        {\n            return UnityEngineTypePredicates.IsUnityEngineObject(typeReference);\n        }\n\n        public static bool IsNonSerialized(TypeReference typeDeclaration)\n        {\n            if (typeDeclaration == null)\n                return true;\n            if (typeDeclaration.HasGenericParameters)\n                return true;\n            if (typeDeclaration.MetadataType == MetadataType.Object)\n                return true;\n            var fullName = typeDeclaration.FullName;\n            if (fullName.StartsWith(\"System.\")) //can this be done better?\n                return true;\n            if (typeDeclaration.IsArray)\n                return true;\n            if (typeDeclaration.FullName == UnityEngineTypePredicates.MonoBehaviour)\n                return true;\n            if (typeDeclaration.FullName == UnityEngineTypePredicates.ScriptableObject)\n                return true;\n            if (typeDeclaration.IsEnum())\n                return true;\n            return false;\n        }\n\n        public static bool ShouldImplementIDeserializable(TypeReference typeDeclaration)\n        {\n            if (typeDeclaration.FullName == \"UnityEngine.ExposedReference`1\")\n                return true;\n\n            if (IsNonSerialized(typeDeclaration))\n                return false;\n\n            try\n            {\n                if (UnityEngineTypePredicates.ShouldHaveHadSerializableAttribute(typeDeclaration))\n                    return true;\n\n                var resolvedTypeDeclaration = typeDeclaration.CheckedResolve();\n                if (resolvedTypeDeclaration.IsValueType)\n                {\n                    return resolvedTypeDeclaration.IsSerializable && !resolvedTypeDeclaration.CustomAttributes.Any(a => a.AttributeType.FullName.Contains(\"System.Runtime.CompilerServices.CompilerGenerated\"));\n                }\n                else\n                {\n                    return (resolvedTypeDeclaration.IsSerializable && !resolvedTypeDeclaration.CustomAttributes.Any(a => a.AttributeType.FullName.Contains(\"System.Runtime.CompilerServices.CompilerGenerated\"))) ||\n                        resolvedTypeDeclaration.IsSubclassOf(UnityEngineTypePredicates.MonoBehaviour, UnityEngineTypePredicates.ScriptableObject);\n                }\n            }\n            catch (Exception)\n            {\n                return false;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016 Radu\nCopyright (c) 2016-2020 Perfare\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# AssetStudio\n[![Build status](https://ci.appveyor.com/api/projects/status/rnu7l90422pdewx4?svg=true)](https://ci.appveyor.com/project/Perfare/assetstudio/branch/master/artifacts)\n\n**None of the repo, the tool, nor the repo owner is affiliated with, or sponsored or authorized by, Unity Technologies or its affiliates.**\n\nAssetStudio is a tool for exploring, extracting and exporting assets and assetbundles.\n\n## Features\n* Support version:\n  * 3.4 - 2022.1\n* Support asset types:\n  * **Texture2D** : convert to png, tga, jpeg, bmp\n  * **Sprite** : crop Texture2D to png, tga, jpeg, bmp\n  * **AudioClip** : mp3, ogg, wav, m4a, fsb. support convert FSB file to WAV(PCM)\n  * **Font** : ttf, otf\n  * **Mesh** : obj\n  * **TextAsset**\n  * **Shader**\n  * **MovieTexture**\n  * **VideoClip**\n  * **MonoBehaviour** : json\n  * **Animator** : export to FBX file with bound AnimationClip\n\n## Requirements\n\n- AssetStudio.net472\n   - [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)\n- AssetStudio.net5\n   - [.NET Desktop Runtime 5.0](https://dotnet.microsoft.com/download/dotnet/5.0)\n- AssetStudio.net6\n   - [.NET Desktop Runtime 6.0](https://dotnet.microsoft.com/download/dotnet/6.0)\n\n\n## Usage\n\n### Load Assets/AssetBundles\n\nUse **File-Load file** or **File-Load folder**.\n\nWhen AssetStudio loads AssetBundles, it decompresses and reads it directly in memory, which may cause a large amount of memory to be used. You can use **File-Extract file** or **File-Extract folder** to extract AssetBundles to another folder, and then read.\n\n### Extract/Decompress AssetBundles\n\nUse **File-Extract file** or **File-Extract folder**.\n\n### Export Assets\n\nuse **Export** menu.\n\n### Export Model\n\nExport model from \"Scene Hierarchy\" using the **Model** menu.\n\nExport Animator from \"Asset List\" using the **Export** menu.\n\n#### With AnimationClip\n\nSelect model from \"Scene Hierarchy\" then select the AnimationClip from \"Asset List\", using **Model-Export selected objects with AnimationClip** to export.\n\nExport Animator will export bound AnimationClip or use **Ctrl** to select Animator and AnimationClip from \"Asset List\", using **Export-Export Animator with selected AnimationClip** to export.\n\n### Export MonoBehaviour\n\nWhen you select an asset of the MonoBehaviour type for the first time, AssetStudio will ask you the directory where the assembly is located, please select the directory where the assembly is located, such as the `Managed` folder.\n\n#### For Il2Cpp\n\nFirst, use my another program [Il2CppDumper](https://github.com/Perfare/Il2CppDumper) to generate dummy dll, then when using AssetStudio to select the assembly directory, select the dummy dll folder.\n\n## Build\n\n* Visual Studio 2022 or newer\n* **AssetStudioFBXNative** uses [FBX SDK 2020.2.1](https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2020-2-1), before building, you need to install the FBX SDK and modify the project file, change include directory and library directory to point to the FBX SDK directory\n\n## Open source libraries used\n\n### Texture2DDecoder\n* [Ishotihadus/mikunyan](https://github.com/Ishotihadus/mikunyan)\n* [BinomialLLC/crunch](https://github.com/BinomialLLC/crunch)\n* [Unity-Technologies/crunch](https://github.com/Unity-Technologies/crunch/tree/unity)\n"
  },
  {
    "path": "Texture2DDecoderNative/Texture2DDecoderNative.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"winres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// Language neutral resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)\nLANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL\n#pragma code_page(65001)\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE \nBEGIN\n    \"#include \"\"winres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION 1,0,0,1\n PRODUCTVERSION 1,0,0,1\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x2L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"000004b0\"\n        BEGIN\n            VALUE \"FileDescription\", \"Texture2DDecoderNative\"\n            VALUE \"FileVersion\", \"1.0.0.1\"\n            VALUE \"InternalName\", \"Texture2DDecoderNative.dll\"\n            VALUE \"LegalCopyright\", \"Copyright (C) Perfare 2020; Copyright (C) hozuki 2020\"\n            VALUE \"OriginalFilename\", \"Texture2DDecoderNative.dll\"\n            VALUE \"ProductName\", \"Texture2DDecoderNative\"\n            VALUE \"ProductVersion\", \"1.0.0.1\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x0, 1200\n    END\nEND\n\n#endif    // Language neutral resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "Texture2DDecoderNative/Texture2DDecoderNative.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"astc.h\" />\n    <ClInclude Include=\"atc.h\" />\n    <ClInclude Include=\"bcn.h\" />\n    <ClInclude Include=\"bool32_t.h\" />\n    <ClInclude Include=\"color.h\" />\n    <ClInclude Include=\"crunch.h\" />\n    <ClInclude Include=\"crunch\\crnlib.h\" />\n    <ClInclude Include=\"crunch\\crn_decomp.h\" />\n    <ClInclude Include=\"dllexport.h\" />\n    <ClInclude Include=\"endianness.h\" />\n    <ClInclude Include=\"etc.h\" />\n    <ClInclude Include=\"fp16.h\" />\n    <ClInclude Include=\"fp16\\bitcasts.h\" />\n    <ClInclude Include=\"fp16\\fp16.h\" />\n    <ClInclude Include=\"pvrtc.h\" />\n    <ClInclude Include=\"resource.h\" />\n    <ClInclude Include=\"unitycrunch.h\" />\n    <ClInclude Include=\"unitycrunch\\crnlib.h\" />\n    <ClInclude Include=\"unitycrunch\\crn_decomp.h\" />\n    <ClInclude Include=\"unitycrunch\\crn_defs.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"astc.cpp\" />\n    <ClCompile Include=\"atc.cpp\" />\n    <ClCompile Include=\"bcn.cpp\" />\n    <ClCompile Include=\"crunch.cpp\" />\n    <ClCompile Include=\"dllmain.cpp\" />\n    <ClCompile Include=\"etc.cpp\" />\n    <ClCompile Include=\"pvrtc.cpp\" />\n    <ClCompile Include=\"unitycrunch.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"cpp.hint\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"Texture2DDecoderNative.rc\" />\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>16.0</VCProjectVersion>\n    <Keyword>Win32Proj</Keyword>\n    <ProjectGuid>{29356642-c46e-4144-83d8-22dc09d0d7fd}</ProjectGuid>\n    <RootNamespace>Texture2DDecoderNative</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n    <OutDir>bin\\$(Platform)\\$(Configuration)\\</OutDir>\n    <IntDir>obj\\$(Platform)\\$(Configuration)\\</IntDir>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_T2D_DLL;WIN32;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_T2D_DLL;WIN32;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_T2D_DLL;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_T2D_DLL;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n  <Target Name=\"AfterBuild\">\n    <MSBuild Condition=\" '$(Platform)' == 'Win32' \" Projects=\"$(MSBuildProjectFile)\" Properties=\"Platform=x64;PlatFormTarget=x64\" RunEachTargetSeparately=\"true\" />\n  </Target>\n</Project>"
  },
  {
    "path": "Texture2DDecoderNative/Texture2DDecoderNative.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"源文件\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"头文件\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"资源文件\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"pvrtc.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"unitycrunch.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"crunch\\crnlib.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"crunch\\crn_decomp.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"fp16\\bitcasts.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"fp16\\fp16.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"unitycrunch\\crnlib.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"unitycrunch\\crn_decomp.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"unitycrunch\\crn_defs.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"astc.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"atc.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"bcn.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"color.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"crunch.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"endianness.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"etc.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"fp16.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"dllexport.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"bool32_t.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"resource.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"unitycrunch.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"astc.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"atc.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bcn.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crunch.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"etc.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"pvrtc.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"dllmain.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"cpp.hint\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"Texture2DDecoderNative.rc\">\n      <Filter>资源文件</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "Texture2DDecoderNative/astc.cpp",
    "content": "#include \"astc.h\"\n#include <math.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"color.h\"\n#include \"fp16.h\"\n\nstatic const int BitReverseTable[] = {\n  0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48,\n  0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4,\n  0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C,\n  0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2,\n  0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A,\n  0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E,\n  0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21,\n  0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,\n  0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55,\n  0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD,\n  0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B,\n  0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7,\n  0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F,\n  0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF};\n\nstatic const int WeightPrecTableA[] = {0, 0, 0, 3, 0, 5, 3, 0, 0, 0, 5, 3, 0, 5, 3, 0};\nstatic const int WeightPrecTableB[] = {0, 0, 1, 0, 2, 0, 1, 3, 0, 0, 1, 2, 4, 2, 3, 5};\n\nstatic const int CemTableA[] = {0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 5, 0, 3, 0, 0};\nstatic const int CemTableB[] = {8, 6, 5, 7, 5, 4, 6, 4, 3, 5, 3, 2, 4, 2, 1, 3, 1, 2, 1};\n\nstatic inline uint_fast8_t bit_reverse_u8(const uint_fast8_t c, const int bits) {\n    return BitReverseTable[c] >> (8 - bits);\n}\n\nstatic inline uint_fast64_t bit_reverse_u64(const uint_fast64_t d, const int bits) {\n    uint_fast64_t ret = (uint_fast64_t)BitReverseTable[d & 0xff] << 56 |\n      (uint_fast64_t)BitReverseTable[d >> 8 & 0xff] << 48 | (uint_fast64_t)BitReverseTable[d >> 16 & 0xff] << 40 |\n      (uint_fast64_t)BitReverseTable[d >> 24 & 0xff] << 32 | (uint_fast32_t)BitReverseTable[d >> 32 & 0xff] << 24 |\n      (uint_fast32_t)BitReverseTable[d >> 40 & 0xff] << 16 | (uint_fast16_t)BitReverseTable[d >> 48 & 0xff] << 8 |\n      BitReverseTable[d >> 56 & 0xff];\n    return ret >> (64 - bits);\n}\n\nstatic inline int getbits(const uint8_t *buf, const int bit, const int len) {\n    return (*(int *)(buf + bit / 8) >> (bit % 8)) & ((1 << len) - 1);\n}\n\nstatic inline uint_fast64_t getbits64(const uint8_t *buf, const int bit, const int len) {\n    uint_fast64_t mask = len == 64 ? 0xffffffffffffffff : (1ull << len) - 1;\n    if (len < 1)\n        return 0;\n    else if (bit >= 64)\n        return (*(uint_fast64_t *)(buf + 8)) >> (bit - 64) & mask;\n    else if (bit <= 0)\n        return (*(uint_fast64_t *)buf) << -bit & mask;\n    else if (bit + len <= 64)\n        return (*(uint_fast64_t *)buf) >> bit & mask;\n    else\n        return ((*(uint_fast64_t *)buf) >> bit | *(uint_fast64_t *)(buf + 8) << (64 - bit)) & mask;\n}\n\nstatic inline uint16_t u8ptr_to_u16(const uint8_t *ptr) {\n    return lton16(*(uint16_t *)ptr);\n}\n\nstatic inline uint_fast8_t clamp(const int n) {\n    return n < 0 ? 0 : n > 255 ? 255 : n;\n}\n\nstatic inline void bit_transfer_signed(int *a, int *b) {\n    *b = (*b >> 1) | (*a & 0x80);\n    *a = (*a >> 1) & 0x3f;\n    if (*a & 0x20)\n        *a -= 0x40;\n}\n\nstatic inline void set_endpoint(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) {\n    endpoint[0] = r1;\n    endpoint[1] = g1;\n    endpoint[2] = b1;\n    endpoint[3] = a1;\n    endpoint[4] = r2;\n    endpoint[5] = g2;\n    endpoint[6] = b2;\n    endpoint[7] = a2;\n}\n\nstatic inline void set_endpoint_clamp(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) {\n    endpoint[0] = clamp(r1);\n    endpoint[1] = clamp(g1);\n    endpoint[2] = clamp(b1);\n    endpoint[3] = clamp(a1);\n    endpoint[4] = clamp(r2);\n    endpoint[5] = clamp(g2);\n    endpoint[6] = clamp(b2);\n    endpoint[7] = clamp(a2);\n}\n\nstatic inline void set_endpoint_blue(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) {\n    endpoint[0] = (r1 + b1) >> 1;\n    endpoint[1] = (g1 + b1) >> 1;\n    endpoint[2] = b1;\n    endpoint[3] = a1;\n    endpoint[4] = (r2 + b2) >> 1;\n    endpoint[5] = (g2 + b2) >> 1;\n    endpoint[6] = b2;\n    endpoint[7] = a2;\n}\n\nstatic inline void set_endpoint_blue_clamp(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2,\n                                           int a2) {\n    endpoint[0] = clamp((r1 + b1) >> 1);\n    endpoint[1] = clamp((g1 + b1) >> 1);\n    endpoint[2] = clamp(b1);\n    endpoint[3] = clamp(a1);\n    endpoint[4] = clamp((r2 + b2) >> 1);\n    endpoint[5] = clamp((g2 + b2) >> 1);\n    endpoint[6] = clamp(b2);\n    endpoint[7] = clamp(a2);\n}\n\nstatic inline uint_fast16_t clamp_hdr(const int n) {\n    return n < 0 ? 0 : n > 0xfff ? 0xfff : n;\n}\n\nstatic inline void set_endpoint_hdr(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2) {\n    endpoint[0] = r1;\n    endpoint[1] = g1;\n    endpoint[2] = b1;\n    endpoint[3] = a1;\n    endpoint[4] = r2;\n    endpoint[5] = g2;\n    endpoint[6] = b2;\n    endpoint[7] = a2;\n}\n\nstatic inline void set_endpoint_hdr_clamp(int endpoint[8], int r1, int g1, int b1, int a1, int r2, int g2, int b2,\n                                          int a2) {\n    endpoint[0] = clamp_hdr(r1);\n    endpoint[1] = clamp_hdr(g1);\n    endpoint[2] = clamp_hdr(b1);\n    endpoint[3] = clamp_hdr(a1);\n    endpoint[4] = clamp_hdr(r2);\n    endpoint[5] = clamp_hdr(g2);\n    endpoint[6] = clamp_hdr(b2);\n    endpoint[7] = clamp_hdr(a2);\n}\n\ntypedef uint_fast8_t (*t_select_folor_func_ptr)(int, int, int);\n\nstatic uint_fast8_t select_color(int v0, int v1, int weight) {\n    return ((((v0 << 8 | v0) * (64 - weight) + (v1 << 8 | v1) * weight + 32) >> 6) * 255 + 32768) / 65536;\n}\n\nstatic uint_fast8_t select_color_hdr(int v0, int v1, int weight) {\n    uint16_t c = ((v0 << 4) * (64 - weight) + (v1 << 4) * weight + 32) >> 6;\n    uint16_t m = c & 0x7ff;\n    if (m < 512)\n        m *= 3;\n    else if (m < 1536)\n        m = 4 * m - 512;\n    else\n        m = 5 * m - 2048;\n    float f = fp16_ieee_to_fp32_value((c >> 1 & 0x7c00) | m >> 3);\n    return isfinite(f) ? clamp(roundf(f * 255)) : 255;\n}\n\nstatic inline uint8_t f32_to_u8(const float f) {\n    float c = roundf(f * 255);\n    if (c < 0)\n        return 0;\n    else if (c > 255)\n        return 255;\n    else\n        return c;\n}\n\nstatic inline uint8_t f16ptr_to_u8(const uint8_t *ptr) {\n    return f32_to_u8(fp16_ieee_to_fp32_value(lton16(*(uint16_t *)ptr)));\n}\n\ntypedef struct {\n    int bw;\n    int bh;\n    int width;\n    int height;\n    int part_num;\n    int dual_plane;\n    int plane_selector;\n    int weight_range;\n    int weight_num;\n    int cem[4];\n    int cem_range;\n    int endpoint_value_num;\n    int endpoints[4][8];\n    int weights[144][2];\n    int partition[144];\n} BlockData;\n\ntypedef struct {\n    int bits;\n    int nonbits;\n} IntSeqData;\n\nvoid decode_intseq(const uint8_t *buf, int offset, const int a, const int b, const int count, const int reverse,\n                   IntSeqData *out) {\n    static int mt[] = {0, 2, 4, 5, 7};\n    static int mq[] = {0, 3, 5};\n    static int TritsTable[5][256] = {\n      {0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 0, 0,\n       1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 1, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1,\n       2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2,\n       2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0,\n       0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0,\n       1, 2, 2, 0, 1, 2, 1, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1,\n       2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2},\n      {0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,\n       1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2,\n       2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2,\n       0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1,\n       1, 1, 1, 1, 2, 2, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2,\n       2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2,\n       2, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1},\n      {0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0,\n       0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0,\n       0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2,\n       2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2,\n       1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1,\n       1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1,\n       1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2},\n      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1,\n       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n       0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n       1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n       2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2},\n      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0,\n       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n       1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n       1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,\n       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}};\n    static int QuintsTable[3][128] = {\n      {0, 1, 2, 3, 4, 0, 4, 4, 0, 1, 2, 3, 4, 1, 4, 4, 0, 1, 2, 3, 4, 2, 4, 4, 0, 1, 2, 3, 4, 3, 4, 4,\n       0, 1, 2, 3, 4, 0, 4, 0, 0, 1, 2, 3, 4, 1, 4, 1, 0, 1, 2, 3, 4, 2, 4, 2, 0, 1, 2, 3, 4, 3, 4, 3,\n       0, 1, 2, 3, 4, 0, 2, 3, 0, 1, 2, 3, 4, 1, 2, 3, 0, 1, 2, 3, 4, 2, 2, 3, 0, 1, 2, 3, 4, 3, 2, 3,\n       0, 1, 2, 3, 4, 0, 0, 1, 0, 1, 2, 3, 4, 1, 0, 1, 0, 1, 2, 3, 4, 2, 0, 1, 0, 1, 2, 3, 4, 3, 0, 1},\n      {0, 0, 0, 0, 0, 4, 4, 4, 1, 1, 1, 1, 1, 4, 4, 4, 2, 2, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, 3, 4, 4, 4,\n       0, 0, 0, 0, 0, 4, 0, 4, 1, 1, 1, 1, 1, 4, 1, 4, 2, 2, 2, 2, 2, 4, 2, 4, 3, 3, 3, 3, 3, 4, 3, 4,\n       0, 0, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 1, 4, 1, 1, 2, 2, 2, 2, 2, 4, 2, 2, 3, 3, 3, 3, 3, 4, 3, 3,\n       0, 0, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 1, 4, 1, 1, 2, 2, 2, 2, 2, 4, 2, 2, 3, 3, 3, 3, 3, 4, 3, 3},\n      {0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 3, 4,\n       1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4,\n       2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4,\n       3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4}};\n\n    if (count <= 0)\n        return;\n\n    int n = 0;\n\n    if (a == 3) {\n        int mask = (1 << b) - 1;\n        int block_count = (count + 4) / 5;\n        int last_block_count = (count + 4) % 5 + 1;\n        int block_size = 8 + 5 * b;\n        int last_block_size = (block_size * last_block_count + 4) / 5;\n\n        if (reverse) {\n            for (int i = 0, p = offset; i < block_count; i++, p -= block_size) {\n                int now_size = (i < block_count - 1) ? block_size : last_block_size;\n                uint_fast64_t d = bit_reverse_u64(getbits64(buf, p - now_size, now_size), now_size);\n                int x =\n                  (d >> b & 3) | (d >> b * 2 & 0xc) | (d >> b * 3 & 0x10) | (d >> b * 4 & 0x60) | (d >> b * 5 & 0x80);\n                for (int j = 0; j < 5 && n < count; j++, n++)\n                    out[n] = { static_cast<int>(d >> (mt[j] + b * j) & mask), TritsTable[j][x]};\n            }\n        } else {\n            for (int i = 0, p = offset; i < block_count; i++, p += block_size) {\n                uint_fast64_t d = getbits64(buf, p, (i < block_count - 1) ? block_size : last_block_size);\n                int x =\n                  (d >> b & 3) | (d >> b * 2 & 0xc) | (d >> b * 3 & 0x10) | (d >> b * 4 & 0x60) | (d >> b * 5 & 0x80);\n                for (int j = 0; j < 5 && n < count; j++, n++)\n                    out[n] = { static_cast<int>(d >> (mt[j] + b * j) & mask), TritsTable[j][x]};\n            }\n        }\n    } else if (a == 5) {\n        int mask = (1 << b) - 1;\n        int block_count = (count + 2) / 3;\n        int last_block_count = (count + 2) % 3 + 1;\n        int block_size = 7 + 3 * b;\n        int last_block_size = (block_size * last_block_count + 2) / 3;\n\n        if (reverse) {\n            for (int i = 0, p = offset; i < block_count; i++, p -= block_size) {\n                int now_size = (i < block_count - 1) ? block_size : last_block_size;\n                uint_fast64_t d = bit_reverse_u64(getbits64(buf, p - now_size, now_size), now_size);\n                int x = (d >> b & 7) | (d >> b * 2 & 0x18) | (d >> b * 3 & 0x60);\n                for (int j = 0; j < 3 && n < count; j++, n++)\n                    out[n] = { static_cast<int>(d >> (mq[j] + b * j) & mask), QuintsTable[j][x]};\n            }\n        } else {\n            for (int i = 0, p = offset; i < block_count; i++, p += block_size) {\n                uint_fast64_t d = getbits64(buf, p, (i < block_count - 1) ? block_size : last_block_size);\n                int x = (d >> b & 7) | (d >> b * 2 & 0x18) | (d >> b * 3 & 0x60);\n                for (int j = 0; j < 3 && n < count; j++, n++)\n                    out[n] = { static_cast<int>(d >> (mq[j] + b * j) & mask), QuintsTable[j][x]};\n            }\n        }\n    } else {\n        if (reverse)\n            for (int p = offset - b; n < count; n++, p -= b)\n                out[n] = {bit_reverse_u8(getbits(buf, p, b), b), 0};\n        else\n            for (int p = offset; n < count; n++, p += b)\n                out[n] = {getbits(buf, p, b), 0};\n    }\n}\n\nvoid decode_block_params(const uint8_t *buf, BlockData *block_data) {\n    block_data->dual_plane = !!(buf[1] & 4);\n    block_data->weight_range = (buf[0] >> 4 & 1) | (buf[1] << 2 & 8);\n\n    if (buf[0] & 3) {\n        block_data->weight_range |= buf[0] << 1 & 6;\n        switch (buf[0] & 0xc) {\n        case 0:\n            block_data->width = (u8ptr_to_u16(buf) >> 7 & 3) + 4;\n            block_data->height = (buf[0] >> 5 & 3) + 2;\n            break;\n        case 4:\n            block_data->width = (u8ptr_to_u16(buf) >> 7 & 3) + 8;\n            block_data->height = (buf[0] >> 5 & 3) + 2;\n            break;\n        case 8:\n            block_data->width = (buf[0] >> 5 & 3) + 2;\n            block_data->height = (u8ptr_to_u16(buf) >> 7 & 3) + 8;\n            break;\n        case 12:\n            if (buf[1] & 1) {\n                block_data->width = (buf[0] >> 7 & 1) + 2;\n                block_data->height = (buf[0] >> 5 & 3) + 2;\n            } else {\n                block_data->width = (buf[0] >> 5 & 3) + 2;\n                block_data->height = (buf[0] >> 7 & 1) + 6;\n            }\n            break;\n        }\n    } else {\n        block_data->weight_range |= buf[0] >> 1 & 6;\n        switch (u8ptr_to_u16(buf) & 0x180) {\n        case 0:\n            block_data->width = 12;\n            block_data->height = (buf[0] >> 5 & 3) + 2;\n            break;\n        case 0x80:\n            block_data->width = (buf[0] >> 5 & 3) + 2;\n            block_data->height = 12;\n            break;\n        case 0x100:\n            block_data->width = (buf[0] >> 5 & 3) + 6;\n            block_data->height = (buf[1] >> 1 & 3) + 6;\n            block_data->dual_plane = 0;\n            block_data->weight_range &= 7;\n            break;\n        case 0x180:\n            block_data->width = (buf[0] & 0x20) ? 10 : 6;\n            block_data->height = (buf[0] & 0x20) ? 6 : 10;\n            break;\n        }\n    }\n\n    block_data->part_num = (buf[1] >> 3 & 3) + 1;\n\n    block_data->weight_num = block_data->width * block_data->height;\n    if (block_data->dual_plane)\n        block_data->weight_num *= 2;\n\n    int weight_bits, config_bits, cem_base = 0;\n\n    switch (WeightPrecTableA[block_data->weight_range]) {\n    case 3:\n        weight_bits =\n          block_data->weight_num * WeightPrecTableB[block_data->weight_range] + (block_data->weight_num * 8 + 4) / 5;\n        break;\n    case 5:\n        weight_bits =\n          block_data->weight_num * WeightPrecTableB[block_data->weight_range] + (block_data->weight_num * 7 + 2) / 3;\n        break;\n    default:\n        weight_bits = block_data->weight_num * WeightPrecTableB[block_data->weight_range];\n    }\n\n    if (block_data->part_num == 1) {\n        block_data->cem[0] = u8ptr_to_u16(buf + 1) >> 5 & 0xf;\n        config_bits = 17;\n    } else {\n        cem_base = u8ptr_to_u16(buf + 2) >> 7 & 3;\n        if (cem_base == 0) {\n            int cem = buf[3] >> 1 & 0xf;\n            for (int i = 0; i < block_data->part_num; i++)\n                block_data->cem[i] = cem;\n            config_bits = 29;\n        } else {\n            for (int i = 0; i < block_data->part_num; i++)\n                block_data->cem[i] = ((buf[3] >> (i + 1) & 1) + cem_base - 1) << 2;\n            switch (block_data->part_num) {\n            case 2:\n                block_data->cem[0] |= buf[3] >> 3 & 3;\n                block_data->cem[1] |= getbits(buf, 126 - weight_bits, 2);\n                break;\n            case 3:\n                block_data->cem[0] |= buf[3] >> 4 & 1;\n                block_data->cem[0] |= getbits(buf, 122 - weight_bits, 2) & 2;\n                block_data->cem[1] |= getbits(buf, 124 - weight_bits, 2);\n                block_data->cem[2] |= getbits(buf, 126 - weight_bits, 2);\n                break;\n            case 4:\n                for (int i = 0; i < 4; i++)\n                    block_data->cem[i] |= getbits(buf, 120 + i * 2 - weight_bits, 2);\n                break;\n            }\n            config_bits = 25 + block_data->part_num * 3;\n        }\n    }\n\n    if (block_data->dual_plane) {\n        config_bits += 2;\n        block_data->plane_selector =\n          getbits(buf, cem_base ? 130 - weight_bits - block_data->part_num * 3 : 126 - weight_bits, 2);\n    }\n\n    int remain_bits = 128 - config_bits - weight_bits;\n\n    block_data->endpoint_value_num = 0;\n    for (int i = 0; i < block_data->part_num; i++)\n        block_data->endpoint_value_num += (block_data->cem[i] >> 1 & 6) + 2;\n\n    for (int i = 0, endpoint_bits; i < (int)(sizeof(CemTableA) / sizeof(int)); i++) {\n        switch (CemTableA[i]) {\n        case 3:\n            endpoint_bits =\n              block_data->endpoint_value_num * CemTableB[i] + (block_data->endpoint_value_num * 8 + 4) / 5;\n            break;\n        case 5:\n            endpoint_bits =\n              block_data->endpoint_value_num * CemTableB[i] + (block_data->endpoint_value_num * 7 + 2) / 3;\n            break;\n        default:\n            endpoint_bits = block_data->endpoint_value_num * CemTableB[i];\n        }\n\n        if (endpoint_bits <= remain_bits) {\n            block_data->cem_range = i;\n            break;\n        }\n    }\n}\n\nvoid decode_endpoints_hdr7(int *endpoints, int *v) {\n    int modeval = (v[2] >> 4 & 0x8) | (v[1] >> 5 & 0x4) | (v[0] >> 6);\n    int major_component, mode;\n    if ((modeval & 0xc) != 0xc) {\n        major_component = modeval >> 2;\n        mode = modeval & 3;\n    } else if (modeval != 0xf) {\n        major_component = modeval & 3;\n        mode = 4;\n    } else {\n        major_component = 0;\n        mode = 5;\n    }\n    int c[] = {v[0] & 0x3f, v[1] & 0x1f, v[2] & 0x1f, v[3] & 0x1f};\n\n    switch (mode) {\n    case 0:\n        c[3] |= v[3] & 0x60;\n        c[0] |= v[3] >> 1 & 0x40;\n        c[0] |= v[2] << 1 & 0x80;\n        c[0] |= v[1] << 3 & 0x300;\n        c[0] |= v[2] << 5 & 0x400;\n        c[0] <<= 1;\n        c[1] <<= 1;\n        c[2] <<= 1;\n        c[3] <<= 1;\n        break;\n    case 1:\n        c[1] |= v[1] & 0x20;\n        c[2] |= v[2] & 0x20;\n        c[0] |= v[3] >> 1 & 0x40;\n        c[0] |= v[2] << 1 & 0x80;\n        c[0] |= v[1] << 2 & 0x100;\n        c[0] |= v[3] << 4 & 0x600;\n        c[0] <<= 1;\n        c[1] <<= 1;\n        c[2] <<= 1;\n        c[3] <<= 1;\n        break;\n    case 2:\n        c[3] |= v[3] & 0xe0;\n        c[0] |= v[2] << 1 & 0xc0;\n        c[0] |= v[1] << 3 & 0x300;\n        c[0] <<= 2;\n        c[1] <<= 2;\n        c[2] <<= 2;\n        c[3] <<= 2;\n        break;\n    case 3:\n        c[1] |= v[1] & 0x20;\n        c[2] |= v[2] & 0x20;\n        c[3] |= v[3] & 0x60;\n        c[0] |= v[3] >> 1 & 0x40;\n        c[0] |= v[2] << 1 & 0x80;\n        c[0] |= v[1] << 2 & 0x100;\n        c[0] <<= 3;\n        c[1] <<= 3;\n        c[2] <<= 3;\n        c[3] <<= 3;\n        break;\n    case 4:\n        c[1] |= v[1] & 0x60;\n        c[2] |= v[2] & 0x60;\n        c[3] |= v[3] & 0x20;\n        c[0] |= v[3] >> 1 & 0x40;\n        c[0] |= v[3] << 1 & 0x80;\n        c[0] <<= 4;\n        c[1] <<= 4;\n        c[2] <<= 4;\n        c[3] <<= 4;\n        break;\n    case 5:\n        c[1] |= v[1] & 0x60;\n        c[2] |= v[2] & 0x60;\n        c[3] |= v[3] & 0x60;\n        c[0] |= v[3] >> 1 & 0x40;\n        c[0] <<= 5;\n        c[1] <<= 5;\n        c[2] <<= 5;\n        c[3] <<= 5;\n        break;\n    }\n    if (mode != 5) {\n        c[1] = c[0] - c[1];\n        c[2] = c[0] - c[2];\n    }\n    if (major_component == 1)\n        set_endpoint_hdr_clamp(endpoints, c[1] - c[3], c[0] - c[3], c[2] - c[3], 0x780, c[1], c[0], c[2], 0x780);\n    else if (major_component == 2)\n        set_endpoint_hdr_clamp(endpoints, c[2] - c[3], c[1] - c[3], c[0] - c[3], 0x780, c[2], c[1], c[0], 0x780);\n    else\n        set_endpoint_hdr_clamp(endpoints, c[0] - c[3], c[1] - c[3], c[2] - c[3], 0x780, c[0], c[1], c[2], 0x780);\n}\n\nvoid decode_endpoints_hdr11(int *endpoints, int *v, int alpha1, int alpha2) {\n    int major_component = (v[4] >> 7) | (v[5] >> 6 & 2);\n    if (major_component == 3) {\n        set_endpoint_hdr(endpoints, v[0] << 4, v[2] << 4, v[4] << 5 & 0xfe0, alpha1, v[1] << 4, v[3] << 4,\n                         v[5] << 5 & 0xfe0, alpha2);\n        return;\n    }\n    int mode = (v[1] >> 7) | (v[2] >> 6 & 2) | (v[3] >> 5 & 4);\n    int va = v[0] | (v[1] << 2 & 0x100);\n    int vb0 = v[2] & 0x3f, vb1 = v[3] & 0x3f;\n    int vc = v[1] & 0x3f;\n    int16_t vd0, vd1;\n\n    switch (mode) {\n    case 0:\n    case 2:\n        vd0 = v[4] & 0x7f;\n        if (vd0 & 0x40)\n            vd0 |= 0xff80;\n        vd1 = v[5] & 0x7f;\n        if (vd1 & 0x40)\n            vd1 |= 0xff80;\n        break;\n    case 1:\n    case 3:\n    case 5:\n    case 7:\n        vd0 = v[4] & 0x3f;\n        if (vd0 & 0x20)\n            vd0 |= 0xffc0;\n        vd1 = v[5] & 0x3f;\n        if (vd1 & 0x20)\n            vd1 |= 0xffc0;\n        break;\n    default:\n        vd0 = v[4] & 0x1f;\n        if (vd0 & 0x10)\n            vd0 |= 0xffe0;\n        vd1 = v[5] & 0x1f;\n        if (vd1 & 0x10)\n            vd1 |= 0xffe0;\n        break;\n    }\n\n    switch (mode) {\n    case 0:\n        vb0 |= v[2] & 0x40;\n        vb1 |= v[3] & 0x40;\n        break;\n    case 1:\n        vb0 |= v[2] & 0x40;\n        vb1 |= v[3] & 0x40;\n        vb0 |= v[4] << 1 & 0x80;\n        vb1 |= v[5] << 1 & 0x80;\n        break;\n    case 2:\n        va |= v[2] << 3 & 0x200;\n        vc |= v[3] & 0x40;\n        break;\n    case 3:\n        va |= v[4] << 3 & 0x200;\n        vc |= v[5] & 0x40;\n        vb0 |= v[2] & 0x40;\n        vb1 |= v[3] & 0x40;\n        break;\n    case 4:\n        va |= v[4] << 4 & 0x200;\n        va |= v[5] << 5 & 0x400;\n        vb0 |= v[2] & 0x40;\n        vb1 |= v[3] & 0x40;\n        vb0 |= v[4] << 1 & 0x80;\n        vb1 |= v[5] << 1 & 0x80;\n        break;\n    case 5:\n        va |= v[2] << 3 & 0x200;\n        va |= v[3] << 4 & 0x400;\n        vc |= v[5] & 0x40;\n        vc |= v[4] << 1 & 0x80;\n        break;\n    case 6:\n        va |= v[4] << 4 & 0x200;\n        va |= v[5] << 5 & 0x400;\n        va |= v[4] << 5 & 0x800;\n        vc |= v[5] & 0x40;\n        vb0 |= v[2] & 0x40;\n        vb1 |= v[3] & 0x40;\n        break;\n    case 7:\n        va |= v[2] << 3 & 0x200;\n        va |= v[3] << 4 & 0x400;\n        va |= v[4] << 5 & 0x800;\n        vc |= v[5] & 0x40;\n        break;\n    }\n\n    int shamt = (mode >> 1) ^ 3;\n    va <<= shamt;\n    vb0 <<= shamt;\n    vb1 <<= shamt;\n    vc <<= shamt;\n    int mult = 1 << shamt;\n    vd0 *= mult;\n    vd1 *= mult;\n\n    if (major_component == 1)\n        set_endpoint_hdr_clamp(endpoints, va - vb0 - vc - vd0, va - vc, va - vb1 - vc - vd1, alpha1, va - vb0, va,\n                               va - vb1, alpha2);\n    else if (major_component == 2)\n        set_endpoint_hdr_clamp(endpoints, va - vb1 - vc - vd1, va - vb0 - vc - vd0, va - vc, alpha1, va - vb1, va - vb0,\n                               va, alpha2);\n    else\n        set_endpoint_hdr_clamp(endpoints, va - vc, va - vb0 - vc - vd0, va - vb1 - vc - vd1, alpha1, va, va - vb0,\n                               va - vb1, alpha2);\n}\n\nvoid decode_endpoints(const uint8_t *buf, BlockData *data) {\n    static const int TritsTable[] = {0, 204, 93, 44, 22, 11, 5};\n    static const int QuintsTable[] = {0, 113, 54, 26, 13, 6};\n    IntSeqData seq[32];\n    int ev[32];\n    decode_intseq(buf, data->part_num == 1 ? 17 : 29, CemTableA[data->cem_range], CemTableB[data->cem_range],\n                  data->endpoint_value_num, 0, seq);\n\n    switch (CemTableA[data->cem_range]) {\n    case 3:\n        for (int i = 0, b, c = TritsTable[CemTableB[data->cem_range]]; i < data->endpoint_value_num; i++) {\n            int a = (seq[i].bits & 1) * 0x1ff;\n            int x = seq[i].bits >> 1;\n            switch (CemTableB[data->cem_range]) {\n            case 1:\n                b = 0;\n                break;\n            case 2:\n                b = 0b100010110 * x;\n                break;\n            case 3:\n                b = x << 7 | x << 2 | x;\n                break;\n            case 4:\n                b = x << 6 | x;\n                break;\n            case 5:\n                b = x << 5 | x >> 2;\n                break;\n            case 6:\n                b = x << 4 | x >> 4;\n                break;\n            }\n            ev[i] = (a & 0x80) | ((seq[i].nonbits * c + b) ^ a) >> 2;\n        }\n        break;\n    case 5:\n        for (int i = 0, b, c = QuintsTable[CemTableB[data->cem_range]]; i < data->endpoint_value_num; i++) {\n            int a = (seq[i].bits & 1) * 0x1ff;\n            int x = seq[i].bits >> 1;\n            switch (CemTableB[data->cem_range]) {\n            case 1:\n                b = 0;\n                break;\n            case 2:\n                b = 0b100001100 * x;\n                break;\n            case 3:\n                b = x << 7 | x << 1 | x >> 1;\n                break;\n            case 4:\n                b = x << 6 | x >> 1;\n                break;\n            case 5:\n                b = x << 5 | x >> 3;\n                break;\n            }\n            ev[i] = (a & 0x80) | ((seq[i].nonbits * c + b) ^ a) >> 2;\n        }\n        break;\n    default:\n        switch (CemTableB[data->cem_range]) {\n        case 1:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits * 0xff;\n            break;\n        case 2:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits * 0x55;\n            break;\n        case 3:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits << 5 | seq[i].bits << 2 | seq[i].bits >> 1;\n            break;\n        case 4:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits << 4 | seq[i].bits;\n            break;\n        case 5:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits << 3 | seq[i].bits >> 2;\n            break;\n        case 6:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits << 2 | seq[i].bits >> 4;\n            break;\n        case 7:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits << 1 | seq[i].bits >> 6;\n            break;\n        case 8:\n            for (int i = 0; i < data->endpoint_value_num; i++)\n                ev[i] = seq[i].bits;\n            break;\n        }\n    }\n\n    int *v = ev;\n    for (int cem = 0; cem < data->part_num; v += (data->cem[cem] / 4 + 1) * 2, cem++) {\n        switch (data->cem[cem]) {\n        case 0:\n            set_endpoint(data->endpoints[cem], v[0], v[0], v[0], 255, v[1], v[1], v[1], 255);\n            break;\n        case 1: {\n            int l0 = (v[0] >> 2) | (v[1] & 0xc0);\n            int l1 = clamp(l0 + (v[1] & 0x3f));\n            set_endpoint(data->endpoints[cem], l0, l0, l0, 255, l1, l1, l1, 255);\n        } break;\n        case 2: {\n            int y0, y1;\n            if (v[0] <= v[1]) {\n                y0 = v[0] << 4;\n                y1 = v[1] << 4;\n            } else {\n                y0 = (v[1] << 4) + 8;\n                y1 = (v[0] << 4) - 8;\n            }\n            set_endpoint_hdr(data->endpoints[cem], y0, y0, y0, 0x780, y1, y1, y1, 0x780);\n        } break;\n        case 3: {\n            int y0, d;\n            if (v[0] & 0x80) {\n                y0 = (v[1] & 0xe0) << 4 | (v[0] & 0x7f) << 2;\n                d = (v[1] & 0x1f) << 2;\n            } else {\n                y0 = (v[1] & 0xf0) << 4 | (v[0] & 0x7f) << 1;\n                d = (v[1] & 0x0f) << 1;\n            }\n            int y1 = clamp_hdr(y0 + d);\n            set_endpoint_hdr(data->endpoints[cem], y0, y0, y0, 0x780, y1, y1, y1, 0x780);\n        } break;\n        case 4:\n            set_endpoint(data->endpoints[cem], v[0], v[0], v[0], v[2], v[1], v[1], v[1], v[3]);\n            break;\n        case 5:\n            bit_transfer_signed(&v[1], &v[0]);\n            bit_transfer_signed(&v[3], &v[2]);\n            v[1] += v[0];\n            set_endpoint_clamp(data->endpoints[cem], v[0], v[0], v[0], v[2], v[1], v[1], v[1], v[2] + v[3]);\n            break;\n        case 6:\n            set_endpoint(data->endpoints[cem], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, 255, v[0], v[1],\n                         v[2], 255);\n            break;\n        case 7:\n            decode_endpoints_hdr7(data->endpoints[cem], v);\n            break;\n        case 8:\n            if (v[0] + v[2] + v[4] <= v[1] + v[3] + v[5])\n                set_endpoint(data->endpoints[cem], v[0], v[2], v[4], 255, v[1], v[3], v[5], 255);\n            else\n                set_endpoint_blue(data->endpoints[cem], v[1], v[3], v[5], 255, v[0], v[2], v[4], 255);\n            break;\n        case 9:\n            bit_transfer_signed(&v[1], &v[0]);\n            bit_transfer_signed(&v[3], &v[2]);\n            bit_transfer_signed(&v[5], &v[4]);\n            if (v[1] + v[3] + v[5] >= 0)\n                set_endpoint_clamp(data->endpoints[cem], v[0], v[2], v[4], 255, v[0] + v[1], v[2] + v[3], v[4] + v[5],\n                                   255);\n            else\n                set_endpoint_blue_clamp(data->endpoints[cem], v[0] + v[1], v[2] + v[3], v[4] + v[5], 255, v[0], v[2],\n                                        v[4], 255);\n            break;\n        case 10:\n            set_endpoint(data->endpoints[cem], v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, v[4], v[0], v[1],\n                         v[2], v[5]);\n            break;\n        case 11:\n            decode_endpoints_hdr11(data->endpoints[cem], v, 0x780, 0x780);\n            break;\n        case 12:\n            if (v[0] + v[2] + v[4] <= v[1] + v[3] + v[5])\n                set_endpoint(data->endpoints[cem], v[0], v[2], v[4], v[6], v[1], v[3], v[5], v[7]);\n            else\n                set_endpoint_blue(data->endpoints[cem], v[1], v[3], v[5], v[7], v[0], v[2], v[4], v[6]);\n            break;\n        case 13:\n            bit_transfer_signed(&v[1], &v[0]);\n            bit_transfer_signed(&v[3], &v[2]);\n            bit_transfer_signed(&v[5], &v[4]);\n            bit_transfer_signed(&v[7], &v[6]);\n            if (v[1] + v[3] + v[5] >= 0)\n                set_endpoint_clamp(data->endpoints[cem], v[0], v[2], v[4], v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5],\n                                   v[6] + v[7]);\n            else\n                set_endpoint_blue_clamp(data->endpoints[cem], v[0] + v[1], v[2] + v[3], v[4] + v[5], v[6] + v[7], v[0],\n                                        v[2], v[4], v[6]);\n            break;\n        case 14:\n            decode_endpoints_hdr11(data->endpoints[cem], v, v[6], v[7]);\n            break;\n        case 15: {\n            int mode = ((v[6] >> 7) & 1) | ((v[7] >> 6) & 2);\n            v[6] &= 0x7f;\n            v[7] &= 0x7f;\n            if (mode == 3) {\n                decode_endpoints_hdr11(data->endpoints[cem], v, v[6] << 5, v[7] << 5);\n            } else {\n                v[6] |= (v[7] << (mode + 1)) & 0x780;\n                v[7] = ((v[7] & (0x3f >> mode)) ^ (0x20 >> mode)) - (0x20 >> mode);\n                v[6] <<= 4 - mode;\n                v[7] <<= 4 - mode;\n                decode_endpoints_hdr11(data->endpoints[cem], v, v[6], clamp_hdr(v[6] + v[7]));\n            }\n        } break;\n        //default:\n        //    rb_raise(rb_eStandardError, \"Unsupported ASTC format\");\n        }\n    }\n}\n\nvoid decode_weights(const uint8_t *buf, BlockData *data) {\n    IntSeqData seq[128];\n    int wv[128] = {};\n    decode_intseq(buf, 128, WeightPrecTableA[data->weight_range], WeightPrecTableB[data->weight_range],\n                  data->weight_num, 1, seq);\n\n    if (WeightPrecTableA[data->weight_range] == 0) {\n        switch (WeightPrecTableB[data->weight_range]) {\n        case 1:\n            for (int i = 0; i < data->weight_num; i++)\n                wv[i] = seq[i].bits ? 63 : 0;\n            break;\n        case 2:\n            for (int i = 0; i < data->weight_num; i++)\n                wv[i] = seq[i].bits << 4 | seq[i].bits << 2 | seq[i].bits;\n            break;\n        case 3:\n            for (int i = 0; i < data->weight_num; i++)\n                wv[i] = seq[i].bits << 3 | seq[i].bits;\n            break;\n        case 4:\n            for (int i = 0; i < data->weight_num; i++)\n                wv[i] = seq[i].bits << 2 | seq[i].bits >> 2;\n            break;\n        case 5:\n            for (int i = 0; i < data->weight_num; i++)\n                wv[i] = seq[i].bits << 1 | seq[i].bits >> 4;\n            break;\n        }\n        for (int i = 0; i < data->weight_num; i++)\n            if (wv[i] > 32)\n                ++wv[i];\n    } else if (WeightPrecTableB[data->weight_range] == 0) {\n        int s = WeightPrecTableA[data->weight_range] == 3 ? 32 : 16;\n        for (int i = 0; i < data->weight_num; i++)\n            wv[i] = seq[i].nonbits * s;\n    } else {\n        if (WeightPrecTableA[data->weight_range] == 3) {\n            switch (WeightPrecTableB[data->weight_range]) {\n            case 1:\n                for (int i = 0; i < data->weight_num; i++)\n                    wv[i] = seq[i].nonbits * 50;\n                break;\n            case 2:\n                for (int i = 0; i < data->weight_num; i++) {\n                    wv[i] = seq[i].nonbits * 23;\n                    if (seq[i].bits & 2)\n                        wv[i] += 0b1000101;\n                }\n                break;\n            case 3:\n                for (int i = 0; i < data->weight_num; i++)\n                    wv[i] = seq[i].nonbits * 11 + ((seq[i].bits << 4 | seq[i].bits >> 1) & 0b1100011);\n                break;\n            }\n        } else if (WeightPrecTableA[data->weight_range] == 5) {\n            switch (WeightPrecTableB[data->weight_range]) {\n            case 1:\n                for (int i = 0; i < data->weight_num; i++)\n                    wv[i] = seq[i].nonbits * 28;\n                break;\n            case 2:\n                for (int i = 0; i < data->weight_num; i++) {\n                    wv[i] = seq[i].nonbits * 13;\n                    if (seq[i].bits & 2)\n                        wv[i] += 0b1000010;\n                }\n                break;\n            }\n        }\n        for (int i = 0; i < data->weight_num; i++) {\n            int a = (seq[i].bits & 1) * 0x7f;\n            wv[i] = (a & 0x20) | ((wv[i] ^ a) >> 2);\n            if (wv[i] > 32)\n                ++wv[i];\n        }\n    }\n\n    int ds = (1024 + data->bw / 2) / (data->bw - 1);\n    int dt = (1024 + data->bh / 2) / (data->bh - 1);\n    int pn = data->dual_plane ? 2 : 1;\n\n    for (int t = 0, i = 0; t < data->bh; t++) {\n        for (int s = 0; s < data->bw; s++, i++) {\n            int gs = (ds * s * (data->width - 1) + 32) >> 6;\n            int gt = (dt * t * (data->height - 1) + 32) >> 6;\n            int fs = gs & 0xf;\n            int ft = gt & 0xf;\n            int v = (gs >> 4) + (gt >> 4) * data->width;\n            int w11 = (fs * ft + 8) >> 4;\n            int w10 = ft - w11;\n            int w01 = fs - w11;\n            int w00 = 16 - fs - ft + w11;\n\n            for (int p = 0; p < pn; p++) {\n                int p00 = wv[v * pn + p];\n                int p01 = wv[(v + 1) * pn + p];\n                int p10 = wv[(v + data->width) * pn + p];\n                int p11 = wv[(v + data->width + 1) * pn + p];\n                data->weights[i][p] = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4;\n            }\n        }\n    }\n}\n\nvoid select_partition(const uint8_t *buf, BlockData *data) {\n    int small_block = data->bw * data->bh < 31;\n    int seed = (*(int *)buf >> 13 & 0x3ff) | (data->part_num - 1) << 10;\n\n    uint32_t rnum = seed;\n    rnum ^= rnum >> 15;\n    rnum -= rnum << 17;\n    rnum += rnum << 7;\n    rnum += rnum << 4;\n    rnum ^= rnum >> 5;\n    rnum += rnum << 16;\n    rnum ^= rnum >> 7;\n    rnum ^= rnum >> 3;\n    rnum ^= rnum << 6;\n    rnum ^= rnum >> 17;\n\n    int seeds[8];\n    for (int i = 0; i < 8; i++) {\n        seeds[i] = (rnum >> (i * 4)) & 0xF;\n        seeds[i] *= seeds[i];\n    }\n\n    int sh[2] = {seed & 2 ? 4 : 5, data->part_num == 3 ? 6 : 5};\n\n    if (seed & 1)\n        for (int i = 0; i < 8; i++)\n            seeds[i] >>= sh[i % 2];\n    else\n        for (int i = 0; i < 8; i++)\n            seeds[i] >>= sh[1 - i % 2];\n\n    if (small_block) {\n        for (int t = 0, i = 0; t < data->bh; t++) {\n            for (int s = 0; s < data->bw; s++, i++) {\n                int x = s << 1;\n                int y = t << 1;\n                int a = (seeds[0] * x + seeds[1] * y + (rnum >> 14)) & 0x3f;\n                int b = (seeds[2] * x + seeds[3] * y + (rnum >> 10)) & 0x3f;\n                int c = data->part_num < 3 ? 0 : (seeds[4] * x + seeds[5] * y + (rnum >> 6)) & 0x3f;\n                int d = data->part_num < 4 ? 0 : (seeds[6] * x + seeds[7] * y + (rnum >> 2)) & 0x3f;\n                data->partition[i] = (a >= b && a >= c && a >= d) ? 0 : (b >= c && b >= d) ? 1 : (c >= d) ? 2 : 3;\n            }\n        }\n    } else {\n        for (int y = 0, i = 0; y < data->bh; y++) {\n            for (int x = 0; x < data->bw; x++, i++) {\n                int a = (seeds[0] * x + seeds[1] * y + (rnum >> 14)) & 0x3f;\n                int b = (seeds[2] * x + seeds[3] * y + (rnum >> 10)) & 0x3f;\n                int c = data->part_num < 3 ? 0 : (seeds[4] * x + seeds[5] * y + (rnum >> 6)) & 0x3f;\n                int d = data->part_num < 4 ? 0 : (seeds[6] * x + seeds[7] * y + (rnum >> 2)) & 0x3f;\n                data->partition[i] = (a >= b && a >= c && a >= d) ? 0 : (b >= c && b >= d) ? 1 : (c >= d) ? 2 : 3;\n            }\n        }\n    }\n}\n\nvoid applicate_color(const BlockData *data, uint32_t *outbuf) {\n    static const t_select_folor_func_ptr FuncTableC[] = {\n      select_color, select_color,     select_color_hdr, select_color_hdr, select_color, select_color,\n      select_color, select_color_hdr, select_color,     select_color,     select_color, select_color_hdr,\n      select_color, select_color,     select_color_hdr, select_color_hdr};\n    static const t_select_folor_func_ptr FuncTableA[] = {\n      select_color, select_color,     select_color_hdr, select_color_hdr, select_color, select_color,\n      select_color, select_color_hdr, select_color,     select_color,     select_color, select_color_hdr,\n      select_color, select_color,     select_color,     select_color_hdr};\n    if (data->dual_plane) {\n        int ps[] = {0, 0, 0, 0};\n        ps[data->plane_selector] = 1;\n        if (data->part_num > 1) {\n            for (int i = 0; i < data->bw * data->bh; i++) {\n                int p = data->partition[i];\n                uint_fast8_t r =\n                  FuncTableC[data->cem[p]](data->endpoints[p][0], data->endpoints[p][4], data->weights[i][ps[0]]);\n                uint_fast8_t g =\n                  FuncTableC[data->cem[p]](data->endpoints[p][1], data->endpoints[p][5], data->weights[i][ps[1]]);\n                uint_fast8_t b =\n                  FuncTableC[data->cem[p]](data->endpoints[p][2], data->endpoints[p][6], data->weights[i][ps[2]]);\n                uint_fast8_t a =\n                  FuncTableA[data->cem[p]](data->endpoints[p][3], data->endpoints[p][7], data->weights[i][ps[3]]);\n                outbuf[i] = color(r, g, b, a);\n            }\n        } else {\n            for (int i = 0; i < data->bw * data->bh; i++) {\n                uint_fast8_t r =\n                  FuncTableC[data->cem[0]](data->endpoints[0][0], data->endpoints[0][4], data->weights[i][ps[0]]);\n                uint_fast8_t g =\n                  FuncTableC[data->cem[0]](data->endpoints[0][1], data->endpoints[0][5], data->weights[i][ps[1]]);\n                uint_fast8_t b =\n                  FuncTableC[data->cem[0]](data->endpoints[0][2], data->endpoints[0][6], data->weights[i][ps[2]]);\n                uint_fast8_t a =\n                  FuncTableA[data->cem[0]](data->endpoints[0][3], data->endpoints[0][7], data->weights[i][ps[3]]);\n                outbuf[i] = color(r, g, b, a);\n            }\n        }\n    } else if (data->part_num > 1) {\n        for (int i = 0; i < data->bw * data->bh; i++) {\n            int p = data->partition[i];\n            uint_fast8_t r =\n              FuncTableC[data->cem[p]](data->endpoints[p][0], data->endpoints[p][4], data->weights[i][0]);\n            uint_fast8_t g =\n              FuncTableC[data->cem[p]](data->endpoints[p][1], data->endpoints[p][5], data->weights[i][0]);\n            uint_fast8_t b =\n              FuncTableC[data->cem[p]](data->endpoints[p][2], data->endpoints[p][6], data->weights[i][0]);\n            uint_fast8_t a =\n              FuncTableA[data->cem[p]](data->endpoints[p][3], data->endpoints[p][7], data->weights[i][0]);\n            outbuf[i] = color(r, g, b, a);\n        }\n    } else {\n        for (int i = 0; i < data->bw * data->bh; i++) {\n            uint_fast8_t r =\n              FuncTableC[data->cem[0]](data->endpoints[0][0], data->endpoints[0][4], data->weights[i][0]);\n            uint_fast8_t g =\n              FuncTableC[data->cem[0]](data->endpoints[0][1], data->endpoints[0][5], data->weights[i][0]);\n            uint_fast8_t b =\n              FuncTableC[data->cem[0]](data->endpoints[0][2], data->endpoints[0][6], data->weights[i][0]);\n            uint_fast8_t a =\n              FuncTableA[data->cem[0]](data->endpoints[0][3], data->endpoints[0][7], data->weights[i][0]);\n            outbuf[i] = color(r, g, b, a);\n        }\n    }\n}\n\nvoid decode_block(const uint8_t *buf, const int bw, const int bh, uint32_t *outbuf) {\n    if (buf[0] == 0xfc && (buf[1] & 1) == 1) {\n        uint_fast32_t c;\n        if (buf[1] & 2)\n            c = color(f16ptr_to_u8(buf + 8), f16ptr_to_u8(buf + 10), f16ptr_to_u8(buf + 12), f16ptr_to_u8(buf + 14));\n        else\n            c = color(buf[9], buf[11], buf[13], buf[15]);\n        for (int i = 0; i < bw * bh; i++)\n            outbuf[i] = c;\n    } else if (((buf[0] & 0xc3) == 0xc0 && (buf[1] & 1) == 1) || (buf[0] & 0xf) == 0) {\n        uint_fast32_t c = color(255, 0, 255, 255);\n        for (int i = 0; i < bw * bh; i++)\n            outbuf[i] = c;\n    } else {\n        BlockData block_data;\n        block_data.bw = bw;\n        block_data.bh = bh;\n        decode_block_params(buf, &block_data);\n        decode_endpoints(buf, &block_data);\n        decode_weights(buf, &block_data);\n        if (block_data.part_num > 1)\n            select_partition(buf, &block_data);\n        applicate_color(&block_data, outbuf);\n    }\n}\n\nint decode_astc(const uint8_t *data, const long w, const long h, const int bw, const int bh, uint32_t *image) {\n    const long num_blocks_x = (w + bw - 1) / bw;\n    const long num_blocks_y = (h + bh - 1) / bh;\n    uint32_t buffer[144];\n    const uint8_t *d = data;\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, d += 16) {\n            decode_block(d, bw, bh, buffer);\n            copy_block_buffer(bx, by, w, h, bw, bh, buffer, image);\n        }\n    }\n    return 1;\n}\n"
  },
  {
    "path": "Texture2DDecoderNative/astc.h",
    "content": "#ifndef ASTC_H\n#define ASTC_H\n\n#include <stdint.h>\n\nint decode_astc(const uint8_t *, const long, const long, const int, const int, uint32_t *);\n\n#endif /* end of include guard: ASTC_H */\n"
  },
  {
    "path": "Texture2DDecoderNative/atc.cpp",
    "content": "#include \"bcn.h\"\n#include \"atc.h\"\n#include \"color.h\"\n#include <algorithm>\n\nstatic uint8_t expand_quantized(uint8_t v, int bits) {\n\tv = v << (8 - bits);\n\treturn v | (v >> bits);\n}\n\nvoid decode_atc_block(const uint8_t* _src, uint32_t* _dst)\n{\n\tuint8_t colors[4 * 4];\n\n\tuint32_t c0 = _src[0] | (_src[1] << 8);\n\tuint32_t c1 = _src[2] | (_src[3] << 8);\n\n\tif (0 == (c0 & 0x8000))\n\t{\n\t\tcolors[0] = expand_quantized((c0 >> 0) & 0x1f, 5);\n\t\tcolors[1] = expand_quantized((c0 >> 5) & 0x1f, 5);\n\t\tcolors[2] = expand_quantized((c0 >> 10) & 0x1f, 5);\n\n\t\tcolors[12] = expand_quantized((c1 >> 0) & 0x1f, 5);\n\t\tcolors[13] = expand_quantized((c1 >> 5) & 0x3f, 6);\n\t\tcolors[14] = expand_quantized((c1 >> 11) & 0x1f, 5);\n\n\t\tcolors[4] = (5 * colors[0] + 3 * colors[12]) / 8;\n\t\tcolors[5] = (5 * colors[1] + 3 * colors[13]) / 8;\n\t\tcolors[6] = (5 * colors[2] + 3 * colors[14]) / 8;\n\n\t\tcolors[8] = (3 * colors[0] + 5 * colors[12]) / 8;\n\t\tcolors[9] = (3 * colors[1] + 5 * colors[13]) / 8;\n\t\tcolors[10] = (3 * colors[2] + 5 * colors[14]) / 8;\n\t}\n\telse\n\t{\n\t\tcolors[0] = 0;\n\t\tcolors[1] = 0;\n\t\tcolors[2] = 0;\n\n\t\tcolors[8] = expand_quantized((c0 >> 0) & 0x1f, 5);\n\t\tcolors[9] = expand_quantized((c0 >> 5) & 0x1f, 5);\n\t\tcolors[10] = expand_quantized((c0 >> 10) & 0x1f, 5);\n\n\t\tcolors[12] = expand_quantized((c1 >> 0) & 0x1f, 5);\n\t\tcolors[13] = expand_quantized((c1 >> 5) & 0x3f, 6);\n\t\tcolors[14] = expand_quantized((c1 >> 11) & 0x1f, 5);\n\n\t\tcolors[4] = std::max(0, colors[8] - colors[12] / 4);\n\t\tcolors[5] = std::max(0, colors[9] - colors[13] / 4);\n\t\tcolors[6] = std::max(0, colors[10] - colors[14] / 4);\n\t}\n\n\tfor (uint32_t i = 0, next = 8 * 4; i < 16; i += 1, next += 2)\n\t{\n\t\tint32_t idx = ((_src[next >> 3] >> (next & 7)) & 3) * 4;\n\t\t_dst[i] = color(colors[idx + 2], colors[idx + 1], colors[idx + 0], 255);\n\t}\n}\n\nint decode_atc_rgb4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) {\n\tuint32_t m_block_width = 4;\n\tuint32_t m_block_height = 4;\n\tuint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width;\n\tuint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height;\n\tuint32_t buffer[16];\n\tfor (uint32_t by = 0; by < m_blocks_y; by++) {\n\t\tfor (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 8) {\n\t\t\tdecode_atc_block(data, buffer);\n\t\t\tcopy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}\n\nint decode_atc_rgba8(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) {\n\tuint32_t m_block_width = 4;\n\tuint32_t m_block_height = 4;\n\tuint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width;\n\tuint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height;\n\tuint32_t buffer[16];\n\tfor (uint32_t by = 0; by < m_blocks_y; by++) {\n\t\tfor (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) {\n\t\t\tdecode_atc_block(data + 8, buffer);\n\t\t\tdecode_bc3_alpha(data, buffer, 3);\n\t\t\tcopy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}"
  },
  {
    "path": "Texture2DDecoderNative/atc.h",
    "content": "#pragma once\n#include <stdint.h>\n\nint decode_atc_rgb4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image);\nint decode_atc_rgba8(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image);"
  },
  {
    "path": "Texture2DDecoderNative/bcn.cpp",
    "content": "#include \"bcn.h\"\n#include <stdint.h>\n#include <assert.h>\n#include <algorithm>\n#include \"color.h\"\n#include \"fp16.h\"\n\nstatic inline void decode_bc1_block(const uint8_t* data, uint32_t* outbuf) {\n\tuint8_t r0, g0, b0, r1, g1, b1;\n\tint q0 = *(uint16_t*)(data);\n\tint q1 = *(uint16_t*)(data + 2);\n\trgb565_le(q0, &r0, &g0, &b0);\n\trgb565_le(q1, &r1, &g1, &b1);\n\tuint_fast32_t c[4] = { color(r0, g0, b0, 255), color(r1, g1, b1, 255) };\n\tif (q0 > q1) {\n\t\tc[2] = color((r0 * 2 + r1) / 3, (g0 * 2 + g1) / 3, (b0 * 2 + b1) / 3, 255);\n\t\tc[3] = color((r0 + r1 * 2) / 3, (g0 + g1 * 2) / 3, (b0 + b1 * 2) / 3, 255);\n\t}\n\telse {\n\t\tc[2] = color((r0 + r1) / 2, (g0 + g1) / 2, (b0 + b1) / 2, 255);\n\t\tc[3] = color(0, 0, 0, 255);\n\t}\n\tuint_fast32_t d = lton32(*(uint32_t*)(data + 4));\n\tfor (int i = 0; i < 16; i++, d >>= 2)\n\t\toutbuf[i] = c[d & 3];\n}\n\nint decode_bc1(const uint8_t* data, const long w, const long h, uint32_t* image) {\n\tlong num_blocks_x = (w + 3) / 4;\n\tlong num_blocks_y = (h + 3) / 4;\n\tuint32_t buffer[16];\n\tconst uint8_t* d = data;\n\tfor (long by = 0; by < num_blocks_y; by++) {\n\t\tfor (long bx = 0; bx < num_blocks_x; bx++, d += 8) {\n\t\t\tdecode_bc1_block(d, buffer);\n\t\t\tcopy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}\n\nvoid decode_bc3_alpha(const uint8_t* data, uint32_t* outbuf, int channel) {\n\tuint_fast8_t a[8] = { data[0], data[1] };\n\tif (a[0] > a[1]) {\n\t\ta[2] = (a[0] * 6 + a[1]) / 7;\n\t\ta[3] = (a[0] * 5 + a[1] * 2) / 7;\n\t\ta[4] = (a[0] * 4 + a[1] * 3) / 7;\n\t\ta[5] = (a[0] * 3 + a[1] * 4) / 7;\n\t\ta[6] = (a[0] * 2 + a[1] * 5) / 7;\n\t\ta[7] = (a[0] + a[1] * 6) / 7;\n\t}\n\telse {\n\t\ta[2] = (a[0] * 4 + a[1]) / 5;\n\t\ta[3] = (a[0] * 3 + a[1] * 2) / 5;\n\t\ta[4] = (a[0] * 2 + a[1] * 3) / 5;\n\t\ta[5] = (a[0] + a[1] * 4) / 5;\n\t\ta[6] = 0;\n\t\ta[7] = 255;\n\t}\n\n\tuint8_t* dst = (uint8_t*)outbuf;\n\tuint_fast64_t d = lton64(*(uint64_t*)data) >> 16;\n\tfor (int i = 0; i < 16; i++, d >>= 3)\n\t\tdst[i * 4 + channel] = a[d & 7];\n}\n\nstatic inline void decode_bc3_block(const uint8_t* data, uint32_t* outbuf) {\n\tdecode_bc1_block(data + 8, outbuf);\n\tdecode_bc3_alpha(data, outbuf, 3);\n}\n\nint decode_bc3(const uint8_t* data, const long w, const long h, uint32_t* image) {\n\tlong num_blocks_x = (w + 3) / 4;\n\tlong num_blocks_y = (h + 3) / 4;\n\tuint32_t buffer[16];\n\tconst uint8_t* d = data;\n\tfor (long by = 0; by < num_blocks_y; by++) {\n\t\tfor (long bx = 0; bx < num_blocks_x; bx++, d += 16) {\n\t\t\tdecode_bc3_block(d, buffer);\n\t\t\tcopy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}\n\nstatic inline void decode_bc4_block(const uint8_t* data, uint32_t* outbuf) {\n\tdecode_bc3_alpha(data, outbuf, 2);\n}\n\nint decode_bc4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) {\n\tuint32_t m_block_width = 4;\n\tuint32_t m_block_height = 4;\n\tuint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width;\n\tuint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height;\n\tuint32_t buffer[16];\n\tfor (uint32_t i = 0; i < 16; i++)\n\t\tbuffer[i] = 0xff000000;\n\tfor (uint32_t by = 0; by < m_blocks_y; by++) {\n\t\tfor (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 8) {\n\t\t\tdecode_bc4_block(data, buffer);\n\t\t\tcopy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}\n\nstatic inline void decode_bc5_block(const uint8_t* data, uint32_t* outbuf) {\n\tdecode_bc3_alpha(data, outbuf, 2);\n\tdecode_bc3_alpha(data + 8, outbuf, 1);\n}\n\nint decode_bc5(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) {\n\tuint32_t m_block_width = 4;\n\tuint32_t m_block_height = 4;\n\tuint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width;\n\tuint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height;\n\tuint32_t buffer[16];\n\tfor (uint32_t i = 0; i < 16; i++)\n\t\tbuffer[i] = 0xff000000;\n\tfor (uint32_t by = 0; by < m_blocks_y; by++) {\n\t\tfor (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) {\n\t\t\tdecode_bc5_block(data, buffer);\n\t\t\tcopy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}\n\nstruct BitReader\n{\n\tBitReader(const uint8_t* _data, uint16_t _bitPos = 0)\n\t\t: m_data(_data)\n\t\t, m_bitPos(_bitPos)\n\t{\n\t}\n\n\tuint16_t read(uint8_t _numBits)\n\t{\n\t\tconst uint16_t pos = m_bitPos / 8;\n\t\tconst uint16_t shift = m_bitPos & 7;\n\t\tuint32_t data = 0;\n\t\tmemcpy(&data, &m_data[pos], std::min(4, 16 - pos));\n\t\tm_bitPos += _numBits;\n\t\treturn uint16_t((data >> shift) & ((1 << _numBits) - 1));\n\t}\n\n\tuint16_t peek(uint16_t _offset, uint8_t _numBits)\n\t{\n\t\tconst uint16_t bitPos = m_bitPos + _offset;\n\t\tconst uint16_t shift = bitPos & 7;\n\t\tuint16_t pos = bitPos / 8;\n\t\tuint32_t data = 0;\n\t\tmemcpy(&data, &m_data[pos], std::min(4, 16 - pos));\n\t\treturn uint8_t((data >> shift) & ((1 << _numBits) - 1));\n\t}\n\n\tconst uint8_t* m_data;\n\tuint16_t m_bitPos;\n};\n\nstatic const uint16_t s_bptcP2[] =\n{ //  3210     0000000000   1111111111   2222222222   3333333333\n\t0xcccc, // 0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1\n\t0x8888, // 0, 0, 0, 1,  0, 0, 0, 1,  0, 0, 0, 1,  0, 0, 0, 1\n\t0xeeee, // 0, 1, 1, 1,  0, 1, 1, 1,  0, 1, 1, 1,  0, 1, 1, 1\n\t0xecc8, // 0, 0, 0, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 1, 1, 1\n\t0xc880, // 0, 0, 0, 0,  0, 0, 0, 1,  0, 0, 0, 1,  0, 0, 1, 1\n\t0xfeec, // 0, 0, 1, 1,  0, 1, 1, 1,  0, 1, 1, 1,  1, 1, 1, 1\n\t0xfec8, // 0, 0, 0, 1,  0, 0, 1, 1,  0, 1, 1, 1,  1, 1, 1, 1\n\t0xec80, // 0, 0, 0, 0,  0, 0, 0, 1,  0, 0, 1, 1,  0, 1, 1, 1\n\t0xc800, // 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 1,  0, 0, 1, 1\n\t0xffec, // 0, 0, 1, 1,  0, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1\n\t0xfe80, // 0, 0, 0, 0,  0, 0, 0, 1,  0, 1, 1, 1,  1, 1, 1, 1\n\t0xe800, // 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 1,  0, 1, 1, 1\n\t0xffe8, // 0, 0, 0, 1,  0, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1\n\t0xff00, // 0, 0, 0, 0,  0, 0, 0, 0,  1, 1, 1, 1,  1, 1, 1, 1\n\t0xfff0, // 0, 0, 0, 0,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1\n\t0xf000, // 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  1, 1, 1, 1\n\t0xf710, // 0, 0, 0, 0,  1, 0, 0, 0,  1, 1, 1, 0,  1, 1, 1, 1\n\t0x008e, // 0, 1, 1, 1,  0, 0, 0, 1,  0, 0, 0, 0,  0, 0, 0, 0\n\t0x7100, // 0, 0, 0, 0,  0, 0, 0, 0,  1, 0, 0, 0,  1, 1, 1, 0\n\t0x08ce, // 0, 1, 1, 1,  0, 0, 1, 1,  0, 0, 0, 1,  0, 0, 0, 0\n\t0x008c, // 0, 0, 1, 1,  0, 0, 0, 1,  0, 0, 0, 0,  0, 0, 0, 0\n\t0x7310, // 0, 0, 0, 0,  1, 0, 0, 0,  1, 1, 0, 0,  1, 1, 1, 0\n\t0x3100, // 0, 0, 0, 0,  0, 0, 0, 0,  1, 0, 0, 0,  1, 1, 0, 0\n\t0x8cce, // 0, 1, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 0, 1\n\t0x088c, // 0, 0, 1, 1,  0, 0, 0, 1,  0, 0, 0, 1,  0, 0, 0, 0\n\t0x3110, // 0, 0, 0, 0,  1, 0, 0, 0,  1, 0, 0, 0,  1, 1, 0, 0\n\t0x6666, // 0, 1, 1, 0,  0, 1, 1, 0,  0, 1, 1, 0,  0, 1, 1, 0\n\t0x366c, // 0, 0, 1, 1,  0, 1, 1, 0,  0, 1, 1, 0,  1, 1, 0, 0\n\t0x17e8, // 0, 0, 0, 1,  0, 1, 1, 1,  1, 1, 1, 0,  1, 0, 0, 0\n\t0x0ff0, // 0, 0, 0, 0,  1, 1, 1, 1,  1, 1, 1, 1,  0, 0, 0, 0\n\t0x718e, // 0, 1, 1, 1,  0, 0, 0, 1,  1, 0, 0, 0,  1, 1, 1, 0\n\t0x399c, // 0, 0, 1, 1,  1, 0, 0, 1,  1, 0, 0, 1,  1, 1, 0, 0\n\t0xaaaa, // 0, 1, 0, 1,  0, 1, 0, 1,  0, 1, 0, 1,  0, 1, 0, 1\n\t0xf0f0, // 0, 0, 0, 0,  1, 1, 1, 1,  0, 0, 0, 0,  1, 1, 1, 1\n\t0x5a5a, // 0, 1, 0, 1,  1, 0, 1, 0,  0, 1, 0, 1,  1, 0, 1, 0\n\t0x33cc, // 0, 0, 1, 1,  0, 0, 1, 1,  1, 1, 0, 0,  1, 1, 0, 0\n\t0x3c3c, // 0, 0, 1, 1,  1, 1, 0, 0,  0, 0, 1, 1,  1, 1, 0, 0\n\t0x55aa, // 0, 1, 0, 1,  0, 1, 0, 1,  1, 0, 1, 0,  1, 0, 1, 0\n\t0x9696, // 0, 1, 1, 0,  1, 0, 0, 1,  0, 1, 1, 0,  1, 0, 0, 1\n\t0xa55a, // 0, 1, 0, 1,  1, 0, 1, 0,  1, 0, 1, 0,  0, 1, 0, 1\n\t0x73ce, // 0, 1, 1, 1,  0, 0, 1, 1,  1, 1, 0, 0,  1, 1, 1, 0\n\t0x13c8, // 0, 0, 0, 1,  0, 0, 1, 1,  1, 1, 0, 0,  1, 0, 0, 0\n\t0x324c, // 0, 0, 1, 1,  0, 0, 1, 0,  0, 1, 0, 0,  1, 1, 0, 0\n\t0x3bdc, // 0, 0, 1, 1,  1, 0, 1, 1,  1, 1, 0, 1,  1, 1, 0, 0\n\t0x6996, // 0, 1, 1, 0,  1, 0, 0, 1,  1, 0, 0, 1,  0, 1, 1, 0\n\t0xc33c, // 0, 0, 1, 1,  1, 1, 0, 0,  1, 1, 0, 0,  0, 0, 1, 1\n\t0x9966, // 0, 1, 1, 0,  0, 1, 1, 0,  1, 0, 0, 1,  1, 0, 0, 1\n\t0x0660, // 0, 0, 0, 0,  0, 1, 1, 0,  0, 1, 1, 0,  0, 0, 0, 0\n\t0x0272, // 0, 1, 0, 0,  1, 1, 1, 0,  0, 1, 0, 0,  0, 0, 0, 0\n\t0x04e4, // 0, 0, 1, 0,  0, 1, 1, 1,  0, 0, 1, 0,  0, 0, 0, 0\n\t0x4e40, // 0, 0, 0, 0,  0, 0, 1, 0,  0, 1, 1, 1,  0, 0, 1, 0\n\t0x2720, // 0, 0, 0, 0,  0, 1, 0, 0,  1, 1, 1, 0,  0, 1, 0, 0\n\t0xc936, // 0, 1, 1, 0,  1, 1, 0, 0,  1, 0, 0, 1,  0, 0, 1, 1\n\t0x936c, // 0, 0, 1, 1,  0, 1, 1, 0,  1, 1, 0, 0,  1, 0, 0, 1\n\t0x39c6, // 0, 1, 1, 0,  0, 0, 1, 1,  1, 0, 0, 1,  1, 1, 0, 0\n\t0x639c, // 0, 0, 1, 1,  1, 0, 0, 1,  1, 1, 0, 0,  0, 1, 1, 0\n\t0x9336, // 0, 1, 1, 0,  1, 1, 0, 0,  1, 1, 0, 0,  1, 0, 0, 1\n\t0x9cc6, // 0, 1, 1, 0,  0, 0, 1, 1,  0, 0, 1, 1,  1, 0, 0, 1\n\t0x817e, // 0, 1, 1, 1,  1, 1, 1, 0,  1, 0, 0, 0,  0, 0, 0, 1\n\t0xe718, // 0, 0, 0, 1,  1, 0, 0, 0,  1, 1, 1, 0,  0, 1, 1, 1\n\t0xccf0, // 0, 0, 0, 0,  1, 1, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1\n\t0x0fcc, // 0, 0, 1, 1,  0, 0, 1, 1,  1, 1, 1, 1,  0, 0, 0, 0\n\t0x7744, // 0, 0, 1, 0,  0, 0, 1, 0,  1, 1, 1, 0,  1, 1, 1, 0\n\t0xee22, // 0, 1, 0, 0,  0, 1, 0, 0,  0, 1, 1, 1,  0, 1, 1, 1\n};\n\nstatic const uint8_t s_bptcA2[] =\n{\n\t15, 15, 15, 15, 15, 15, 15, 15,\n\t15, 15, 15, 15, 15, 15, 15, 15,\n\t15,  2,  8,  2,  2,  8,  8, 15,\n\t 2,  8,  2,  2,  8,  8,  2,  2,\n\t15, 15,  6,  8,  2,  8, 15, 15,\n\t 2,  8,  2,  2,  2, 15, 15,  6,\n\t 6,  2,  6,  8, 15, 15,  2,  2,\n\t15, 15, 15, 15, 15,  2,  2, 15,\n};\n\nstatic const uint8_t s_bptcFactors[3][16] =\n{\n\t{  0, 21, 43, 64,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },\n\t{  0,  9, 18, 27, 37, 46, 55, 64,  0,  0,  0,  0,  0,  0,  0,  0 },\n\t{  0,  4,  9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 },\n};\n\nstruct Bc6hModeInfo\n{\n\tuint8_t transformed;\n\tuint8_t partitionBits;\n\tuint8_t endpointBits;\n\tuint8_t deltaBits[3];\n};\n\nstatic const Bc6hModeInfo s_bc6hModeInfo[] =\n{ //  +--------------------------- transformed\n  //  |  +------------------------ partition bits\n  //  |  |  +--------------------- endpoint bits\n  //  |  |  |      +-------------- delta bits\n\t{ 1, 5, 10, {  5,  5,  5 } }, // 00    2-bits\n\t{ 1, 5,  7, {  6,  6,  6 } }, // 01\n\t{ 1, 5, 11, {  5,  4,  4 } }, // 00010 5-bits\n\t{ 0, 0, 10, { 10, 10, 10 } }, // 00011\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 1, 5, 11, {  4,  5,  4 } }, // 00110\n\t{ 1, 0, 11, {  9,  9,  9 } }, // 00010\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 1, 5, 11, {  4,  4,  5 } }, // 00010\n\t{ 1, 0, 12, {  8,  8,  8 } }, // 00010\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 1, 5,  9, {  5,  5,  5 } }, // 00010\n\t{ 1, 0, 16, {  4,  4,  4 } }, // 00010\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 1, 5,  8, {  6,  5,  5 } }, // 00010\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 1, 5,  8, {  5,  6,  5 } }, // 00010\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 1, 5,  8, {  5,  5,  6 } }, // 00010\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n\t{ 0, 5,  6, {  6,  6,  6 } }, // 00010\n\t{ 0, 0,  0, {  0,  0,  0 } }, // -\n};\n\nstatic uint16_t unquantize(uint16_t _value, bool _signed, uint8_t _endpointBits)\n{\n\tconst uint16_t maxValue = 1 << (_endpointBits - 1);\n\n\tif (_signed)\n\t{\n\t\tif (_endpointBits >= 16)\n\t\t{\n\t\t\treturn _value;\n\t\t}\n\n\t\tconst bool sign = !!(_value & 0x8000);\n\t\t_value &= 0x7fff;\n\n\t\tuint16_t unq;\n\n\t\tif (0 == _value)\n\t\t{\n\t\t\tunq = 0;\n\t\t}\n\t\telse if (_value >= maxValue - 1)\n\t\t{\n\t\t\tunq = 0x7fff;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tunq = ((_value << 15) + 0x4000) >> (_endpointBits - 1);\n\t\t}\n\n\t\treturn sign ? -unq : unq;\n\t}\n\n\tif (_endpointBits >= 15)\n\t{\n\t\treturn _value;\n\t}\n\n\tif (0 == _value)\n\t{\n\t\treturn 0;\n\t}\n\n\tif (_value == maxValue)\n\t{\n\t\treturn UINT16_MAX;\n\t}\n\n\treturn ((_value << 15) + 0x4000) >> (_endpointBits - 1);\n}\n\nstatic uint16_t finish_unquantize(uint16_t _value, bool _signed)\n{\n\tif (_signed)\n\t{\n\t\tconst uint16_t sign = _value & 0x8000;\n\t\t_value &= 0x7fff;\n\n\t\treturn ((_value * 31) >> 5) | sign;\n\t}\n\n\treturn (_value * 31) >> 6;\n}\n\nstatic uint16_t sign_extend(uint16_t _value, uint8_t _numBits)\n{\n\tconst uint16_t mask = 1 << (_numBits - 1);\n\tconst uint16_t result = (_value ^ mask) - mask;\n\n\treturn result;\n}\n\nstatic inline uint8_t f32_to_u8(const float f) {\n\tfloat c = roundf(f * 255);\n\tif (c < 0)\n\t\treturn 0;\n\telse if (c > 255)\n\t\treturn 255;\n\telse\n\t\treturn c;\n}\n\nstatic uint8_t half_to_u8(uint16_t h) {\n\treturn f32_to_u8(fp16_ieee_to_fp32_value(h));\n}\n\nstatic void decode_bc6_block(const uint8_t* _src, uint32_t* _dst, bool _signed)\n{\n\tBitReader bit(_src);\n\n\tuint8_t mode = uint8_t(bit.read(2));\n\n\tuint16_t epR[4] = { /* rw, rx, ry, rz */ };\n\tuint16_t epG[4] = { /* gw, gx, gy, gz */ };\n\tuint16_t epB[4] = { /* bw, bx, by, bz */ };\n\n\tif (mode & 2)\n\t{\n\t\t// 5-bit mode\n\t\tmode |= bit.read(3) << 2;\n\n\t\tif (0 == s_bc6hModeInfo[mode].endpointBits)\n\t\t{\n\t\t\tmemset(_dst, 0, 16 * 4);\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (mode)\n\t\t{\n\t\tcase 2:\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(5) << 0;\n\t\t\tepR[0] |= bit.read(1) << 10;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(4) << 0;\n\t\t\tepG[0] |= bit.read(1) << 10;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(4) << 0;\n\t\t\tepB[0] |= bit.read(1) << 10;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepR[3] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tbreak;\n\n\t\tcase 3:\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(10) << 0;\n\t\t\tepG[1] |= bit.read(10) << 0;\n\t\t\tepB[1] |= bit.read(10) << 0;\n\t\t\tbreak;\n\n\t\tcase 6:\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(4) << 0;\n\t\t\tepR[0] |= bit.read(1) << 10;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(5) << 0;\n\t\t\tepG[0] |= bit.read(1) << 10;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(4) << 0;\n\t\t\tepB[0] |= bit.read(1) << 10;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(4) << 0;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepR[3] |= bit.read(4) << 0;\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tbreak;\n\n\t\tcase 7:\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(9) << 0;\n\t\t\tepR[0] |= bit.read(1) << 10;\n\t\t\tepG[1] |= bit.read(9) << 0;\n\t\t\tepG[0] |= bit.read(1) << 10;\n\t\t\tepB[1] |= bit.read(9) << 0;\n\t\t\tepB[0] |= bit.read(1) << 10;\n\t\t\tbreak;\n\n\t\tcase 10:\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(4) << 0;\n\t\t\tepR[0] |= bit.read(1) << 10;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(4) << 0;\n\t\t\tepG[0] |= bit.read(1) << 10;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(5) << 0;\n\t\t\tepB[0] |= bit.read(1) << 10;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(4) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepR[3] |= bit.read(4) << 0;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tbreak;\n\n\t\tcase 11:\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(8) << 0;\n\t\t\tepR[0] |= bit.read(1) << 11;\n\t\t\tepR[0] |= bit.read(1) << 10;\n\t\t\tepG[1] |= bit.read(8) << 0;\n\t\t\tepG[0] |= bit.read(1) << 11;\n\t\t\tepG[0] |= bit.read(1) << 10;\n\t\t\tepB[1] |= bit.read(8) << 0;\n\t\t\tepB[0] |= bit.read(1) << 11;\n\t\t\tepB[0] |= bit.read(1) << 10;\n\t\t\tbreak;\n\n\t\tcase 14:\n\t\t\tepR[0] |= bit.read(9) << 0;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepG[0] |= bit.read(9) << 0;\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[0] |= bit.read(9) << 0;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepR[1] |= bit.read(5) << 0;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepR[3] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tbreak;\n\n\t\tcase 15:\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(4) << 0;\n\t\t\tepR[0] |= bit.read(1) << 15;\n\t\t\tepR[0] |= bit.read(1) << 14;\n\t\t\tepR[0] |= bit.read(1) << 13;\n\t\t\tepR[0] |= bit.read(1) << 12;\n\t\t\tepR[0] |= bit.read(1) << 11;\n\t\t\tepR[0] |= bit.read(1) << 10;\n\t\t\tepG[1] |= bit.read(4) << 0;\n\t\t\tepG[0] |= bit.read(1) << 15;\n\t\t\tepG[0] |= bit.read(1) << 14;\n\t\t\tepG[0] |= bit.read(1) << 13;\n\t\t\tepG[0] |= bit.read(1) << 12;\n\t\t\tepG[0] |= bit.read(1) << 11;\n\t\t\tepG[0] |= bit.read(1) << 10;\n\t\t\tepB[1] |= bit.read(4) << 0;\n\t\t\tepB[0] |= bit.read(1) << 15;\n\t\t\tepB[0] |= bit.read(1) << 14;\n\t\t\tepB[0] |= bit.read(1) << 13;\n\t\t\tepB[0] |= bit.read(1) << 12;\n\t\t\tepB[0] |= bit.read(1) << 11;\n\t\t\tepB[0] |= bit.read(1) << 10;\n\t\t\tbreak;\n\n\t\tcase 18:\n\t\t\tepR[0] |= bit.read(8) << 0;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepG[0] |= bit.read(8) << 0;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[0] |= bit.read(8) << 0;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepR[1] |= bit.read(6) << 0;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(6) << 0;\n\t\t\tepR[3] |= bit.read(6) << 0;\n\t\t\tbreak;\n\n\t\tcase 22:\n\t\t\tepR[0] |= bit.read(8) << 0;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepG[0] |= bit.read(8) << 0;\n\t\t\tepG[2] |= bit.read(1) << 5;\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[0] |= bit.read(8) << 0;\n\t\t\tepG[3] |= bit.read(1) << 5;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepR[1] |= bit.read(5) << 0;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(6) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepR[3] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tbreak;\n\n\t\tcase 26:\n\t\t\tepR[0] |= bit.read(8) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepG[0] |= bit.read(8) << 0;\n\t\t\tepB[2] |= bit.read(1) << 5;\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[0] |= bit.read(8) << 0;\n\t\t\tepB[3] |= bit.read(1) << 5;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepR[1] |= bit.read(5) << 0;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(6) << 0;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepR[3] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tbreak;\n\n\t\tcase 30:\n\t\t\tepR[0] |= bit.read(6) << 0;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepG[0] |= bit.read(6) << 0;\n\t\t\tepG[2] |= bit.read(1) << 5;\n\t\t\tepB[2] |= bit.read(1) << 5;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[0] |= bit.read(6) << 0;\n\t\t\tepG[3] |= bit.read(1) << 5;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tepB[3] |= bit.read(1) << 5;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepR[1] |= bit.read(6) << 0;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(6) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(6) << 0;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(6) << 0;\n\t\t\tepR[3] |= bit.read(6) << 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch (mode)\n\t\t{\n\t\tcase 0:\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepR[0] |= bit.read(10) << 0;\n\t\t\tepG[0] |= bit.read(10) << 0;\n\t\t\tepB[0] |= bit.read(10) << 0;\n\t\t\tepR[1] |= bit.read(5) << 0;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepR[3] |= bit.read(5) << 0;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tepG[2] |= bit.read(1) << 5;\n\t\t\tepG[3] |= bit.read(1) << 4;\n\t\t\tepG[3] |= bit.read(1) << 5;\n\t\t\tepR[0] |= bit.read(7) << 0;\n\t\t\tepB[3] |= bit.read(1) << 0;\n\t\t\tepB[3] |= bit.read(1) << 1;\n\t\t\tepB[2] |= bit.read(1) << 4;\n\t\t\tepG[0] |= bit.read(7) << 0;\n\t\t\tepB[2] |= bit.read(1) << 5;\n\t\t\tepB[3] |= bit.read(1) << 2;\n\t\t\tepG[2] |= bit.read(1) << 4;\n\t\t\tepB[0] |= bit.read(7) << 0;\n\t\t\tepB[3] |= bit.read(1) << 3;\n\t\t\tepB[3] |= bit.read(1) << 5;\n\t\t\tepB[3] |= bit.read(1) << 4;\n\t\t\tepR[1] |= bit.read(6) << 0;\n\t\t\tepG[2] |= bit.read(4) << 0;\n\t\t\tepG[1] |= bit.read(6) << 0;\n\t\t\tepG[3] |= bit.read(4) << 0;\n\t\t\tepB[1] |= bit.read(6) << 0;\n\t\t\tepB[2] |= bit.read(4) << 0;\n\t\t\tepR[2] |= bit.read(6) << 0;\n\t\t\tepR[3] |= bit.read(6) << 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst Bc6hModeInfo mi = s_bc6hModeInfo[mode];\n\n\tif (_signed)\n\t{\n\t\tepR[0] = sign_extend(epR[0], mi.endpointBits);\n\t\tepG[0] = sign_extend(epG[0], mi.endpointBits);\n\t\tepB[0] = sign_extend(epB[0], mi.endpointBits);\n\t}\n\n\tconst uint8_t numSubsets = !!mi.partitionBits + 1;\n\n\tfor (uint8_t ii = 1, num = numSubsets * 2; ii < num; ++ii)\n\t{\n\t\tif (_signed\n\t\t\t|| mi.transformed)\n\t\t{\n\t\t\tepR[ii] = sign_extend(epR[ii], mi.deltaBits[0]);\n\t\t\tepG[ii] = sign_extend(epG[ii], mi.deltaBits[1]);\n\t\t\tepB[ii] = sign_extend(epB[ii], mi.deltaBits[2]);\n\t\t}\n\n\t\tif (mi.transformed)\n\t\t{\n\t\t\tconst uint16_t mask = (1 << mi.endpointBits) - 1;\n\n\t\t\tepR[ii] = (epR[ii] + epR[0]) & mask;\n\t\t\tepG[ii] = (epG[ii] + epG[0]) & mask;\n\t\t\tepB[ii] = (epB[ii] + epB[0]) & mask;\n\n\t\t\tif (_signed)\n\t\t\t{\n\t\t\t\tepR[ii] = sign_extend(epR[ii], mi.endpointBits);\n\t\t\t\tepG[ii] = sign_extend(epG[ii], mi.endpointBits);\n\t\t\t\tepB[ii] = sign_extend(epB[ii], mi.endpointBits);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (uint8_t ii = 0, num = numSubsets * 2; ii < num; ++ii)\n\t{\n\t\tepR[ii] = unquantize(epR[ii], _signed, mi.endpointBits);\n\t\tepG[ii] = unquantize(epG[ii], _signed, mi.endpointBits);\n\t\tepB[ii] = unquantize(epB[ii], _signed, mi.endpointBits);\n\t}\n\n\tconst uint8_t partitionSetIdx = uint8_t(mi.partitionBits ? bit.read(5) : 0);\n\tconst uint8_t indexBits = mi.partitionBits ? 3 : 4;\n\tconst uint8_t* factors = s_bptcFactors[indexBits - 2];\n\n\tfor (uint8_t yy = 0; yy < 4; ++yy)\n\t{\n\t\tfor (uint8_t xx = 0; xx < 4; ++xx)\n\t\t{\n\t\t\tconst uint8_t idx = yy * 4 + xx;\n\n\t\t\tuint8_t subsetIndex = 0;\n\t\t\tuint8_t indexAnchor = 0;\n\n\t\t\tif (0 != mi.partitionBits)\n\t\t\t{\n\t\t\t\tsubsetIndex = (s_bptcP2[partitionSetIdx] >> idx) & 1;\n\t\t\t\tindexAnchor = subsetIndex ? s_bptcA2[partitionSetIdx] : 0;\n\t\t\t}\n\n\t\t\tconst uint8_t anchor = idx == indexAnchor;\n\t\t\tconst uint8_t num = indexBits - anchor;\n\t\t\tconst uint8_t index = (uint8_t)bit.read(num);\n\n\t\t\tconst uint8_t fc = factors[index];\n\t\t\tconst uint8_t fca = 64 - fc;\n\t\t\tconst uint8_t fcb = fc;\n\n\t\t\tsubsetIndex *= 2;\n\t\t\tuint16_t rr = finish_unquantize((epR[subsetIndex] * fca + epR[subsetIndex + 1] * fcb + 32) >> 6, _signed);\n\t\t\tuint16_t gg = finish_unquantize((epG[subsetIndex] * fca + epG[subsetIndex + 1] * fcb + 32) >> 6, _signed);\n\t\t\tuint16_t bb = finish_unquantize((epB[subsetIndex] * fca + epB[subsetIndex + 1] * fcb + 32) >> 6, _signed);\n\n\t\t\t_dst[idx] = color(half_to_u8(rr), half_to_u8(gg), half_to_u8(bb), 255);\n\t\t}\n\t}\n}\n\nint decode_bc6(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) {\n\tuint32_t m_block_width = 4;\n\tuint32_t m_block_height = 4;\n\tuint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width;\n\tuint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height;\n\tuint32_t buffer[16];\n\tfor (uint32_t by = 0; by < m_blocks_y; by++) {\n\t\tfor (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) {\n\t\t\tdecode_bc6_block(data, buffer, false);\n\t\t\tcopy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}\n\nstatic const uint32_t s_bptcP3[] =\n{ //  76543210     0000   1111   2222   3333   4444   5555   6666   7777\n\t0xaa685050, // 0, 0,  1, 1,  0, 0,  1, 1,  0, 2,  2, 1,  2, 2,  2, 2\n\t0x6a5a5040, // 0, 0,  0, 1,  0, 0,  1, 1,  2, 2,  1, 1,  2, 2,  2, 1\n\t0x5a5a4200, // 0, 0,  0, 0,  2, 0,  0, 1,  2, 2,  1, 1,  2, 2,  1, 1\n\t0x5450a0a8, // 0, 2,  2, 2,  0, 0,  2, 2,  0, 0,  1, 1,  0, 1,  1, 1\n\t0xa5a50000, // 0, 0,  0, 0,  0, 0,  0, 0,  1, 1,  2, 2,  1, 1,  2, 2\n\t0xa0a05050, // 0, 0,  1, 1,  0, 0,  1, 1,  0, 0,  2, 2,  0, 0,  2, 2\n\t0x5555a0a0, // 0, 0,  2, 2,  0, 0,  2, 2,  1, 1,  1, 1,  1, 1,  1, 1\n\t0x5a5a5050, // 0, 0,  1, 1,  0, 0,  1, 1,  2, 2,  1, 1,  2, 2,  1, 1\n\t0xaa550000, // 0, 0,  0, 0,  0, 0,  0, 0,  1, 1,  1, 1,  2, 2,  2, 2\n\t0xaa555500, // 0, 0,  0, 0,  1, 1,  1, 1,  1, 1,  1, 1,  2, 2,  2, 2\n\t0xaaaa5500, // 0, 0,  0, 0,  1, 1,  1, 1,  2, 2,  2, 2,  2, 2,  2, 2\n\t0x90909090, // 0, 0,  1, 2,  0, 0,  1, 2,  0, 0,  1, 2,  0, 0,  1, 2\n\t0x94949494, // 0, 1,  1, 2,  0, 1,  1, 2,  0, 1,  1, 2,  0, 1,  1, 2\n\t0xa4a4a4a4, // 0, 1,  2, 2,  0, 1,  2, 2,  0, 1,  2, 2,  0, 1,  2, 2\n\t0xa9a59450, // 0, 0,  1, 1,  0, 1,  1, 2,  1, 1,  2, 2,  1, 2,  2, 2\n\t0x2a0a4250, // 0, 0,  1, 1,  2, 0,  0, 1,  2, 2,  0, 0,  2, 2,  2, 0\n\t0xa5945040, // 0, 0,  0, 1,  0, 0,  1, 1,  0, 1,  1, 2,  1, 1,  2, 2\n\t0x0a425054, // 0, 1,  1, 1,  0, 0,  1, 1,  2, 0,  0, 1,  2, 2,  0, 0\n\t0xa5a5a500, // 0, 0,  0, 0,  1, 1,  2, 2,  1, 1,  2, 2,  1, 1,  2, 2\n\t0x55a0a0a0, // 0, 0,  2, 2,  0, 0,  2, 2,  0, 0,  2, 2,  1, 1,  1, 1\n\t0xa8a85454, // 0, 1,  1, 1,  0, 1,  1, 1,  0, 2,  2, 2,  0, 2,  2, 2\n\t0x6a6a4040, // 0, 0,  0, 1,  0, 0,  0, 1,  2, 2,  2, 1,  2, 2,  2, 1\n\t0xa4a45000, // 0, 0,  0, 0,  0, 0,  1, 1,  0, 1,  2, 2,  0, 1,  2, 2\n\t0x1a1a0500, // 0, 0,  0, 0,  1, 1,  0, 0,  2, 2,  1, 0,  2, 2,  1, 0\n\t0x0050a4a4, // 0, 1,  2, 2,  0, 1,  2, 2,  0, 0,  1, 1,  0, 0,  0, 0\n\t0xaaa59090, // 0, 0,  1, 2,  0, 0,  1, 2,  1, 1,  2, 2,  2, 2,  2, 2\n\t0x14696914, // 0, 1,  1, 0,  1, 2,  2, 1,  1, 2,  2, 1,  0, 1,  1, 0\n\t0x69691400, // 0, 0,  0, 0,  0, 1,  1, 0,  1, 2,  2, 1,  1, 2,  2, 1\n\t0xa08585a0, // 0, 0,  2, 2,  1, 1,  0, 2,  1, 1,  0, 2,  0, 0,  2, 2\n\t0xaa821414, // 0, 1,  1, 0,  0, 1,  1, 0,  2, 0,  0, 2,  2, 2,  2, 2\n\t0x50a4a450, // 0, 0,  1, 1,  0, 1,  2, 2,  0, 1,  2, 2,  0, 0,  1, 1\n\t0x6a5a0200, // 0, 0,  0, 0,  2, 0,  0, 0,  2, 2,  1, 1,  2, 2,  2, 1\n\t0xa9a58000, // 0, 0,  0, 0,  0, 0,  0, 2,  1, 1,  2, 2,  1, 2,  2, 2\n\t0x5090a0a8, // 0, 2,  2, 2,  0, 0,  2, 2,  0, 0,  1, 2,  0, 0,  1, 1\n\t0xa8a09050, // 0, 0,  1, 1,  0, 0,  1, 2,  0, 0,  2, 2,  0, 2,  2, 2\n\t0x24242424, // 0, 1,  2, 0,  0, 1,  2, 0,  0, 1,  2, 0,  0, 1,  2, 0\n\t0x00aa5500, // 0, 0,  0, 0,  1, 1,  1, 1,  2, 2,  2, 2,  0, 0,  0, 0\n\t0x24924924, // 0, 1,  2, 0,  1, 2,  0, 1,  2, 0,  1, 2,  0, 1,  2, 0\n\t0x24499224, // 0, 1,  2, 0,  2, 0,  1, 2,  1, 2,  0, 1,  0, 1,  2, 0\n\t0x50a50a50, // 0, 0,  1, 1,  2, 2,  0, 0,  1, 1,  2, 2,  0, 0,  1, 1\n\t0x500aa550, // 0, 0,  1, 1,  1, 1,  2, 2,  2, 2,  0, 0,  0, 0,  1, 1\n\t0xaaaa4444, // 0, 1,  0, 1,  0, 1,  0, 1,  2, 2,  2, 2,  2, 2,  2, 2\n\t0x66660000, // 0, 0,  0, 0,  0, 0,  0, 0,  2, 1,  2, 1,  2, 1,  2, 1\n\t0xa5a0a5a0, // 0, 0,  2, 2,  1, 1,  2, 2,  0, 0,  2, 2,  1, 1,  2, 2\n\t0x50a050a0, // 0, 0,  2, 2,  0, 0,  1, 1,  0, 0,  2, 2,  0, 0,  1, 1\n\t0x69286928, // 0, 2,  2, 0,  1, 2,  2, 1,  0, 2,  2, 0,  1, 2,  2, 1\n\t0x44aaaa44, // 0, 1,  0, 1,  2, 2,  2, 2,  2, 2,  2, 2,  0, 1,  0, 1\n\t0x66666600, // 0, 0,  0, 0,  2, 1,  2, 1,  2, 1,  2, 1,  2, 1,  2, 1\n\t0xaa444444, // 0, 1,  0, 1,  0, 1,  0, 1,  0, 1,  0, 1,  2, 2,  2, 2\n\t0x54a854a8, // 0, 2,  2, 2,  0, 1,  1, 1,  0, 2,  2, 2,  0, 1,  1, 1\n\t0x95809580, // 0, 0,  0, 2,  1, 1,  1, 2,  0, 0,  0, 2,  1, 1,  1, 2\n\t0x96969600, // 0, 0,  0, 0,  2, 1,  1, 2,  2, 1,  1, 2,  2, 1,  1, 2\n\t0xa85454a8, // 0, 2,  2, 2,  0, 1,  1, 1,  0, 1,  1, 1,  0, 2,  2, 2\n\t0x80959580, // 0, 0,  0, 2,  1, 1,  1, 2,  1, 1,  1, 2,  0, 0,  0, 2\n\t0xaa141414, // 0, 1,  1, 0,  0, 1,  1, 0,  0, 1,  1, 0,  2, 2,  2, 2\n\t0x96960000, // 0, 0,  0, 0,  0, 0,  0, 0,  2, 1,  1, 2,  2, 1,  1, 2\n\t0xaaaa1414, // 0, 1,  1, 0,  0, 1,  1, 0,  2, 2,  2, 2,  2, 2,  2, 2\n\t0xa05050a0, // 0, 0,  2, 2,  0, 0,  1, 1,  0, 0,  1, 1,  0, 0,  2, 2\n\t0xa0a5a5a0, // 0, 0,  2, 2,  1, 1,  2, 2,  1, 1,  2, 2,  0, 0,  2, 2\n\t0x96000000, // 0, 0,  0, 0,  0, 0,  0, 0,  0, 0,  0, 0,  2, 1,  1, 2\n\t0x40804080, // 0, 0,  0, 2,  0, 0,  0, 1,  0, 0,  0, 2,  0, 0,  0, 1\n\t0xa9a8a9a8, // 0, 2,  2, 2,  1, 2,  2, 2,  0, 2,  2, 2,  1, 2,  2, 2\n\t0xaaaaaa44, // 0, 1,  0, 1,  2, 2,  2, 2,  2, 2,  2, 2,  2, 2,  2, 2\n\t0x2a4a5254, // 0, 1,  1, 1,  2, 0,  1, 1,  2, 2,  0, 1,  2, 2,  2, 0\n};\n\nstatic const uint8_t s_bptcA3[2][64] =\n{\n\t{\n\t\t 3,  3, 15, 15,  8,  3, 15, 15,\n\t\t 8,  8,  6,  6,  6,  5,  3,  3,\n\t\t 3,  3,  8, 15,  3,  3,  6, 10,\n\t\t 5,  8,  8,  6,  8,  5, 15, 15,\n\t\t 8, 15,  3,  5,  6, 10,  8, 15,\n\t\t15,  3, 15,  5, 15, 15, 15, 15,\n\t\t 3, 15,  5,  5,  5,  8,  5, 10,\n\t\t 5, 10,  8, 13, 15, 12,  3,  3,\n\t},\n\t{\n\t\t15,  8,  8,  3, 15, 15,  3,  8,\n\t\t15, 15, 15, 15, 15, 15, 15,  8,\n\t\t15,  8, 15,  3, 15,  8, 15,  8,\n\t\t 3, 15,  6, 10, 15, 15, 10,  8,\n\t\t15,  3, 15, 10, 10,  8,  9, 10,\n\t\t 6, 15,  8, 15,  3,  6,  6,  8,\n\t\t15,  3, 15, 15, 15, 15, 15, 15,\n\t\t15, 15, 15, 15,  3, 15, 15,  8,\n\t},\n};\n\nstruct Bc7ModeInfo\n{\n\tuint8_t numSubsets;\n\tuint8_t partitionBits;\n\tuint8_t rotationBits;\n\tuint8_t indexSelectionBits;\n\tuint8_t colorBits;\n\tuint8_t alphaBits;\n\tuint8_t endpointPBits;\n\tuint8_t sharedPBits;\n\tuint8_t indexBits[2];\n};\n\nstatic const Bc7ModeInfo s_bp7ModeInfo[] =\n{ //  +---------------------------- num subsets\n  //  |  +------------------------- partition bits\n  //  |  |  +---------------------- rotation bits\n  //  |  |  |  +------------------- index selection bits\n  //  |  |  |  |  +---------------- color bits\n  //  |  |  |  |  |  +------------- alpha bits\n  //  |  |  |  |  |  |  +---------- endpoint P-bits\n  //  |  |  |  |  |  |  |  +------- shared P-bits\n  //  |  |  |  |  |  |  |  |    +-- 2x index bits\n\t{ 3, 4, 0, 0, 4, 0, 1, 0, { 3, 0 } }, // 0\n\t{ 2, 6, 0, 0, 6, 0, 0, 1, { 3, 0 } }, // 1\n\t{ 3, 6, 0, 0, 5, 0, 0, 0, { 2, 0 } }, // 2\n\t{ 2, 6, 0, 0, 7, 0, 1, 0, { 2, 0 } }, // 3\n\t{ 1, 0, 2, 1, 5, 6, 0, 0, { 2, 3 } }, // 4\n\t{ 1, 0, 2, 0, 7, 8, 0, 0, { 2, 2 } }, // 5\n\t{ 1, 0, 0, 0, 7, 7, 1, 0, { 4, 0 } }, // 6\n\t{ 2, 6, 0, 0, 5, 5, 1, 0, { 2, 0 } }, // 7\n};\n\nstatic uint8_t expand_quantized(uint8_t v, int bits) {\n\tv = v << (8 - bits);\n\treturn v | (v >> bits);\n}\n\nstatic void decode_bc7_block(const uint8_t* _src, uint32_t* _dst)\n{\n\tBitReader bit(_src);\n\n\tuint8_t mode = 0;\n\tfor (; mode < 8 && 0 == bit.read(1); ++mode)\n\t{\n\t}\n\n\tif (mode == 8)\n\t{\n\t\tmemset(_dst, 0, 16 * 4);\n\t\treturn;\n\t}\n\n\tconst Bc7ModeInfo& mi = s_bp7ModeInfo[mode];\n\tconst uint8_t modePBits = 0 != mi.endpointPBits\n\t\t? mi.endpointPBits\n\t\t: mi.sharedPBits\n\t\t;\n\n\tconst uint8_t partitionSetIdx = uint8_t(bit.read(mi.partitionBits));\n\tconst uint8_t rotationMode = uint8_t(bit.read(mi.rotationBits));\n\tconst uint8_t indexSelectionMode = uint8_t(bit.read(mi.indexSelectionBits));\n\n\tuint8_t epR[6];\n\tuint8_t epG[6];\n\tuint8_t epB[6];\n\tuint8_t epA[6];\n\n\tfor (uint8_t ii = 0; ii < mi.numSubsets; ++ii)\n\t{\n\t\tepR[ii * 2 + 0] = uint8_t(bit.read(mi.colorBits) << modePBits);\n\t\tepR[ii * 2 + 1] = uint8_t(bit.read(mi.colorBits) << modePBits);\n\t}\n\n\tfor (uint8_t ii = 0; ii < mi.numSubsets; ++ii)\n\t{\n\t\tepG[ii * 2 + 0] = uint8_t(bit.read(mi.colorBits) << modePBits);\n\t\tepG[ii * 2 + 1] = uint8_t(bit.read(mi.colorBits) << modePBits);\n\t}\n\n\tfor (uint8_t ii = 0; ii < mi.numSubsets; ++ii)\n\t{\n\t\tepB[ii * 2 + 0] = uint8_t(bit.read(mi.colorBits) << modePBits);\n\t\tepB[ii * 2 + 1] = uint8_t(bit.read(mi.colorBits) << modePBits);\n\t}\n\n\tif (mi.alphaBits)\n\t{\n\t\tfor (uint8_t ii = 0; ii < mi.numSubsets; ++ii)\n\t\t{\n\t\t\tepA[ii * 2 + 0] = uint8_t(bit.read(mi.alphaBits) << modePBits);\n\t\t\tepA[ii * 2 + 1] = uint8_t(bit.read(mi.alphaBits) << modePBits);\n\t\t}\n\t}\n\telse\n\t{\n\t\tmemset(epA, 0xff, 6);\n\t}\n\n\tif (0 != modePBits)\n\t{\n\t\tfor (uint8_t ii = 0; ii < mi.numSubsets; ++ii)\n\t\t{\n\t\t\tconst uint8_t pda = uint8_t(bit.read(modePBits));\n\t\t\tconst uint8_t pdb = uint8_t(0 == mi.sharedPBits ? bit.read(modePBits) : pda);\n\n\t\t\tepR[ii * 2 + 0] |= pda;\n\t\t\tepR[ii * 2 + 1] |= pdb;\n\t\t\tepG[ii * 2 + 0] |= pda;\n\t\t\tepG[ii * 2 + 1] |= pdb;\n\t\t\tepB[ii * 2 + 0] |= pda;\n\t\t\tepB[ii * 2 + 1] |= pdb;\n\t\t\tepA[ii * 2 + 0] |= pda;\n\t\t\tepA[ii * 2 + 1] |= pdb;\n\t\t}\n\t}\n\n\tconst uint8_t colorBits = mi.colorBits + modePBits;\n\n\tfor (uint8_t ii = 0; ii < mi.numSubsets; ++ii)\n\t{\n\t\tepR[ii * 2 + 0] = expand_quantized(epR[ii * 2 + 0], colorBits);\n\t\tepR[ii * 2 + 1] = expand_quantized(epR[ii * 2 + 1], colorBits);\n\t\tepG[ii * 2 + 0] = expand_quantized(epG[ii * 2 + 0], colorBits);\n\t\tepG[ii * 2 + 1] = expand_quantized(epG[ii * 2 + 1], colorBits);\n\t\tepB[ii * 2 + 0] = expand_quantized(epB[ii * 2 + 0], colorBits);\n\t\tepB[ii * 2 + 1] = expand_quantized(epB[ii * 2 + 1], colorBits);\n\t}\n\n\tif (mi.alphaBits)\n\t{\n\t\tconst uint8_t alphaBits = mi.alphaBits + modePBits;\n\n\t\tfor (uint8_t ii = 0; ii < mi.numSubsets; ++ii)\n\t\t{\n\t\t\tepA[ii * 2 + 0] = expand_quantized(epA[ii * 2 + 0], alphaBits);\n\t\t\tepA[ii * 2 + 1] = expand_quantized(epA[ii * 2 + 1], alphaBits);\n\t\t}\n\t}\n\n\tconst bool hasIndexBits1 = 0 != mi.indexBits[1];\n\n\tconst uint8_t* factors[] =\n\t{\n\t\t\t\t\t\ts_bptcFactors[mi.indexBits[0] - 2],\n\t\thasIndexBits1 ? s_bptcFactors[mi.indexBits[1] - 2] : factors[0],\n\t};\n\n\tuint16_t offset[2] =\n\t{\n\t\t0,\n\t\tuint16_t(mi.numSubsets * (16 * mi.indexBits[0] - 1)),\n\t};\n\n\tfor (uint8_t yy = 0; yy < 4; ++yy)\n\t{\n\t\tfor (uint8_t xx = 0; xx < 4; ++xx)\n\t\t{\n\t\t\tconst uint8_t idx = yy * 4 + xx;\n\n\t\t\tuint8_t subsetIndex = 0;\n\t\t\tuint8_t indexAnchor = 0;\n\t\t\tswitch (mi.numSubsets)\n\t\t\t{\n\t\t\tcase 2:\n\t\t\t\tsubsetIndex = (s_bptcP2[partitionSetIdx] >> idx) & 1;\n\t\t\t\tindexAnchor = 0 != subsetIndex ? s_bptcA2[partitionSetIdx] : 0;\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tsubsetIndex = (s_bptcP3[partitionSetIdx] >> (2 * idx)) & 3;\n\t\t\t\tindexAnchor = 0 != subsetIndex ? s_bptcA3[subsetIndex - 1][partitionSetIdx] : 0;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst uint8_t anchor = idx == indexAnchor;\n\t\t\tconst uint8_t num[2] =\n\t\t\t{\n\t\t\t\tuint8_t(mi.indexBits[0] - anchor),\n\t\t\t\tuint8_t(hasIndexBits1 ? mi.indexBits[1] - anchor : 0),\n\t\t\t};\n\n\t\t\tconst uint8_t index[2] =\n\t\t\t{\n\t\t\t\t\t\t\t\t(uint8_t)bit.peek(offset[0], num[0]),\n\t\t\t\thasIndexBits1 ? (uint8_t)bit.peek(offset[1], num[1]) : index[0],\n\t\t\t};\n\n\t\t\toffset[0] += num[0];\n\t\t\toffset[1] += num[1];\n\n\t\t\tconst uint8_t fc = factors[indexSelectionMode][index[indexSelectionMode]];\n\t\t\tconst uint8_t fa = factors[!indexSelectionMode][index[!indexSelectionMode]];\n\n\t\t\tconst uint8_t fca = 64 - fc;\n\t\t\tconst uint8_t fcb = fc;\n\t\t\tconst uint8_t faa = 64 - fa;\n\t\t\tconst uint8_t fab = fa;\n\n\t\t\tsubsetIndex *= 2;\n\t\t\tuint8_t rr = uint8_t(uint16_t(epR[subsetIndex] * fca + epR[subsetIndex + 1] * fcb + 32) >> 6);\n\t\t\tuint8_t gg = uint8_t(uint16_t(epG[subsetIndex] * fca + epG[subsetIndex + 1] * fcb + 32) >> 6);\n\t\t\tuint8_t bb = uint8_t(uint16_t(epB[subsetIndex] * fca + epB[subsetIndex + 1] * fcb + 32) >> 6);\n\t\t\tuint8_t aa = uint8_t(uint16_t(epA[subsetIndex] * faa + epA[subsetIndex + 1] * fab + 32) >> 6);\n\n\t\t\tswitch (rotationMode)\n\t\t\t{\n\t\t\tcase 1: std::swap(aa, rr); break;\n\t\t\tcase 2: std::swap(aa, gg); break;\n\t\t\tcase 3: std::swap(aa, bb); break;\n\t\t\tdefault:                  break;\n\t\t\t};\n\n\t\t\t_dst[idx] = color(rr, gg, bb, aa);\n\t\t}\n\t}\n}\n\nint decode_bc7(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image) {\n\tuint32_t m_block_width = 4;\n\tuint32_t m_block_height = 4;\n\tuint32_t m_blocks_x = (m_width + m_block_width - 1) / m_block_width;\n\tuint32_t m_blocks_y = (m_height + m_block_height - 1) / m_block_height;\n\tuint32_t buffer[16];\n\tfor (uint32_t by = 0; by < m_blocks_y; by++) {\n\t\tfor (uint32_t bx = 0; bx < m_blocks_x; bx++, data += 16) {\n\t\t\tdecode_bc7_block(data, buffer);\n\t\t\tcopy_block_buffer(bx, by, m_width, m_height, m_block_width, m_block_height, buffer, image);\n\t\t}\n\t}\n\treturn 1;\n}"
  },
  {
    "path": "Texture2DDecoderNative/bcn.h",
    "content": "#pragma once\n#include <stdint.h>\n\nstruct color_bgra\n{\n\tuint8_t b;\n\tuint8_t g;\n\tuint8_t r;\n\tuint8_t a;\n};\n\nconst color_bgra g_black_color{ 0, 0, 0, 255 };\n\nint decode_bc1(const uint8_t* data, const long w, const long h, uint32_t* image);\nvoid decode_bc3_alpha(const uint8_t* data, uint32_t* outbuf, int channel);\nint decode_bc3(const uint8_t* data, const long w, const long h, uint32_t* image);\nint decode_bc4(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image);\nint decode_bc5(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image);\nint decode_bc6(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image);\nint decode_bc7(const uint8_t* data, uint32_t m_width, uint32_t m_height, uint32_t* image);"
  },
  {
    "path": "Texture2DDecoderNative/bool32_t.h",
    "content": "#pragma once\n\n#include <cstdint>\n\ntypedef uint32_t bool32_t;\n"
  },
  {
    "path": "Texture2DDecoderNative/color.h",
    "content": "#ifndef COLOR_H\n#define COLOR_H\n\n#include <stdint.h>\n#include <string.h>\n#include \"endianness.h\"\n\n#ifdef __LITTLE_ENDIAN__\nstatic const uint_fast32_t TRANSPARENT_MASK = 0x00ffffff;\n#else\nstatic const uint_fast32_t TRANSPARENT_MASK = 0xffffff00;\n#endif\n\nstatic inline uint_fast32_t color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {\n#ifdef __LITTLE_ENDIAN__\n    return b | g << 8 | r << 16 | a << 24;\n#else\n    return a | r << 8 | g << 16 | b << 24;\n#endif\n}\n\nstatic inline uint_fast32_t alpha_mask(uint8_t a) {\n#ifdef __LITTLE_ENDIAN__\n    return TRANSPARENT_MASK | a << 24;\n#else\n    return TRANSPARENT_MASK | a;\n#endif\n}\n\nstatic inline void rgb565_le(const uint16_t d, uint8_t *r, uint8_t *g, uint8_t *b) {\n#ifdef __LITTLE_ENDIAN__\n    *r = (d >> 8 & 0xf8) | (d >> 13);\n    *g = (d >> 3 & 0xfc) | (d >> 9 & 3);\n    *b = (d << 3) | (d >> 2 & 7);\n#else\n    *r = (d & 0xf8) | (d >> 5 & 7);\n    *g = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3);\n    *b = (d >> 5 & 0xf8) | (d >> 10 & 0x7);\n#endif\n}\n\nstatic inline void rgb565_be(const uint16_t d, uint8_t *r, uint8_t *g, uint8_t *b) {\n#ifdef __BIG_ENDIAN__\n    *r = (d >> 8 & 0xf8) | (d >> 13);\n    *g = (d >> 3 & 0xfc) | (d >> 9 & 3);\n    *b = (d << 3) | (d >> 2 & 7);\n#else\n    *r = (d & 0xf8) | (d >> 5 & 7);\n    *g = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3);\n    *b = (d >> 5 & 0xf8) | (d >> 10 & 0x7);\n#endif\n}\n\nstatic inline void rgb565_lep(const uint16_t d, uint8_t *c) {\n#ifdef __LITTLE_ENDIAN__\n    *(c++) = (d >> 8 & 0xf8) | (d >> 13);\n    *(c++) = (d >> 3 & 0xfc) | (d >> 9 & 3);\n    *(c++) = (d << 3) | (d >> 2 & 7);\n#else\n    *(c++) = (d & 0xf8) | (d >> 5 & 7);\n    *(c++) = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3);\n    *(c++) = (d >> 5 & 0xf8) | (d >> 10 & 0x7);\n#endif\n}\n\nstatic inline void rgb565_bep(const uint16_t d, uint8_t *c) {\n#ifdef __BIG_ENDIAN__\n    *(c++) = (d >> 8 & 0xf8) | (d >> 13);\n    *(c++) = (d >> 3 & 0xfc) | (d >> 9 & 3);\n    *(c++) = (d << 3) | (d >> 2 & 7);\n#else\n    *(c++) = (d & 0xf8) | (d >> 5 & 7);\n    *(c++) = (d << 5 & 0xe0) | (d >> 11 & 0x1c) | (d >> 1 & 3);\n    *(c++) = (d >> 5 & 0xf8) | (d >> 10 & 0x7);\n#endif\n}\n\nstatic inline void copy_block_buffer(const long bx, const long by, const long w, const long h, const long bw,\n                                     const long bh, const uint32_t *buffer, uint32_t *image) {\n    long x = bw * bx;\n    long xl = (bw * (bx + 1) > w ? w - bw * bx : bw) * 4;\n    const uint32_t *buffer_end = buffer + bw * bh;\n    for (long y = by * bh; buffer < buffer_end && y < h; buffer += bw, y++)\n        memcpy(image + y * w + x, buffer, xl);\n}\n\n#endif /* end of include guard: COLOR_H */\n"
  },
  {
    "path": "Texture2DDecoderNative/cpp.hint",
    "content": "#define T2D_API(ret_type)\n"
  },
  {
    "path": "Texture2DDecoderNative/crunch/crn_decomp.h",
    "content": "// File: crn_decomp.h - Fast CRN->DXTc texture transcoder header file library\n// Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved.\n// See Copyright Notice and license at the end of this file.\n//\n// This single header file contains *all* of the code necessary to unpack .CRN files to raw DXTn bits.\n// It does NOT depend on the crn compression library.\n//\n// Note: This is a single file, stand-alone C++ library which is controlled by the use of two macros:\n//   If CRND_INCLUDE_CRND_H is NOT defined, the header is included.\n//   If CRND_HEADER_FILE_ONLY is NOT defined, the implementation is included.\n//\n// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing\n#ifndef CRND_INCLUDE_CRND_H\n#define CRND_INCLUDE_CRND_H\n\n// Include crnlib.h (only to bring in some basic CRN-related types).\n#include \"crnlib.h\"\n\n#define CRND_LIB_VERSION 104\n#define CRND_VERSION_STRING \"01.04\"\n\n#ifdef _DEBUG\n#define CRND_BUILD_DEBUG\n#else\n#define CRND_BUILD_RELEASE\n#endif\n\n// CRN decompression API\nnamespace crnd\n{\n   typedef unsigned char      uint8;\n   typedef signed char        int8;\n   typedef unsigned short     uint16;\n   typedef signed short       int16;\n   typedef unsigned int       uint32;\n   typedef uint32             uint32;\n   typedef unsigned int       uint;\n   typedef signed int         int32;\n   #ifdef __GNUC__\n      typedef unsigned long long    uint64;\n      typedef long long             int64;\n   #else\n      typedef unsigned __int64      uint64;\n      typedef signed __int64        int64;\n   #endif\n\n   // The crnd library assumes all allocation blocks have at least CRND_MIN_ALLOC_ALIGNMENT alignment.\n   const uint32 CRND_MIN_ALLOC_ALIGNMENT = sizeof(uint32) * 2U;\n\n   // realloc callback:\n   // Used to allocate, resize, or free memory blocks.\n   // If p is NULL, the realloc function attempts to allocate a block of at least size bytes. Returns NULL on out of memory.\n   // *pActual_size must be set to the actual size of the allocated block, which must be greater than or equal to the requested size.\n   // If p is not NULL, and size is 0, the realloc function frees the specified block, and always returns NULL. *pActual_size should be set to 0.\n   // If p is not NULL, and size is non-zero, the realloc function attempts to resize the specified block:\n   //    If movable is false, the realloc function attempts to shrink or expand the block in-place. NULL is returned if the block cannot be resized in place, or if the\n   //    underlying heap implementation doesn't support in-place resizing. Otherwise, the pointer to the original block is returned.\n   //    If movable is true, it is permissible to move the block's contents if it cannot be resized in place. NULL is returned if the block cannot be resized in place, and there\n   //    is not enough memory to relocate the block.\n   //    In all cases, *pActual_size must be set to the actual size of the allocated block, whether it was successfully resized or not.\n   typedef void*  (*crnd_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data);\n\n   // msize callback: Returns the size of the memory block in bytes, or 0 if the pointer or block is invalid.\n   typedef size_t (*crnd_msize_func)(void* p, void* pUser_data);\n\n   // crnd_set_memory_callbacks() - Use to override the crnd library's memory allocation functions.\n   // If any input parameters are NULL, the memory callback functions are reset to the default functions.\n   // The default functions call malloc(), free(),  _msize(), _expand(), etc.\n   void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data);\n\n   struct crn_file_info\n   {\n      inline crn_file_info() : m_struct_size(sizeof(crn_file_info)) { }\n\n      uint32 m_struct_size;\n      uint32 m_actual_data_size;\n      uint32 m_header_size;\n      uint32 m_total_palette_size;\n      uint32 m_tables_size;\n      uint32 m_levels;\n      uint32 m_level_compressed_size[cCRNMaxLevels];\n      uint32 m_color_endpoint_palette_entries;\n      uint32 m_color_selector_palette_entries;\n      uint32 m_alpha_endpoint_palette_entries;\n      uint32 m_alpha_selector_palette_entries;\n   };\n\n   struct crn_texture_info\n   {\n      inline crn_texture_info() : m_struct_size(sizeof(crn_texture_info)) { }\n\n      uint32      m_struct_size;\n      uint32      m_width;\n      uint32      m_height;\n      uint32      m_levels;\n      uint32      m_faces;\n      uint32      m_bytes_per_block;\n      uint32      m_userdata0;\n      uint32      m_userdata1;\n      crn_format  m_format;\n   };\n\n   struct crn_level_info\n   {\n      inline crn_level_info() : m_struct_size(sizeof(crn_level_info)) { }\n\n      uint32      m_struct_size;\n      uint32      m_width;\n      uint32      m_height;\n      uint32      m_faces;\n      uint32      m_blocks_x;\n      uint32      m_blocks_y;\n      uint32      m_bytes_per_block;\n      crn_format  m_format;\n   };\n\n   // Returns the FOURCC format code corresponding to the specified CRN format.\n   uint32 crnd_crn_format_to_fourcc(crn_format fmt);\n\n   // Returns the fundamental GPU format given a potentially swizzled DXT5 crn_format.\n   crn_format crnd_get_fundamental_dxt_format(crn_format fmt);\n\n   // Returns the size of the crn_format in bits/texel (either 4 or 8).\n   uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt);\n\n   // Returns the number of bytes per DXTn block (8 or 16).\n   uint32 crnd_get_bytes_per_dxt_block(crn_format fmt);\n\n   // Validates the entire file by checking the header and data CRC's.\n   // This is not something you want to be doing much!\n   // The crn_file_info.m_struct_size field must be set before calling this function.\n   bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info);\n\n   // Retrieves texture information from the CRN file.\n   // The crn_texture_info.m_struct_size field must be set before calling this function.\n   bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pTexture_info);\n\n   // Retrieves mipmap level specific information from the CRN file.\n   // The crn_level_info.m_struct_size field must be set before calling this function.\n   bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info);\n\n   // Transcode/unpack context handle.\n   typedef void* crnd_unpack_context;\n\n   // crnd_unpack_begin() - Decompresses the texture's decoder tables and endpoint/selector palettes.\n   // Once you call this function, you may call crnd_unpack_level() to unpack one or more mip levels.\n   // Don't call this once per mip level (unless you absolutely must)!\n   // This function allocates enough memory to hold: Huffman decompression tables, and the endpoint/selector palettes (color and/or alpha).\n   // Worst case allocation is approx. 200k, assuming all palettes contain 8192 entries.\n   // pData must point to a buffer holding all of the compressed .CRN file data.\n   // This buffer must be stable until crnd_unpack_end() is called.\n   // Returns NULL if out of memory, or if any of the input parameters are invalid.\n   crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size);\n\n   // Returns a pointer to the compressed .CRN data associated with a crnd_unpack_context.\n   // Returns false if any of the input parameters are invalid.\n   bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size);\n\n   // crnd_unpack_level() - Transcodes the specified mipmap level to a destination buffer in cached or write combined memory.\n   // pContext - Context created by a call to crnd_unpack_begin().\n   // ppDst - A pointer to an array of 1 or 6 destination buffer pointers. Cubemaps require an array of 6 pointers, 2D textures require an array of 1 pointer.\n   // dst_size_in_bytes - Optional size of each destination buffer. Only used for debugging - OK to set to UINT32_MAX.\n   // row_pitch_in_bytes - The pitch in bytes from one row of DXT blocks to the next. Must be a multiple of 4.\n   // level_index - mipmap level index, where 0 is the largest/first level.\n   // Returns false if any of the input parameters, or the compressed stream, are invalid.\n   // This function does not allocate any memory.\n   bool crnd_unpack_level(\n      crnd_unpack_context pContext,\n      void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n      uint32 level_index);\n\n   // crnd_unpack_level_segmented() - Unpacks the specified mipmap level from a \"segmented\" CRN file.\n   // See the crnd_create_segmented_file() API below.\n   // Segmented files allow the user to control where the compressed mipmap data is stored.\n   bool crnd_unpack_level_segmented(\n      crnd_unpack_context pContext,\n      const void* pSrc, uint32 src_size_in_bytes,\n      void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n      uint32 level_index);\n\n   // crnd_unpack_end() - Frees the decompress tables and unpacked palettes associated with the specified unpack context.\n   // Returns false if the context is NULL, or if it points to an invalid context.\n   // This function frees all memory associated with the context.\n   bool crnd_unpack_end(crnd_unpack_context pContext);\n\n   // The following API's allow the user to create \"segmented\" CRN files. A segmented file contains multiple pieces:\n   // - Base data: Header + compression tables\n   // - Level data: Individual mipmap levels\n   // This allows mipmap levels from multiple CRN files to be tightly packed together into single files.\n\n   // Returns a pointer to the level's compressed data, and optionally returns the level's compressed data size if pSize is not NULL.\n   const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize);\n\n   // Returns the compressed size of the texture's header and compression tables (but no levels).\n   uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size);\n\n   // Creates a \"segmented\" CRN texture from a normal CRN texture. The new texture will be created at pBase_data, and will be crnd_get_base_data_size() bytes long.\n   // base_data_size must be >= crnd_get_base_data_size().\n   // The base data will contain the CRN header and compression tables, but no mipmap data.\n   bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size);\n\n} // namespace crnd\n\n// Low-level CRN file header cracking.\nnamespace crnd\n{\n   template<unsigned int N>\n   struct crn_packed_uint\n   {\n      inline crn_packed_uint() { }\n\n      inline crn_packed_uint(unsigned int val) { *this = val; }\n\n      inline crn_packed_uint(const crn_packed_uint& other) { *this = other; }\n\n      inline crn_packed_uint& operator= (const crn_packed_uint& rhs)\n      {\n         if (this != &rhs)\n            memcpy(m_buf, rhs.m_buf, sizeof(m_buf));\n         return *this;\n      }\n\n      inline crn_packed_uint& operator= (unsigned int val)\n      {\n         //CRND_ASSERT((N == 4U) || (val < (1U << (N * 8U))));\n\n         val <<= (8U * (4U - N));\n\n         for (unsigned int i = 0; i < N; i++)\n         {\n            m_buf[i] = static_cast<unsigned char>(val >> 24U);\n            val <<= 8U;\n         }\n\n         return *this;\n      }\n\n      inline operator unsigned int() const\n      {\n         switch (N)\n         {\n         case 1:  return  m_buf[0];\n         case 2:  return (m_buf[0] <<  8U) |  m_buf[1];\n         case 3:  return (m_buf[0] << 16U) | (m_buf[1] <<  8U) | (m_buf[2]);\n         default: return (m_buf[0] << 24U) | (m_buf[1] << 16U) | (m_buf[2] << 8U) | (m_buf[3]);\n         }\n      }\n\n      unsigned char m_buf[N];\n   };\n\n#pragma pack(push)\n#pragma pack(1)\n   struct crn_palette\n   {\n      crn_packed_uint<3> m_ofs;\n      crn_packed_uint<3> m_size;\n      crn_packed_uint<2> m_num;\n   };\n\n   enum crn_header_flags\n   {\n      // If set, the compressed mipmap level data is not located after the file's base data - it will be separately managed by the user instead.\n      cCRNHeaderFlagSegmented = 1\n   };\n\n   struct crn_header\n   {\n      enum { cCRNSigValue = ('H' << 8) | 'x' };\n\n      crn_packed_uint<2>    m_sig;\n      crn_packed_uint<2>    m_header_size;\n      crn_packed_uint<2>    m_header_crc16;\n\n      crn_packed_uint<4>    m_data_size;\n      crn_packed_uint<2>    m_data_crc16;\n\n      crn_packed_uint<2>    m_width;\n      crn_packed_uint<2>    m_height;\n\n      crn_packed_uint<1>    m_levels;\n      crn_packed_uint<1>    m_faces;\n\n      crn_packed_uint<1>    m_format;\n      crn_packed_uint<2>    m_flags;\n\n      crn_packed_uint<4>    m_reserved;\n      crn_packed_uint<4>    m_userdata0;\n      crn_packed_uint<4>    m_userdata1;\n\n      crn_palette           m_color_endpoints;\n      crn_palette           m_color_selectors;\n\n      crn_palette           m_alpha_endpoints;\n      crn_palette           m_alpha_selectors;\n\n      crn_packed_uint<2>    m_tables_size;\n      crn_packed_uint<3>    m_tables_ofs;\n\n      // m_level_ofs[] is actually an array of offsets: m_level_ofs[m_levels]\n      crn_packed_uint<4>    m_level_ofs[1];\n   };\n\n   const unsigned int cCRNHeaderMinSize = 62U;\n\n#pragma pack(pop)\n\n} // namespace crnd\n\n#endif // CRND_INCLUDE_CRND_H\n\n// Internal library source follows this line.\n\n#ifndef CRND_HEADER_FILE_ONLY\n\n#include <stdlib.h>\n#include <stdio.h>\n#ifdef _WIN32\n#include <memory.h>\n#else\n#include <malloc.h>\n#endif\n#include <stdarg.h>\n#include <new> // needed for placement new, _msize, _expand\n\n#define CRND_RESTRICT __restrict\n\n#ifdef _MSC_VER\n#include <intrin.h>\n#pragma intrinsic(_WriteBarrier)\n#pragma intrinsic(_ReadWriteBarrier)\n#define CRND_WRITE_BARRIER _WriteBarrier();\n#define CRND_FULL_BARRIER _ReadWriteBarrier();\n#else\n#define CRND_WRITE_BARRIER\n#define CRND_FULL_BARRIER\n#endif\n\n#ifdef _MSC_VER\n#pragma warning(disable:4127) // warning C4127: conditional expression is constant\n#endif\n\n#ifdef CRND_DEVEL\n#ifndef _WIN32_WINNT\n#define _WIN32_WINNT 0x500\n#endif\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#ifndef\n#define NOMINMAX\n#endif\n#include \"windows.h\" // only for IsDebuggerPresent(), DebugBreak(), and OutputDebugStringA()\n#endif\n\n// File: crnd_types.h\nnamespace crnd\n{\n   const crn_uint8 cUINT8_MIN  = 0;\n   const crn_uint8 cUINT8_MAX  = 0xFFU;\n   const uint16 cUINT16_MIN = 0;\n   const uint16 cUINT16_MAX = 0xFFFFU;\n   const uint32 cUINT32_MIN = 0;\n   const uint32 cUINT32_MAX = 0xFFFFFFFFU;\n\n   const int8  cINT8_MIN  = -128;\n   const int8  cINT8_MAX  = 127;\n   const int16 cINT16_MIN = -32768;\n   const int16 cINT16_MAX = 32767;\n   const int32 cINT32_MIN = (-2147483647 - 1);\n   const int32 cINT32_MAX = 2147483647;\n\n   enum eClear { cClear };\n\n   const uint32 cIntBits = 32U;\n\n#ifdef _WIN64\n   typedef uint64 ptr_bits;\n#else\n   #ifdef __x86_64__\n      typedef uint64 ptr_bits;\n   #else\n      typedef uint32 ptr_bits;\n   #endif\n#endif\n\n   template<typename T> struct int_traits { enum { cMin = crnd::cINT32_MIN, cMax = crnd::cINT32_MAX, cSigned = true }; };\n\n   template<> struct int_traits<int8> { enum { cMin = crnd::cINT8_MIN, cMax = crnd::cINT8_MAX, cSigned = true }; };\n   template<> struct int_traits<int16> { enum { cMin = crnd::cINT16_MIN, cMax = crnd::cINT16_MAX, cSigned = true }; };\n   template<> struct int_traits<int32> { enum { cMin = crnd::cINT32_MIN, cMax = crnd::cINT32_MAX, cSigned = true }; };\n\n   template<> struct int_traits<uint8> { enum { cMin = 0, cMax = crnd::cUINT8_MAX, cSigned = false }; };\n   template<> struct int_traits<uint16> { enum { cMin = 0, cMax = crnd::cUINT16_MAX, cSigned = false }; };\n   template<> struct int_traits<uint32> { enum { cMin = 0, cMax = crnd::cUINT32_MAX, cSigned = false }; };\n\n   struct empty_type { };\n\n} // namespace crnd\n\n// File: crnd_platform.h\nnamespace crnd\n{\n#ifdef _XBOX\n   const bool c_crnd_little_endian_platform = false;\n   const bool c_crnd_big_endian_platform = true;\n#define CRND_BIG_ENDIAN_PLATFORM 1\n#else\n   const bool c_crnd_little_endian_platform = true;\n   const bool c_crnd_big_endian_platform = false;\n#endif\n\n   bool crnd_is_debugger_present();\n   void crnd_debug_break();\n   void crnd_output_debug_string(const char* p);\n\n   // actually in crnd_assert.cpp\n   void crnd_assert(const char* pExp, const char* pFile, unsigned line);\n   void crnd_fail(const char* pExp, const char* pFile, unsigned line);\n\n} // namespace crnd\n\n// File: crnd_assert.h\nnamespace crnd\n{\n   void crnd_assert(const char* pExp, const char* pFile, unsigned line);\n\n#ifdef NDEBUG\n#define CRND_ASSERT(x) ((void)0)\n#undef  CRND_ASSERTS_ENABLED\n#else\n#define CRND_ASSERT(_exp) (void)( (!!(_exp)) || (crnd::crnd_assert(#_exp, __FILE__, __LINE__), 0) )\n#define CRND_ASSERTS_ENABLED\n#endif\n\n   void crnd_trace(const char* pFmt, va_list args);\n   void crnd_trace(const char* pFmt, ...);\n\n} // namespace crnd\n\n// File: crnd_helpers.h\nnamespace crnd\n{\n   namespace helpers\n   {\n      template<typename T> struct rel_ops\n      {\n         friend bool operator!= (const T& x, const T& y) { return (!(x == y)); }\n         friend bool operator>  (const T& x, const T& y) { return (y < x); }\n         friend bool operator<= (const T& x, const T& y) { return (!(y < x)); }\n         friend bool operator>= (const T& x, const T& y) { return (!(x < y)); }\n      };\n\n      template <typename T>\n      inline T* construct(T* p)\n      {\n         return new (static_cast<void*>(p)) T;\n      }\n\n      template <typename T, typename U>\n      inline T* construct(T* p, const U& init)\n      {\n         return new (static_cast<void*>(p)) T(init);\n      }\n\n      template <typename T>\n      void construct_array(T* p, uint32 n)\n      {\n         T* q = p + n;\n         for ( ; p != q; ++p)\n            new (static_cast<void*>(p)) T;\n      }\n\n      template <typename T, typename U>\n      void construct_array(T* p, uint32 n, const U& init)\n      {\n         T* q = p + n;\n         for ( ; p != q; ++p)\n            new (static_cast<void*>(p)) T(init);\n      }\n\n      template <typename T>\n      inline void destruct(T* p)\n      {\n         p;\n         p->~T();\n      }\n\n      template <typename T> inline void destruct_array(T* p, uint32 n)\n      {\n         T* q = p + n;\n         for ( ; p != q; ++p)\n            p->~T();\n      }\n\n   }  // namespace helpers\n\n}  // namespace crnd\n\n// File: crnd_traits.h\nnamespace crnd\n{\n   template<typename T>\n   struct scalar_type\n   {\n      enum { cFlag = false };\n      static inline void construct(T* p) { helpers::construct(p); }\n      static inline void construct(T* p, const T& init) { helpers::construct(p, init); }\n      static inline void construct_array(T* p, uint32 n) { helpers::construct_array(p, n); }\n      static inline void destruct(T* p) { helpers::destruct(p); }\n      static inline void destruct_array(T* p, uint32 n) { helpers::destruct_array(p, n); }\n   };\n\n   template<typename T> struct scalar_type<T*>\n   {\n      enum { cFlag = true };\n      static inline void construct(T** p) { memset(p, 0, sizeof(T*)); }\n      static inline void construct(T** p, T* init) { *p = init; }\n      static inline void construct_array(T** p, uint32 n) { memset(p, 0, sizeof(T*) * n); }\n      static inline void destruct(T** p) { p; }\n      static inline void destruct_array(T** p, uint32 n) { p, n; }\n   };\n\n#define CRND_DEFINE_BUILT_IN_TYPE(X) \\\n   template<> struct scalar_type<X> { \\\n   enum { cFlag = true }; \\\n   static inline void construct(X* p) { memset(p, 0, sizeof(X)); } \\\n   static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); } \\\n   static inline void construct_array(X* p, uint32 n) { memset(p, 0, sizeof(X) * n); } \\\n   static inline void destruct(X* p) { p; } \\\n   static inline void destruct_array(X* p, uint32 n) { p, n; } };\n\n   CRND_DEFINE_BUILT_IN_TYPE(bool)\n   CRND_DEFINE_BUILT_IN_TYPE(char)\n   CRND_DEFINE_BUILT_IN_TYPE(unsigned char)\n   CRND_DEFINE_BUILT_IN_TYPE(short)\n   CRND_DEFINE_BUILT_IN_TYPE(unsigned short)\n   CRND_DEFINE_BUILT_IN_TYPE(int)\n   CRND_DEFINE_BUILT_IN_TYPE(unsigned int)\n   CRND_DEFINE_BUILT_IN_TYPE(long)\n   CRND_DEFINE_BUILT_IN_TYPE(unsigned long)\n   CRND_DEFINE_BUILT_IN_TYPE(int64)\n   CRND_DEFINE_BUILT_IN_TYPE(uint64)\n   CRND_DEFINE_BUILT_IN_TYPE(float)\n   CRND_DEFINE_BUILT_IN_TYPE(double)\n   CRND_DEFINE_BUILT_IN_TYPE(long double)\n\n#undef CRND_DEFINE_BUILT_IN_TYPE\n\n   // See: http://erdani.org/publications/cuj-2004-06.pdf\n\n   template<typename T>\n   struct bitwise_movable { enum { cFlag = false }; };\n\n   // Defines type Q as bitwise movable.\n#define CRND_DEFINE_BITWISE_MOVABLE(Q) template<> struct bitwise_movable<Q> { enum { cFlag = true }; };\n\n   // From yasli_traits.h:\n   // Credit goes to Boost;\n   // also found in the C++ Templates book by Vandevoorde and Josuttis\n\n   typedef char (&yes_t)[1];\n   typedef char (&no_t)[2];\n\n   template <class U> yes_t class_test(int U::*);\n   template <class U> no_t class_test(...);\n\n   template <class T> struct is_class\n   {\n      enum { value = (sizeof(class_test<T>(0)) == sizeof(yes_t)) };\n   };\n\n   template <typename T> struct is_pointer\n   {\n      enum { value = false };\n   };\n\n   template <typename T> struct is_pointer<T*>\n   {\n      enum { value = true };\n   };\n\n#define CRND_IS_POD(T) __is_pod(T)\n\n} // namespace crnd\n\n// File: crnd_mem.h\nnamespace crnd\n{\n   void*    crnd_malloc(size_t size, size_t* pActual_size = NULL);\n   void*    crnd_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true);\n   void     crnd_free(void* p);\n   size_t   crnd_msize(void* p);\n\n   template<typename T>\n   inline T* crnd_new()\n   {\n      T* p = static_cast<T*>(crnd_malloc(sizeof(T)));\n      if (!p)\n         return NULL;\n\n      return helpers::construct(p);\n   }\n\n   template<typename T>\n   inline T* crnd_new(const T& init)\n   {\n      T* p = static_cast<T*>(crnd_malloc(sizeof(T)));\n      if (!p)\n         return NULL;\n\n      return helpers::construct(p, init);\n   }\n\n   template<typename T>\n   inline T* crnd_new_array(uint32 num)\n   {\n      if (!num) num = 1;\n\n      uint8* q = static_cast<uint8*>(crnd_malloc(CRND_MIN_ALLOC_ALIGNMENT + sizeof(T) * num));\n      if (!q)\n         return NULL;\n\n      T* p = reinterpret_cast<T*>(q + CRND_MIN_ALLOC_ALIGNMENT);\n\n      reinterpret_cast<uint32*>(p)[-1] = num;\n      reinterpret_cast<uint32*>(p)[-2] = ~num;\n\n      helpers::construct_array(p, num);\n      return p;\n   }\n\n   template<typename T>\n   inline void crnd_delete(T* p)\n   {\n      if (p)\n      {\n         helpers::destruct(p);\n         crnd_free(p);\n      }\n   }\n\n   template<typename T>\n   inline void crnd_delete_array(T* p)\n   {\n      if (p)\n      {\n         const uint32 num = reinterpret_cast<uint32*>(p)[-1];\n         const uint32 num_check = reinterpret_cast<uint32*>(p)[-2];\n         num_check;\n         CRND_ASSERT(num && (num == ~num_check));\n\n         helpers::destruct_array(p, num);\n\n         crnd_free(reinterpret_cast<uint8*>(p) - CRND_MIN_ALLOC_ALIGNMENT);\n      }\n   }\n\n} // namespace crnd\n\n// File: crnd_math.h\nnamespace crnd\n{\n   namespace math\n   {\n      const float cNearlyInfinite = 1.0e+37f;\n\n      const float cDegToRad = 0.01745329252f;\n      const float cRadToDeg = 57.29577951f;\n\n      extern uint32 g_bitmasks[32];\n\n      // Yes I know these should probably be pass by ref, not val:\n      // http://www.stepanovpapers.com/notes.pdf\n      // Just don't use them on non-simple (non built-in) types!\n      template<typename T> inline T minimum(T a, T b)\n      {\n         return (a < b) ? a : b;\n      }\n\n      template<typename T> inline T minimum(T a, T b, T c)\n      {\n         return minimum(minimum(a, b), c);\n      }\n\n      template<typename T> inline T maximum(T a, T b)\n      {\n         return (a > b) ? a : b;\n      }\n\n      template<typename T> inline T maximum(T a, T b, T c)\n      {\n         return maximum(maximum(a, b), c);\n      }\n\n      template<typename T> inline T clamp(T value, T low, T high)\n      {\n         return (value < low) ? low : ((value > high) ? high : value);\n      }\n\n      template<typename T> inline T square(T value)\n      {\n         return value * value;\n      }\n\n      inline bool is_power_of_2(uint32 x)\n      {\n         return x && ((x & (x - 1U)) == 0U);\n      }\n\n      // From \"Hackers Delight\"\n      inline int next_pow2(uint32 val)\n      {\n         val--;\n         val |= val >> 16;\n         val |= val >> 8;\n         val |= val >> 4;\n         val |= val >> 2;\n         val |= val >> 1;\n         return val + 1;\n      }\n\n      // Returns the total number of bits needed to encode v.\n      inline uint32 total_bits(uint32 v)\n      {\n         uint32 l = 0;\n         while (v > 0U)\n         {\n            v >>= 1;\n            l++;\n         }\n         return l;\n      }\n\n      inline uint floor_log2i(uint v)\n      {\n         uint l = 0;\n         while (v > 1U)\n         {\n            v >>= 1;\n            l++;\n         }\n         return l;\n      }\n\n      inline uint ceil_log2i(uint v)\n      {\n         uint l = floor_log2i(v);\n         if ((l != cIntBits) && (v > (1U << l)))\n            l++;\n         return l;\n      }\n   }\n}\n\n// File: crnd_utils.h\nnamespace crnd\n{\n   namespace utils\n   {\n      template<typename T> inline void zero_object(T& obj)\n      {\n         memset(&obj, 0, sizeof(obj));\n      }\n\n      template<typename T> inline void zero_this(T* pObj)\n      {\n         memset(pObj, 0, sizeof(*pObj));\n      }\n\n      template <typename T>\n      inline void swap(T& left, T& right)\n      {\n         T temp(left);\n         left = right;\n         right = temp;\n      }\n\n      inline void invert_buf(void* pBuf, uint32 size)\n      {\n         uint8* p = static_cast<uint8*>(pBuf);\n\n         const uint32 half_size = size >> 1;\n         for (uint32 i = 0; i < half_size; i++)\n            swap(p[i], p[size - 1U - i]);\n      }\n\n      static inline uint16 swap16(uint16 x) { return static_cast<uint16>((x << 8) | (x >> 8)); }\n      static inline uint32 swap32(uint32 x) { return ((x << 24) | ((x << 8) & 0x00FF0000) | (( x >> 8) & 0x0000FF00) | (x >> 24)); }\n\n      uint32 compute_max_mips(uint32 width, uint32 height);\n\n   }   // namespace utils\n\n} // namespace crnd\n\n// File: crnd_vector.h\nnamespace crnd\n{\n   struct elemental_vector\n   {\n      void* m_p;\n      uint32 m_size;\n      uint32 m_capacity;\n\n      typedef void (*object_mover)(void* pDst, void* pSrc, uint32 num);\n\n      bool increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pRelocate);\n   };\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable:4127) //  warning C4127: conditional expression is constant\n#endif\n\n   template<typename T>\n   class vector : public helpers::rel_ops< vector<T> >\n   {\n   public:\n      typedef T*              iterator;\n      typedef const T*        const_iterator;\n      typedef T               value_type;\n      typedef T&              reference;\n      typedef const T&        const_reference;\n      typedef T*              pointer;\n      typedef const T*        const_pointer;\n\n      inline vector() :\n         m_p(NULL),\n         m_size(0),\n         m_capacity(0),\n         m_alloc_failed(false)\n      {\n      }\n\n      inline vector(const vector& other) :\n         m_p(NULL),\n         m_size(0),\n         m_capacity(0),\n         m_alloc_failed(false)\n      {\n         *this = other;\n      }\n\n      inline vector(uint32 size) :\n         m_p(NULL),\n         m_size(0),\n         m_capacity(0),\n         m_alloc_failed(false)\n      {\n         resize(size);\n      }\n\n      inline ~vector()\n      {\n         clear();\n      }\n\n      // I don't like this. Not at all. But exceptions, or just failing suck worse.\n      inline bool get_alloc_failed() const { return m_alloc_failed; }\n      inline void clear_alloc_failed() { m_alloc_failed = false; }\n\n      inline bool assign(const vector& other)\n      {\n         if (this == &other)\n            return true;\n\n         if (m_capacity == other.m_size)\n            resize(0);\n         else\n         {\n            clear();\n\n            if (!increase_capacity(other.m_size, false))\n               return false;\n         }\n\n         if (scalar_type<T>::cFlag)\n            memcpy(m_p, other.m_p, other.m_size * sizeof(T));\n         else\n         {\n            T* pDst = m_p;\n            const T* pSrc = other.m_p;\n            for (uint32 i = other.m_size; i > 0; i--)\n               helpers::construct(pDst++, *pSrc++);\n         }\n\n         m_size = other.m_size;\n\n         return true;\n      }\n\n      inline vector& operator= (const vector& other)\n      {\n         assign(other);\n         return *this;\n      }\n\n      inline const   T* begin() const  { return m_p; }\n      T* begin()        { return m_p; }\n\n      inline const   T* end() const  { return m_p + m_size; }\n      T* end()        { return m_p + m_size; }\n\n      inline bool empty() const { return !m_size; }\n      inline uint32 size() const { return m_size; }\n      inline uint32 capacity() const { return m_capacity; }\n\n      inline const T& operator[] (uint32 i) const  { CRND_ASSERT(i < m_size); return m_p[i]; }\n      inline       T& operator[] (uint32 i)        { CRND_ASSERT(i < m_size); return m_p[i]; }\n\n      inline const T& front() const  { CRND_ASSERT(m_size); return m_p[0]; }\n      inline       T& front()        { CRND_ASSERT(m_size); return m_p[0]; }\n\n      inline const T& back() const  { CRND_ASSERT(m_size); return m_p[m_size - 1]; }\n      inline       T& back()        { CRND_ASSERT(m_size); return m_p[m_size - 1]; }\n\n      inline void clear()\n      {\n         if (m_p)\n         {\n            scalar_type<T>::destruct_array(m_p, m_size);\n            crnd_free(m_p);\n            m_p = NULL;\n            m_size = 0;\n            m_capacity = 0;\n         }\n\n         m_alloc_failed = false;\n      }\n\n      inline bool reserve(uint32 new_capacity)\n      {\n         if (!increase_capacity(new_capacity, false))\n            return false;\n\n         return true;\n      }\n\n      inline bool resize(uint32 new_size)\n      {\n         if (m_size != new_size)\n         {\n            if (new_size < m_size)\n               scalar_type<T>::destruct_array(m_p + new_size, m_size - new_size);\n            else\n            {\n               if (new_size > m_capacity)\n               {\n                  if (!increase_capacity(new_size, new_size == (m_size + 1)))\n                     return false;\n               }\n\n               scalar_type<T>::construct_array(m_p + m_size, new_size - m_size);\n            }\n\n            m_size = new_size;\n         }\n\n         return true;\n      }\n\n      inline bool push_back(const T& obj)\n      {\n         CRND_ASSERT(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size)));\n\n         if (m_size >= m_capacity)\n         {\n            if (!increase_capacity(m_size + 1, true))\n               return false;\n         }\n\n         scalar_type<T>::construct(m_p + m_size, obj);\n         m_size++;\n\n         return true;\n      }\n\n      inline void pop_back()\n      {\n         CRND_ASSERT(m_size);\n\n         if (m_size)\n         {\n            m_size--;\n            scalar_type<T>::destruct(&m_p[m_size]);\n         }\n      }\n\n      inline void insert(uint32 index, const T* p, uint32 n)\n      {\n         CRND_ASSERT(index <= m_size);\n         if (!n)\n            return;\n\n         const uint32 orig_size = m_size;\n         resize(m_size + n);\n\n         const T* pSrc = m_p + orig_size - 1;\n         T* pDst = const_cast<T*>(pSrc) + n;\n\n         const uint32 num_to_move = orig_size - index;\n\n         for (uint32 i = 0; i < num_to_move; i++)\n         {\n            CRND_ASSERT((pDst - m_p) < (int)m_size);\n            *pDst-- = *pSrc--;\n         }\n\n         pSrc = p;\n         pDst = m_p + index;\n\n         for (uint32 i = 0; i < n; i++)\n         {\n            CRND_ASSERT((pDst - m_p) < (int)m_size);\n            *pDst++ = *p++;\n         }\n      }\n\n      inline void erase(uint32 start, uint32 n)\n      {\n         CRND_ASSERT((start + n) <= m_size);\n\n         if (!n)\n            return;\n\n         const uint32 num_to_move = m_size - (start + n);\n\n         T* pDst = m_p + start;\n         T* pDst_end = pDst + num_to_move;\n         const T* pSrc = m_p + start + n;\n\n         while (pDst != pDst_end)\n            *pDst++ = *pSrc++;\n\n         scalar_type<T>::destruct_array(pDst_end, n);\n\n         m_size -= n;\n      }\n\n      inline void erase(uint32 index)\n      {\n         erase(index, 1);\n      }\n\n      inline void erase(T* p)\n      {\n         CRND_ASSERT((p >= m_p) && (p < (m_p + m_size)));\n         erase(p - m_p);\n      }\n\n      inline bool operator== (const vector& rhs) const\n      {\n         if (m_size != rhs.m_size)\n            return false;\n         else if (m_size)\n         {\n            if (scalar_type<T>::cFlag)\n               return memcmp(m_p, rhs.m_p, sizeof(T) * m_size) == 0;\n            else\n            {\n               const T* pSrc = m_p;\n               const T* pDst = rhs.m_p;\n               for (uint32 i = m_size; i; i--)\n                  if (!(*pSrc++ == *pDst++))\n                     return false;\n            }\n         }\n\n         return true;\n      }\n\n      inline bool operator< (const vector& rhs) const\n      {\n         const uint32 min_size = math::minimum(m_size, rhs.m_size);\n\n         const T* pSrc = m_p;\n         const T* pSrc_end = m_p + min_size;\n         const T* pDst = rhs.m_p;\n\n         while ((pSrc < pSrc_end) && (*pSrc == *pDst))\n         {\n            pSrc++;\n            pDst++;\n         }\n\n         if (pSrc < pSrc_end)\n            return *pSrc < *pDst;\n\n         return m_size < rhs.m_size;\n      }\n\n      void swap(vector& other)\n      {\n         utils::swap(m_p, other.m_p);\n         utils::swap(m_size, other.m_size);\n         utils::swap(m_capacity, other.m_capacity);\n      }\n\n   private:\n      T*          m_p;\n      uint32      m_size;\n      uint32      m_capacity;\n      bool        m_alloc_failed;\n\n      template<typename Q> struct is_vector { enum { cFlag = false }; };\n      template<typename Q> struct is_vector< vector<Q> > { enum { cFlag = true }; };\n\n      static void object_mover(void* pDst_void, void* pSrc_void, uint32 num)\n      {\n         T* pSrc = static_cast<T*>(pSrc_void);\n         T* const pSrc_end = pSrc + num;\n         T* pDst = static_cast<T*>(pDst_void);\n\n         while (pSrc != pSrc_end)\n         {\n            helpers::construct<T>(pDst, *pSrc);\n            pSrc->~T();\n            pSrc++;\n            pDst++;\n         }\n      }\n\n      inline bool increase_capacity(uint32 min_new_capacity, bool grow_hint)\n      {\n         if (!reinterpret_cast<elemental_vector*>(this)->increase_capacity(\n            min_new_capacity, grow_hint, sizeof(T),\n            ((scalar_type<T>::cFlag) || (is_vector<T>::cFlag) || (bitwise_movable<T>::cFlag) || CRND_IS_POD(T)) ? NULL : object_mover))\n         {\n            m_alloc_failed = true;\n            return false;\n         }\n         return true;\n      }\n   };\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n   extern void vector_test();\n\n} // namespace crnd\n\n// File: crnd_private.h\nnamespace crnd\n{\n   const crn_header* crnd_get_header(crn_header& header, const void* pData, uint32 data_size);\n\n} // namespace crnd\n\n// File: checksum.h\nnamespace crnd\n{\n   // crc16() intended for small buffers - doesn't use an acceleration table.\n   const uint16 cInitCRC16 = 0;\n   uint16 crc16(const void* pBuf, uint32 len, uint16 crc = cInitCRC16);\n\n}  // namespace crnd\n\n// File: crnd_color.h\nnamespace crnd\n{\n   template<typename component_type> struct color_quad_component_traits\n   {\n      enum\n      {\n         cSigned = false,\n         cFloat = false,\n         cMin = cUINT8_MIN,\n         cMax = cUINT8_MAX\n      };\n   };\n\n   template<> struct color_quad_component_traits<int16>\n   {\n      enum\n      {\n         cSigned = true,\n         cFloat = false,\n         cMin = cINT16_MIN,\n         cMax = cINT16_MAX\n      };\n   };\n\n   template<> struct color_quad_component_traits<uint16>\n   {\n      enum\n      {\n         cSigned = false,\n         cFloat = false,\n         cMin = cUINT16_MIN,\n         cMax = cUINT16_MAX\n      };\n   };\n\n   template<> struct color_quad_component_traits<int32>\n   {\n      enum\n      {\n         cSigned = true,\n         cFloat = false,\n         cMin = cINT32_MIN,\n         cMax = cINT32_MAX\n      };\n   };\n\n   template<> struct color_quad_component_traits<uint32>\n   {\n      enum\n      {\n         cSigned = false,\n         cFloat = false,\n         cMin = cUINT32_MIN,\n         cMax = cUINT32_MAX\n      };\n   };\n\n   template<> struct color_quad_component_traits<float>\n   {\n      enum\n      {\n         cSigned = false,\n         cFloat = true,\n         cMin = cINT32_MIN,\n         cMax = cINT32_MAX\n      };\n   };\n\n   template<> struct color_quad_component_traits<double>\n   {\n      enum\n      {\n         cSigned = false,\n         cFloat = true,\n         cMin = cINT32_MIN,\n         cMax = cINT32_MAX\n      };\n   };\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable:4201) //  warning C4201: nonstandard extension used : nameless struct/union\n#pragma warning(disable:4127) //  warning C4127: conditional expression is constant\n#endif\n\n   template<typename component_type, typename parameter_type>\n   class color_quad : public helpers::rel_ops<color_quad<component_type, parameter_type> >\n   {\n      static parameter_type clamp(parameter_type v)\n      {\n         if (component_traits::cFloat)\n            return v;\n         else\n         {\n            if (v < component_traits::cMin)\n               return component_traits::cMin;\n            else if (v > component_traits::cMax)\n               return component_traits::cMax;\n            return v;\n         }\n      }\n\n   public:\n      typedef component_type component_t;\n      typedef parameter_type parameter_t;\n      typedef color_quad_component_traits<component_type> component_traits;\n\n      enum { cNumComps = 4 };\n\n      union\n      {\n         struct\n         {\n            component_type r;\n            component_type g;\n            component_type b;\n            component_type a;\n         };\n\n         component_type c[cNumComps];\n      };\n\n      inline color_quad()\n      {\n      }\n\n      inline color_quad(eClear) :\n         r(0), g(0), b(0), a(0)\n      {\n      }\n\n      inline color_quad(const color_quad& other) :\n         r(other.r), g(other.g), b(other.b), a(other.a)\n      {\n      }\n\n      inline color_quad(parameter_type y, parameter_type alpha = component_traits::cMax)\n      {\n         set(y, alpha);\n      }\n\n      inline color_quad(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax)\n      {\n         set(red, green, blue, alpha);\n      }\n\n      template<typename other_component_type, typename other_parameter_type>\n      inline color_quad(const color_quad<other_component_type, other_parameter_type>& other) :\n         r(clamp(other.r)), g(clamp(other.g)), b(clamp(other.b)), a(clamp(other.a))\n      {\n      }\n\n      inline void clear()\n      {\n         r = 0;\n         g = 0;\n         b = 0;\n         a = 0;\n      }\n\n      inline color_quad& operator= (const color_quad& other)\n      {\n         r = other.r;\n         g = other.g;\n         b = other.b;\n         a = other.a;\n         return *this;\n      }\n\n      template<typename other_component_type, typename other_parameter_type>\n      inline color_quad& operator=(const color_quad<other_component_type, other_parameter_type>& other)\n      {\n         r = clamp(other.r);\n         g = clamp(other.g);\n         b = clamp(other.b);\n         a = clamp(other.a);\n         return *this;\n      }\n\n      inline color_quad& set(parameter_type y, parameter_type alpha = component_traits::cMax)\n      {\n         y = clamp(y);\n         r = static_cast<component_type>(y);\n         g = static_cast<component_type>(y);\n         b = static_cast<component_type>(y);\n         a = static_cast<component_type>(alpha);\n         return *this;\n      }\n\n      inline color_quad& set(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax)\n      {\n         r = static_cast<component_type>(clamp(red));\n         g = static_cast<component_type>(clamp(green));\n         b = static_cast<component_type>(clamp(blue));\n         a = static_cast<component_type>(clamp(alpha));\n         return *this;\n      }\n\n      inline color_quad& set_noclamp_rgba(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha)\n      {\n         r = static_cast<component_type>(red);\n         g = static_cast<component_type>(green);\n         b = static_cast<component_type>(blue);\n         a = static_cast<component_type>(alpha);\n         return *this;\n      }\n\n      inline color_quad& set_noclamp_rgb(parameter_type red, parameter_type green, parameter_type blue)\n      {\n         r = static_cast<component_type>(red);\n         g = static_cast<component_type>(green);\n         b = static_cast<component_type>(blue);\n         return *this;\n      }\n\n      static inline parameter_type get_min_comp() { return component_traits::cMin; }\n      static inline parameter_type get_max_comp() { return component_traits::cMax; }\n      static inline bool get_comps_are_signed() { return component_traits::cSigned; }\n\n      inline component_type operator[] (uint32 i) const { CRND_ASSERT(i < cNumComps); return c[i]; }\n      inline component_type& operator[] (uint32 i) { CRND_ASSERT(i < cNumComps); return c[i]; }\n\n      inline color_quad& set_component(uint32 i, parameter_type f)\n      {\n         CRND_ASSERT(i < cNumComps);\n\n         c[i] = static_cast<component_type>(clamp(f));\n\n         return *this;\n      }\n\n      inline color_quad& clamp(const color_quad& l, const color_quad& h)\n      {\n         for (uint32 i = 0; i < cNumComps; i++)\n            c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l[i], h[i]));\n         return *this;\n      }\n\n      inline color_quad& clamp(parameter_type l, parameter_type h)\n      {\n         for (uint32 i = 0; i < cNumComps; i++)\n            c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l, h));\n         return *this;\n      }\n\n      // Returns CCIR 601 luma (consistent with color_utils::RGB_To_Y).\n      inline parameter_type get_luma() const\n      {\n         return static_cast<parameter_type>((19595U * r + 38470U * g + 7471U * b + 32768) >> 16U);\n      }\n\n      // Returns REC 709 luma.\n      inline parameter_type get_luma_rec709() const\n      {\n         return static_cast<parameter_type>((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U);\n      }\n\n      inline uint32 squared_distance(const color_quad& c, bool alpha = true) const\n      {\n         return math::square(r - c.r) + math::square(g - c.g) + math::square(b - c.b) + (alpha ? math::square(a - c.a) : 0);\n      }\n\n      inline bool rgb_equals(const color_quad& rhs) const\n      {\n         return (r == rhs.r) && (g == rhs.g) && (b == rhs.b);\n      }\n\n      inline bool operator== (const color_quad& rhs) const\n      {\n         return (r == rhs.r) && (g == rhs.g) && (b == rhs.b) && (a == rhs.a);\n      }\n\n      inline bool operator< (const color_quad& rhs) const\n      {\n         for (uint32 i = 0; i < cNumComps; i++)\n         {\n            if (c[i] < rhs.c[i])\n               return true;\n            else if (!(c[i] == rhs.c[i]))\n               return false;\n         }\n         return false;\n      }\n\n      inline color_quad& operator+= (const color_quad& other)\n      {\n         for (uint32 i = 0; i < 4; i++)\n            c[i] = static_cast<component_type>(clamp(c[i] + other.c[i]));\n         return *this;\n      }\n\n      inline color_quad& operator-= (const color_quad& other)\n      {\n         for (uint32 i = 0; i < 4; i++)\n            c[i] = static_cast<component_type>(clamp(c[i] - other.c[i]));\n         return *this;\n      }\n\n      inline color_quad& operator*= (parameter_type v)\n      {\n         for (uint32 i = 0; i < 4; i++)\n            c[i] = static_cast<component_type>(clamp(c[i] * v));\n         return *this;\n      }\n\n      inline color_quad& operator/= (parameter_type v)\n      {\n         for (uint32 i = 0; i < 4; i++)\n            c[i] = static_cast<component_type>(c[i] / v);\n         return *this;\n      }\n\n      inline color_quad get_swizzled(uint32 x, uint32 y, uint32 z, uint32 w) const\n      {\n         CRND_ASSERT((x | y | z | w) < 4);\n         return color_quad(c[x], c[y], c[z], c[w]);\n      }\n\n      inline friend color_quad operator+ (const color_quad& lhs, const color_quad& rhs)\n      {\n         color_quad result(lhs);\n         result += rhs;\n         return result;\n      }\n\n      inline friend color_quad operator- (const color_quad& lhs, const color_quad& rhs)\n      {\n         color_quad result(lhs);\n         result -= rhs;\n         return result;\n      }\n\n      inline friend color_quad operator* (const color_quad& lhs, parameter_type v)\n      {\n         color_quad result(lhs);\n         result *= v;\n         return result;\n      }\n\n      friend inline color_quad operator/ (const color_quad& lhs, parameter_type v)\n      {\n         color_quad result(lhs);\n         result /= v;\n         return result;\n      }\n\n      friend inline color_quad operator* (parameter_type v, const color_quad& rhs)\n      {\n         color_quad result(rhs);\n         result *= v;\n         return result;\n      }\n\n      inline uint32 get_min_component_index(bool alpha = true) const\n      {\n         uint32 index = 0;\n         uint32 limit = alpha ? cNumComps : (cNumComps - 1);\n         for (uint32 i = 1; i < limit; i++)\n            if (c[i] < c[index])\n               index = i;\n         return index;\n      }\n\n      inline uint32 get_max_component_index(bool alpha = true) const\n      {\n         uint32 index = 0;\n         uint32 limit = alpha ? cNumComps : (cNumComps - 1);\n         for (uint32 i = 1; i < limit; i++)\n            if (c[i] > c[index])\n               index = i;\n         return index;\n      }\n\n      inline void get_float4(float* pDst)\n      {\n         for (uint32 i = 0; i < 4; i++)\n            pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);\n      }\n\n      inline void get_float3(float* pDst)\n      {\n         for (uint32 i = 0; i < 3; i++)\n            pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);\n      }\n\n      static inline color_quad make_black()\n      {\n         return color_quad(0, 0, 0, component_traits::cMax);\n      }\n\n      static inline color_quad make_white()\n      {\n         return color_quad(component_traits::cMax, component_traits::cMax, component_traits::cMax, component_traits::cMax);\n      }\n   }; // class color_quad\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n   template<typename c, typename q>\n   struct scalar_type< color_quad<c, q> >\n   {\n      enum { cFlag = true };\n      static inline void construct(color_quad<c, q>* p) { }\n      static inline void construct(color_quad<c, q>* p, const color_quad<c, q>& init) { memcpy(p, &init, sizeof(color_quad<c, q>)); }\n      static inline void construct_array(color_quad<c, q>* p, uint32 n) { p, n; }\n      static inline void destruct(color_quad<c, q>* p) { p; }\n      static inline void destruct_array(color_quad<c, q>* p, uint32 n) { p, n; }\n   };\n\n   typedef color_quad<uint8, int>      color_quad_u8;\n   typedef color_quad<int16, int>      color_quad_i16;\n   typedef color_quad<uint16, int>     color_quad_u16;\n   typedef color_quad<int32, int>      color_quad_i32;\n   typedef color_quad<uint32, uint32>    color_quad_u32;\n   typedef color_quad<float, float>    color_quad_f;\n   typedef color_quad<double, double>  color_quad_d;\n\n} // namespace crnd\n\n// File: crnd_dxt.h\nnamespace crnd\n{\n   enum dxt_format\n   {\n      cDXTInvalid = -1,\n\n      // cDXT1/1A must appear first!\n      cDXT1,\n      cDXT1A,\n\n      cDXT3,\n      cDXT5,\n      cDXT5A,\n\n      cDXN_XY,    // inverted relative to standard ATI2, 360's DXN\n      cDXN_YX     // standard ATI2\n   };\n\n   enum dxt_constants\n   {\n      cDXTBlockShift = 2U,\n      cDXTBlockSize = 1U << cDXTBlockShift,\n\n      cDXT1BytesPerBlock = 8U,\n      cDXT5NBytesPerBlock = 16U,\n\n      cDXT1SelectorBits = 2U,\n      cDXT1SelectorValues = 1U << cDXT1SelectorBits,\n      cDXT1SelectorMask = cDXT1SelectorValues - 1U,\n\n      cDXT5SelectorBits = 3U,\n      cDXT5SelectorValues = 1U << cDXT5SelectorBits,\n      cDXT5SelectorMask = cDXT5SelectorValues - 1U\n   };\n\n   const float cDXT1MaxLinearValue = 3.0f;\n   const float cDXT1InvMaxLinearValue = 1.0f/3.0f;\n\n   const float cDXT5MaxLinearValue = 7.0f;\n   const float cDXT5InvMaxLinearValue = 1.0f/7.0f;\n\n   // Converts DXT1 raw color selector index to a linear value.\n   extern const uint8 g_dxt1_to_linear[cDXT1SelectorValues];\n\n   // Converts DXT5 raw alpha selector index to a linear value.\n   extern const uint8 g_dxt5_to_linear[cDXT5SelectorValues];\n\n   // Converts DXT1 linear color selector index to a raw value (inverse of g_dxt1_to_linear).\n   extern const uint8 g_dxt1_from_linear[cDXT1SelectorValues];\n\n   // Converts DXT5 linear alpha selector index to a raw value (inverse of g_dxt5_to_linear).\n   extern const uint8 g_dxt5_from_linear[cDXT5SelectorValues];\n\n   extern const uint8 g_six_alpha_invert_table[cDXT5SelectorValues];\n   extern const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues];\n\n   struct dxt1_block\n   {\n      uint8 m_low_color[2];\n      uint8 m_high_color[2];\n\n      enum { cNumSelectorBytes = 4 };\n      uint8 m_selectors[cNumSelectorBytes];\n\n      inline void clear()\n      {\n         utils::zero_this(this);\n      }\n\n      // These methods assume the in-memory rep is in LE byte order.\n      inline uint32 get_low_color() const\n      {\n         return m_low_color[0] | (m_low_color[1] << 8U);\n      }\n\n      inline uint32 get_high_color() const\n      {\n         return m_high_color[0] | (m_high_color[1] << 8U);\n      }\n\n      inline void set_low_color(uint16 c)\n      {\n         m_low_color[0] = static_cast<uint8>(c & 0xFF);\n         m_low_color[1] = static_cast<uint8>((c >> 8) & 0xFF);\n      }\n\n      inline void set_high_color(uint16 c)\n      {\n         m_high_color[0] = static_cast<uint8>(c & 0xFF);\n         m_high_color[1] = static_cast<uint8>((c >> 8) & 0xFF);\n      }\n\n      inline uint32 get_selector(uint32 x, uint32 y) const\n      {\n         CRND_ASSERT((x < 4U) && (y < 4U));\n         return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask;\n      }\n\n      inline void set_selector(uint32 x, uint32 y, uint32 val)\n      {\n         CRND_ASSERT((x < 4U) && (y < 4U) && (val < 4U));\n\n         m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits)));\n         m_selectors[y] |= (val << (x * cDXT1SelectorBits));\n      }\n\n      static uint16        pack_color(const color_quad_u8& color, bool scaled, uint32 bias = 127U);\n      static uint16        pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias = 127U);\n\n      static color_quad_u8 unpack_color(uint16 packed_color, bool scaled, uint32 alpha = 255U);\n      static void          unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled);\n\n      static uint32        get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1);\n      static uint32        get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1);\n      // pDst must point to an array at least cDXT1SelectorValues long.\n      static uint32        get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1);\n\n      static color_quad_u8 unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha = 255U);\n      static uint32        pack_endpoints(uint32 lo, uint32 hi);\n   };\n\n   CRND_DEFINE_BITWISE_MOVABLE(dxt1_block);\n\n   struct dxt3_block\n   {\n      enum { cNumAlphaBytes = 8 };\n      uint8 m_alpha[cNumAlphaBytes];\n\n      void set_alpha(uint32 x, uint32 y, uint32 value, bool scaled);\n      uint32 get_alpha(uint32 x, uint32 y, bool scaled) const;\n   };\n\n   CRND_DEFINE_BITWISE_MOVABLE(dxt3_block);\n\n   struct dxt5_block\n   {\n      uint8 m_endpoints[2];\n\n      enum { cNumSelectorBytes = 6 };\n      uint8 m_selectors[cNumSelectorBytes];\n\n      inline void clear()\n      {\n         utils::zero_this(this);\n      }\n\n      inline uint32 get_low_alpha() const\n      {\n         return m_endpoints[0];\n      }\n\n      inline uint32 get_high_alpha() const\n      {\n         return m_endpoints[1];\n      }\n\n      inline void set_low_alpha(uint32 i)\n      {\n         CRND_ASSERT(i <= cUINT8_MAX);\n         m_endpoints[0] = static_cast<uint8>(i);\n      }\n\n      inline void set_high_alpha(uint32 i)\n      {\n         CRND_ASSERT(i <= cUINT8_MAX);\n         m_endpoints[1] = static_cast<uint8>(i);\n      }\n\n      uint32 get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); }\n\n      uint32 get_selectors_as_word(uint32 index) { CRND_ASSERT(index < 3); return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8); }\n\n      inline uint32 get_selector(uint32 x, uint32 y) const\n      {\n         CRND_ASSERT((x < 4U) && (y < 4U));\n\n         uint32 selector_index = (y * 4) + x;\n         uint32 bit_index = selector_index * cDXT5SelectorBits;\n\n         uint32 byte_index = bit_index >> 3;\n         uint32 bit_ofs = bit_index & 7;\n\n         uint32 v = m_selectors[byte_index];\n         if (byte_index < (cNumSelectorBytes - 1))\n            v |= (m_selectors[byte_index + 1] << 8);\n\n         return (v >> bit_ofs) & 7;\n      }\n\n      inline void set_selector(uint32 x, uint32 y, uint32 val)\n      {\n         CRND_ASSERT((x < 4U) && (y < 4U) && (val < 8U));\n\n         uint32 selector_index = (y * 4) + x;\n         uint32 bit_index = selector_index * cDXT5SelectorBits;\n\n         uint32 byte_index = bit_index >> 3;\n         uint32 bit_ofs = bit_index & 7;\n\n         uint32 v = m_selectors[byte_index];\n         if (byte_index < (cNumSelectorBytes - 1))\n            v |= (m_selectors[byte_index + 1] << 8);\n\n         v &= (~(7 << bit_ofs));\n         v |= (val << bit_ofs);\n\n         m_selectors[byte_index] = static_cast<uint8>(v);\n         if (byte_index < (cNumSelectorBytes - 1))\n            m_selectors[byte_index + 1] = static_cast<uint8>(v >> 8);\n      }\n\n      // Results written to alpha channel.\n      static uint32          get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h);\n      static uint32          get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h);\n      static uint32          get_block_values(color_quad_u8* pDst, uint32 l, uint32 h);\n\n      static uint32          get_block_values6(uint32* pDst, uint32 l, uint32 h);\n      static uint32          get_block_values8(uint32* pDst, uint32 l, uint32 h);\n      // pDst must point to an array at least cDXT5SelectorValues long.\n      static uint32          get_block_values(uint32* pDst, uint32 l, uint32 h);\n\n      static uint32          unpack_endpoint(uint32 packed, uint32 index);\n      static uint32          pack_endpoints(uint32 lo, uint32 hi);\n   };\n\n   CRND_DEFINE_BITWISE_MOVABLE(dxt5_block);\n\n} // namespace crnd\n\n// File: crnd_dxt_hc_common.h\nnamespace crnd\n{\n   struct chunk_tile_desc\n   {\n      // These values are in pixels, and always a multiple of cBlockPixelWidth/cBlockPixelHeight.\n      uint32 m_x_ofs;\n      uint32 m_y_ofs;\n      uint32 m_width;\n      uint32 m_height;\n      uint32 m_layout_index;\n   };\n\n   struct chunk_encoding_desc\n   {\n      uint32 m_num_tiles;\n      chunk_tile_desc m_tiles[4];\n   };\n\n   const uint32 cChunkPixelWidth = 8;\n   const uint32 cChunkPixelHeight = 8;\n   const uint32 cChunkBlockWidth = 2;\n   const uint32 cChunkBlockHeight = 2;\n\n   const uint32 cChunkMaxTiles = 4;\n\n   const uint32 cBlockPixelWidthShift = 2;\n   const uint32 cBlockPixelHeightShift = 2;\n\n   const uint32 cBlockPixelWidth = 4;\n   const uint32 cBlockPixelHeight = 4;\n\n   const uint32 cNumChunkEncodings = 8;\n   extern chunk_encoding_desc g_chunk_encodings[cNumChunkEncodings];\n\n   const uint32 cNumChunkTileLayouts = 9;\n   const uint32 cFirst4x4ChunkTileLayout = 5;\n   extern chunk_tile_desc g_chunk_tile_layouts[cNumChunkTileLayouts];\n\n} // namespace crnd\n\n// File: crnd_prefix_coding.h\n#ifdef _XBOX\n#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 1\n#else\n#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 0\n#endif\n\nnamespace crnd\n{\n   namespace prefix_coding\n   {\n      const uint32 cMaxExpectedCodeSize = 16;\n      const uint32 cMaxSupportedSyms = 8192;\n      const uint32 cMaxTableBits = 11;\n\n      class decoder_tables\n      {\n      public:\n         inline decoder_tables() :\n            m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)\n         {\n         }\n\n         inline decoder_tables(const decoder_tables& other) :\n            m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)\n         {\n            *this = other;\n         }\n\n         decoder_tables& operator= (const decoder_tables& other)\n         {\n            if (this == &other)\n               return *this;\n\n            clear();\n\n            memcpy(this, &other, sizeof(*this));\n\n            if (other.m_lookup)\n            {\n               m_lookup = crnd_new_array<uint32>(m_cur_lookup_size);\n               if (m_lookup)\n                  memcpy(m_lookup, other.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);\n            }\n\n            if (other.m_sorted_symbol_order)\n            {\n               m_sorted_symbol_order = crnd_new_array<uint16>(m_cur_sorted_symbol_order_size);\n               if (m_sorted_symbol_order)\n                  memcpy(m_sorted_symbol_order, other.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);\n            }\n\n            return *this;\n         }\n\n         inline void clear()\n         {\n            if (m_lookup)\n            {\n               crnd_delete_array(m_lookup);\n               m_lookup = 0;\n               m_cur_lookup_size = 0;\n            }\n\n            if (m_sorted_symbol_order)\n            {\n               crnd_delete_array(m_sorted_symbol_order);\n               m_sorted_symbol_order = NULL;\n               m_cur_sorted_symbol_order_size = 0;\n            }\n         }\n\n         inline ~decoder_tables()\n         {\n            if (m_lookup)\n               crnd_delete_array(m_lookup);\n\n            if (m_sorted_symbol_order)\n               crnd_delete_array(m_sorted_symbol_order);\n         }\n\n         bool init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits);\n\n         // DO NOT use any complex classes here - it is bitwise copied.\n\n         uint32                  m_num_syms;\n         uint32                  m_total_used_syms;\n         uint32                  m_table_bits;\n         uint32                  m_table_shift;\n         uint32                  m_table_max_code;\n         uint32                  m_decode_start_code_size;\n\n         uint8                   m_min_code_size;\n         uint8                   m_max_code_size;\n\n         uint32                  m_max_codes[cMaxExpectedCodeSize + 1];\n         int32                   m_val_ptrs[cMaxExpectedCodeSize + 1];\n\n         uint32                  m_cur_lookup_size;\n         uint32*                 m_lookup;\n\n         uint32                  m_cur_sorted_symbol_order_size;\n         uint16*                 m_sorted_symbol_order;\n\n         inline uint32 get_unshifted_max_code(uint32 len) const\n         {\n            CRND_ASSERT( (len >= 1) && (len <= cMaxExpectedCodeSize) );\n            uint32 k = m_max_codes[len - 1];\n            if (!k)\n               return crnd::cUINT32_MAX;\n            return (k - 1) >> (16 - len);\n         }\n      };\n\n   } // namespace prefix_coding\n\n} // namespace crnd\n\n// File: crnd_symbol_codec.h\nnamespace crnd\n{\n   class static_huffman_data_model\n   {\n   public:\n      static_huffman_data_model();\n      static_huffman_data_model(const static_huffman_data_model& other);\n      ~static_huffman_data_model();\n\n      static_huffman_data_model& operator= (const static_huffman_data_model& rhs);\n\n      bool init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit);\n      void clear();\n\n      inline bool is_valid() const { return m_pDecode_tables != NULL; }\n\n      inline uint32 get_total_syms() const { return m_total_syms; }\n\n      inline uint32 get_code_size(uint32 sym) const { return m_code_sizes[sym]; }\n\n      inline const uint8* get_code_sizes() const { return m_code_sizes.empty() ? NULL : &m_code_sizes[0]; }\n\n   public:\n      uint32                           m_total_syms;\n      crnd::vector<uint8>              m_code_sizes;\n      prefix_coding::decoder_tables*   m_pDecode_tables;\n\n   private:\n      bool prepare_decoder_tables();\n      uint compute_decoder_table_bits() const;\n\n      friend class symbol_codec;\n   };\n\n   class symbol_codec\n   {\n   public:\n      symbol_codec();\n\n      bool start_decoding(const uint8* pBuf, uint32 buf_size);\n      bool decode_receive_static_data_model(static_huffman_data_model& model);\n\n      uint32 decode_bits(uint32 num_bits);\n      uint32 decode(const static_huffman_data_model& model);\n\n      uint64 stop_decoding();\n\n   public:\n      const uint8*         m_pDecode_buf;\n      const uint8*         m_pDecode_buf_next;\n      const uint8*         m_pDecode_buf_end;\n      uint32               m_decode_buf_size;\n\n      typedef uint32 bit_buf_type;\n      enum { cBitBufSize = 32U };\n      bit_buf_type         m_bit_buf;\n\n      int                  m_bit_count;\n\n   private:\n      void get_bits_init();\n      uint32 get_bits(uint32 num_bits);\n   };\n\n} // namespace crnd\n\n#define CRND_HUFF_DECODE_BEGIN(x)\n#define CRND_HUFF_DECODE_END(x)\n#define CRND_HUFF_DECODE(codec, model, symbol) symbol = codec.decode(model);\n\nnamespace crnd\n{\n   void crnd_assert(const char* pExp, const char* pFile, unsigned line)\n   {\n      char buf[512];\n\n#if defined(_WIN32) && defined(_MSC_VER)\n      sprintf_s(buf, sizeof(buf), \"%s(%u): Assertion failure: \\\"%s\\\"\\n\", pFile, line, pExp);\n#else\n      sprintf(buf, \"%s(%u): Assertion failure: \\\"%s\\\"\\n\", pFile, line, pExp);\n#endif\n\n      crnd_output_debug_string(buf);\n\n      puts(buf);\n\n      if (crnd_is_debugger_present())\n         crnd_debug_break();\n   }\n\n   void crnd_trace(const char* pFmt, va_list args)\n   {\n      if (crnd_is_debugger_present())\n      {\n         char buf[512];\n#if defined(_WIN32) && defined(_MSC_VER)\n         vsprintf_s(buf, sizeof(buf), pFmt, args);\n#else\n         vsprintf(buf, pFmt, args);\n#endif\n\n         crnd_output_debug_string(buf);\n      }\n   };\n\n   void crnd_trace(const char* pFmt, ...)\n   {\n      va_list args;\n      va_start(args, pFmt);\n      crnd_trace(pFmt, args);\n      va_end(args);\n   };\n\n} // namespace crnd\n\n// File: checksum.cpp\n// From the public domain stb.h header.\nnamespace crnd\n{\n   uint16 crc16(const void* pBuf, uint32 len, uint16 crc)\n   {\n      crc = ~crc;\n\n      const uint8* p = reinterpret_cast<const uint8*>(pBuf);\n      while (len)\n      {\n         const uint16 q = *p++ ^ (crc >> 8U);\n         crc <<= 8U;\n\n         uint16 r = (q >> 4U) ^ q;\n         crc ^= r;\n         r <<= 5U;\n         crc ^= r;\n         r <<= 7U;\n         crc ^= r;\n\n         len--;\n      }\n\n      return static_cast<uint16>(~crc);\n   }\n\n} // namespace crnd\n\n\n// File: crnd_vector.cpp\nnamespace crnd\n{\n   bool elemental_vector::increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pMover)\n   {\n      CRND_ASSERT(m_size <= m_capacity);\n      CRND_ASSERT(min_new_capacity < (0x7FFF0000U / element_size));\n\n      if (m_capacity >= min_new_capacity)\n         return true;\n\n      uint32 new_capacity = min_new_capacity;\n      if ((grow_hint) && (!math::is_power_of_2(new_capacity)))\n         new_capacity = math::next_pow2(new_capacity);\n\n      CRND_ASSERT(new_capacity && (new_capacity > m_capacity));\n\n      const uint32 desired_size = element_size * new_capacity;\n      size_t actual_size;\n      if (!pMover)\n      {\n         void* new_p = crnd_realloc(m_p, desired_size, &actual_size, true);\n         if (!new_p)\n            return false;\n         m_p = new_p;\n      }\n      else\n      {\n         void* new_p = crnd_malloc(desired_size, &actual_size);\n         if (!new_p)\n            return false;\n\n         (*pMover)(new_p, m_p, m_size);\n\n         if (m_p)\n            crnd_free(m_p);\n\n         m_p = new_p;\n      }\n\n      if (actual_size > desired_size)\n         m_capacity = static_cast<uint32>(actual_size / element_size);\n      else\n         m_capacity = new_capacity;\n\n      return true;\n   }\n\n} // namespace crnd\n\n// File: crnd_utils.cpp\nnamespace crnd\n{\n   namespace utils\n   {\n      uint32 compute_max_mips(uint32 width, uint32 height)\n      {\n         if ((width | height) == 0)\n            return 0;\n\n         uint32 num_mips = 1;\n\n         while ((width > 1U) || (height > 1U))\n         {\n            width >>= 1U;\n            height >>= 1U;\n            num_mips++;\n         }\n\n         return num_mips;\n      }\n\n   } // namespace utils\n\n} // namespace crnd\n\n// File: crnd_prefix_coding.cpp\nnamespace crnd\n{\n   namespace prefix_coding\n   {\n      bool decoder_tables::init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits)\n      {\n         uint32 min_codes[cMaxExpectedCodeSize];\n         if ((!num_syms) || (table_bits > cMaxTableBits))\n            return false;\n\n         m_num_syms = num_syms;\n\n         uint32 num_codes[cMaxExpectedCodeSize + 1];\n         utils::zero_object(num_codes);\n\n         for (uint32 i = 0; i < num_syms; i++)\n         {\n            uint32 c = pCodesizes[i];\n            if (c)\n               num_codes[c]++;\n         }\n\n         uint32 sorted_positions[cMaxExpectedCodeSize + 1];\n\n         uint32 cur_code = 0;\n\n         uint32 total_used_syms = 0;\n         uint32 max_code_size = 0;\n         uint32 min_code_size = cUINT32_MAX;\n         for (uint32 i = 1; i <= cMaxExpectedCodeSize; i++)\n         {\n            const uint32 n = num_codes[i];\n\n            if (!n)\n               m_max_codes[i - 1] = 0;//UINT_MAX;\n            else\n            {\n               min_code_size = math::minimum(min_code_size, i);\n               max_code_size = math::maximum(max_code_size, i);\n\n               min_codes[i - 1] = cur_code;\n\n               m_max_codes[i - 1] = cur_code + n - 1;\n               m_max_codes[i - 1] = 1 + ((m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1));\n\n               m_val_ptrs[i - 1] = total_used_syms;\n\n               sorted_positions[i] = total_used_syms;\n\n               cur_code += n;\n               total_used_syms += n;\n            }\n\n            cur_code <<= 1;\n         }\n\n         m_total_used_syms = total_used_syms;\n\n         if (total_used_syms > m_cur_sorted_symbol_order_size)\n         {\n            m_cur_sorted_symbol_order_size = total_used_syms;\n\n            if (!math::is_power_of_2(total_used_syms))\n               m_cur_sorted_symbol_order_size = math::minimum<uint32>(num_syms, math::next_pow2(total_used_syms));\n\n            if (m_sorted_symbol_order)\n               crnd_delete_array(m_sorted_symbol_order);\n\n            m_sorted_symbol_order = crnd_new_array<uint16>(m_cur_sorted_symbol_order_size);\n            if (!m_sorted_symbol_order)\n               return false;\n         }\n\n         m_min_code_size = static_cast<uint8>(min_code_size);\n         m_max_code_size = static_cast<uint8>(max_code_size);\n\n         for (uint32 i = 0; i < num_syms; i++)\n         {\n            uint32 c = pCodesizes[i];\n            if (c)\n            {\n               CRND_ASSERT(num_codes[c]);\n\n               uint32 sorted_pos = sorted_positions[c]++;\n\n               CRND_ASSERT(sorted_pos < total_used_syms);\n\n               m_sorted_symbol_order[sorted_pos] = static_cast<uint16>(i);\n            }\n         }\n\n         if (table_bits <= m_min_code_size)\n            table_bits = 0;\n         m_table_bits = table_bits;\n\n         if (table_bits)\n         {\n            uint32 table_size = 1 << table_bits;\n            if (table_size > m_cur_lookup_size)\n            {\n               m_cur_lookup_size = table_size;\n\n               if (m_lookup)\n                  crnd_delete_array(m_lookup);\n\n               m_lookup = crnd_new_array<uint32>(table_size);\n               if (!m_lookup)\n                  return false;\n            }\n\n            memset(m_lookup, 0xFF, (uint)sizeof(m_lookup[0]) * (1UL << table_bits));\n\n            for (uint32 codesize = 1; codesize <= table_bits; codesize++)\n            {\n               if (!num_codes[codesize])\n                  continue;\n\n               const uint32 fillsize = table_bits - codesize;\n               const uint32 fillnum = 1 << fillsize;\n\n               const uint32 min_code = min_codes[codesize - 1];\n               const uint32 max_code = get_unshifted_max_code(codesize);\n               const uint32 val_ptr = m_val_ptrs[codesize - 1];\n\n               for (uint32 code = min_code; code <= max_code; code++)\n               {\n                  const uint32 sym_index = m_sorted_symbol_order[ val_ptr + code - min_code ];\n                  CRND_ASSERT( pCodesizes[sym_index] == codesize );\n\n                  for (uint32 j = 0; j < fillnum; j++)\n                  {\n                     const uint32 t = j + (code << fillsize);\n\n                     CRND_ASSERT(t < (1U << table_bits));\n\n                     CRND_ASSERT(m_lookup[t] == cUINT32_MAX);\n\n                     m_lookup[t] = sym_index | (codesize << 16U);\n                  }\n               }\n            }\n         }\n\n         for (uint32 i = 0; i < cMaxExpectedCodeSize; i++)\n            m_val_ptrs[i] -= min_codes[i];\n\n         m_table_max_code = 0;\n         m_decode_start_code_size = m_min_code_size;\n\n         if (table_bits)\n         {\n            uint32 i;\n            for (i = table_bits; i >= 1; i--)\n            {\n               if (num_codes[i])\n               {\n                  m_table_max_code = m_max_codes[i - 1];\n                  break;\n               }\n            }\n            if (i >= 1)\n            {\n               m_decode_start_code_size = table_bits + 1;\n               for (uint32 j = table_bits + 1; j <= max_code_size; j++)\n               {\n                  if (num_codes[j])\n                  {\n                     m_decode_start_code_size = j;\n                     break;\n                  }\n               }\n            }\n         }\n\n         // sentinels\n         m_max_codes[cMaxExpectedCodeSize] = cUINT32_MAX;\n         m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF;\n\n         m_table_shift = 32 - m_table_bits;\n         return true;\n      }\n\n   } // namespace prefix_codig\n\n} // namespace crnd\n\n// File: crnd_platform.cpp\nnamespace crnd\n{\n   bool crnd_is_debugger_present()\n   {\n#ifdef CRND_DEVEL\n      return IsDebuggerPresent() != 0;\n#else\n      return false;\n#endif\n   }\n\n   void crnd_debug_break()\n   {\n#ifdef CRND_DEVEL\n      DebugBreak();\n#endif\n   }\n\n   void crnd_output_debug_string(const char* p)\n   {\n      p;\n#ifdef CRND_DEVEL\n      OutputDebugStringA(p);\n#endif\n   }\n\n} // namespace crnd\n\n// File: crnd_mem.cpp\nnamespace crnd\n{\n   const uint32 MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U;\n\n   static void* crnd_default_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data)\n   {\n      pUser_data;\n\n      void* p_new;\n\n      if (!p)\n      {\n         p_new = ::malloc(size);\n\n         if (pActual_size)\n         {\n#ifdef _WIN32\n            *pActual_size = p_new ? ::_msize(p_new) : 0;\n#else\n            *pActual_size = p_new ? malloc_usable_size(p_new) : 0;\n#endif\n         }\n      }\n      else if (!size)\n      {\n         ::free(p);\n         p_new = NULL;\n\n         if (pActual_size)\n            *pActual_size = 0;\n      }\n      else\n      {\n         void* p_final_block = p;\n#ifdef _WIN32\n         p_new = ::_expand(p, size);\n#else\n         p_new = NULL;\n#endif\n\n         if (p_new)\n            p_final_block = p_new;\n         else if (movable)\n         {\n            p_new = ::realloc(p, size);\n\n            if (p_new)\n               p_final_block = p_new;\n         }\n\n         if (pActual_size)\n         {\n#ifdef _WIN32\n            *pActual_size = ::_msize(p_final_block);\n#else\n            *pActual_size = ::malloc_usable_size(p_final_block);\n#endif\n         }\n      }\n\n      return p_new;\n   }\n\n   static size_t crnd_default_msize(void* p, void* pUser_data)\n   {\n      pUser_data;\n#ifdef _WIN32\n      return p ? _msize(p) : 0;\n#else\n      return p ? malloc_usable_size(p) : 0;\n#endif\n   }\n\n   static crnd_realloc_func        g_pRealloc = crnd_default_realloc;\n   static crnd_msize_func          g_pMSize   = crnd_default_msize;\n   static void*                   g_pUser_data;\n\n   void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data)\n   {\n      if ((!pRealloc) || (!pMSize))\n      {\n         g_pRealloc = crnd_default_realloc;\n         g_pMSize = crnd_default_msize;\n         g_pUser_data = NULL;\n      }\n      else\n      {\n         g_pRealloc = pRealloc;\n         g_pMSize = pMSize;\n         g_pUser_data = pUser_data;\n      }\n   }\n\n   static inline void crnd_mem_error(const char* p_msg)\n   {\n      crnd_assert(p_msg, __FILE__, __LINE__);\n   }\n\n   void* crnd_malloc(size_t size, size_t* pActual_size)\n   {\n      size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U);\n      if (!size)\n         size = sizeof(uint32);\n\n      if (size > MAX_POSSIBLE_BLOCK_SIZE)\n      {\n         crnd_mem_error(\"crnd_malloc: size too big\");\n         return NULL;\n      }\n\n      size_t actual_size = size;\n      uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));\n\n      if (pActual_size)\n         *pActual_size = actual_size;\n\n      if ((!p_new) || (actual_size < size))\n      {\n         crnd_mem_error(\"crnd_malloc: out of memory\");\n         return NULL;\n      }\n\n      CRND_ASSERT(((uint32)p_new & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0);\n\n      return p_new;\n   }\n\n   void* crnd_realloc(void* p, size_t size, size_t* pActual_size, bool movable)\n   {\n      if ((uint32)reinterpret_cast<ptr_bits>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1))\n      {\n         crnd_mem_error(\"crnd_realloc: bad ptr\");\n         return NULL;\n      }\n\n      if (size > MAX_POSSIBLE_BLOCK_SIZE)\n      {\n         crnd_mem_error(\"crnd_malloc: size too big\");\n         return NULL;\n      }\n\n      size_t actual_size = size;\n      void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);\n\n      if (pActual_size)\n         *pActual_size = actual_size;\n\n      CRND_ASSERT(((uint32)p_new & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0);\n\n      return p_new;\n   }\n\n   void crnd_free(void* p)\n   {\n      if (!p)\n         return;\n\n      if ((uint32)reinterpret_cast<ptr_bits>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1))\n      {\n         crnd_mem_error(\"crnd_free: bad ptr\");\n         return;\n      }\n\n      (*g_pRealloc)(p, 0, NULL, true, g_pUser_data);\n   }\n\n   size_t crnd_msize(void* p)\n   {\n      if (!p)\n         return 0;\n\n      if ((uint32)reinterpret_cast<ptr_bits>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1))\n      {\n         crnd_mem_error(\"crnd_msize: bad ptr\");\n         return 0;\n      }\n\n      return (*g_pMSize)(p, g_pUser_data);\n   }\n\n} // namespace crnd\n\n// File: crnd_math.cpp\nnamespace crnd\n{\n   namespace math\n   {\n      uint32 g_bitmasks[32] =\n      {\n         1U <<  0U,         1U <<  1U,          1U <<  2U,        1U <<  3U,\n         1U <<  4U,         1U <<  5U,          1U <<  6U,        1U <<  7U,\n         1U <<  8U,         1U <<  9U,          1U << 10U,        1U << 11U,\n         1U << 12U,         1U << 13U,          1U << 14U,        1U << 15U,\n         1U << 16U,         1U << 17U,          1U << 18U,        1U << 19U,\n         1U << 20U,         1U << 21U,          1U << 22U,        1U << 23U,\n         1U << 24U,         1U << 25U,          1U << 26U,        1U << 27U,\n         1U << 28U,         1U << 29U,          1U << 30U,        1U << 31U\n      };\n\n   } // namespace math\n} // namespace crnd\n\n// File: crnd_info.cpp\nnamespace crnd\n{\n#define CRND_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U))\n\n   uint32 crnd_crn_format_to_fourcc(crn_format fmt)\n   {\n      switch (fmt)\n      {\n         case cCRNFmtDXT1:        return CRND_FOURCC('D', 'X', 'T', '1');\n         case cCRNFmtDXT3:        return CRND_FOURCC('D', 'X', 'T', '3');\n         case cCRNFmtDXT5:        return CRND_FOURCC('D', 'X', 'T', '5');\n         case cCRNFmtDXN_XY:      return CRND_FOURCC('A', '2', 'X', 'Y');\n         case cCRNFmtDXN_YX:      return CRND_FOURCC('A', 'T', 'I', '2');\n         case cCRNFmtDXT5A:       return CRND_FOURCC('A', 'T', 'I', '1');\n         case cCRNFmtDXT5_CCxY:   return CRND_FOURCC('C', 'C', 'x', 'Y');\n         case cCRNFmtDXT5_xGxR:   return CRND_FOURCC('x', 'G', 'x', 'R');\n         case cCRNFmtDXT5_xGBR:   return CRND_FOURCC('x', 'G', 'B', 'R');\n         case cCRNFmtDXT5_AGBR:   return CRND_FOURCC('A', 'G', 'B', 'R');\n         case cCRNFmtETC1:        return CRND_FOURCC('E', 'T', 'C', '1');\n         default: break;\n      }\n      CRND_ASSERT(false);\n      return 0;\n   }\n\n   crn_format crnd_get_fundamental_dxt_format(crn_format fmt)\n   {\n      switch (fmt)\n      {\n         case cCRNFmtDXT5_CCxY:\n         case cCRNFmtDXT5_xGxR:\n         case cCRNFmtDXT5_xGBR:\n         case cCRNFmtDXT5_AGBR:\n            return cCRNFmtDXT5;\n         default: break;\n      }\n      return fmt;\n   }\n\n   uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt)\n   {\n      switch (fmt)\n      {\n         case cCRNFmtDXT1:\n         case cCRNFmtDXT5A:\n         case cCRNFmtETC1:\n            return 4;\n         case cCRNFmtDXT3:\n         case cCRNFmtDXT5:\n         case cCRNFmtDXN_XY:\n         case cCRNFmtDXN_YX:\n         case cCRNFmtDXT5_CCxY:\n         case cCRNFmtDXT5_xGxR:\n         case cCRNFmtDXT5_xGBR:\n         case cCRNFmtDXT5_AGBR:\n            return 8;\n         default: break;\n      }\n      CRND_ASSERT(false);\n      return 0;\n   }\n\n   uint32 crnd_get_bytes_per_dxt_block(crn_format fmt)\n   {\n      return (crnd_get_crn_format_bits_per_texel(fmt) << 4) >> 3;\n   }\n\n   // TODO: tmp_header isn't used/This function is a helper to support old headers.\n   const crn_header* crnd_get_header(crn_header& tmp_header, const void* pData, uint32 data_size)\n   {\n      tmp_header;\n\n      if ((!pData) || (data_size < sizeof(crn_header)))\n         return NULL;\n\n      const crn_header& file_header = *static_cast<const crn_header*>(pData);\n      if (file_header.m_sig != crn_header::cCRNSigValue)\n         return NULL;\n\n      if ((file_header.m_header_size < sizeof(crn_header)) || (data_size < file_header.m_data_size))\n         return NULL;\n\n      return &file_header;\n   }\n\n   bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info)\n   {\n      if (pFile_info)\n      {\n         if (pFile_info->m_struct_size != sizeof(crn_file_info))\n            return false;\n\n         memset(&pFile_info->m_struct_size + 1, 0, sizeof(crn_file_info) - sizeof(pFile_info->m_struct_size));\n      }\n\n      if ((!pData) || (data_size < cCRNHeaderMinSize))\n         return false;\n\n      crn_header tmp_header;\n      const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size);\n      if (!pHeader)\n         return false;\n\n      const uint32 header_crc = crc16(&pHeader->m_data_size, (uint32)(pHeader->m_header_size - ((const uint8*)&pHeader->m_data_size - (const uint8*)pHeader)));\n      if (header_crc != pHeader->m_header_crc16)\n         return false;\n\n      const uint32 data_crc = crc16((const uint8*)pData + pHeader->m_header_size, pHeader->m_data_size - pHeader->m_header_size);\n      if (data_crc != pHeader->m_data_crc16)\n         return false;\n\n      if ((pHeader->m_faces != 1) && (pHeader->m_faces != 6))\n         return false;\n      if ((pHeader->m_width < 1) || (pHeader->m_width > cCRNMaxLevelResolution))\n         return false;\n      if ((pHeader->m_height < 1) || (pHeader->m_height > cCRNMaxLevelResolution))\n         return false;\n      if ((pHeader->m_levels < 1) || (pHeader->m_levels > utils::compute_max_mips(pHeader->m_width, pHeader->m_height)))\n         return false;\n      if (((int)pHeader->m_format < cCRNFmtDXT1) || ((int)pHeader->m_format >= cCRNFmtTotal))\n         return false;\n\n      if (pFile_info)\n      {\n         pFile_info->m_actual_data_size = pHeader->m_data_size;\n         pFile_info->m_header_size = pHeader->m_header_size;\n         pFile_info->m_total_palette_size = pHeader->m_color_endpoints.m_size + pHeader->m_color_selectors.m_size + pHeader->m_alpha_endpoints.m_size + pHeader->m_alpha_selectors.m_size;\n         pFile_info->m_tables_size = pHeader->m_tables_size;\n\n         pFile_info->m_levels = pHeader->m_levels;\n\n         for (uint32 i = 0; i < pHeader->m_levels; i++)\n         {\n            uint32 next_ofs = pHeader->m_data_size;\n\n            // assumes the levels are packed together sequentially\n            if ((i + 1) < pHeader->m_levels)\n               next_ofs = pHeader->m_level_ofs[i + 1];\n\n            pFile_info->m_level_compressed_size[i] = next_ofs - pHeader->m_level_ofs[i];\n         }\n\n         pFile_info->m_color_endpoint_palette_entries = pHeader->m_color_endpoints.m_num;\n         pFile_info->m_color_selector_palette_entries = pHeader->m_color_selectors.m_num;;\n         pFile_info->m_alpha_endpoint_palette_entries = pHeader->m_alpha_endpoints.m_num;;\n         pFile_info->m_alpha_selector_palette_entries = pHeader->m_alpha_selectors.m_num;;\n      }\n\n      return true;\n   }\n\n   bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pInfo)\n   {\n      if ((!pData) || (data_size < sizeof(crn_header)) || (!pInfo))\n         return false;\n\n      if (pInfo->m_struct_size != sizeof(crn_texture_info))\n         return false;\n\n      crn_header tmp_header;\n      const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size);\n      if (!pHeader)\n         return false;\n\n      pInfo->m_width = pHeader->m_width;\n      pInfo->m_height = pHeader->m_height;\n      pInfo->m_levels = pHeader->m_levels;\n      pInfo->m_faces = pHeader->m_faces;\n      pInfo->m_format = static_cast<crn_format>((uint32)pHeader->m_format);\n      pInfo->m_bytes_per_block = ((pHeader->m_format == cCRNFmtDXT1) || (pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16;\n      pInfo->m_userdata0 = pHeader->m_userdata0;\n      pInfo->m_userdata1 = pHeader->m_userdata1;\n\n      return true;\n   }\n\n   bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info)\n   {\n      if ((!pData) || (data_size < cCRNHeaderMinSize) || (!pLevel_info))\n         return false;\n\n      if (pLevel_info->m_struct_size != sizeof(crn_level_info))\n         return false;\n\n      crn_header tmp_header;\n      const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size);\n      if (!pHeader)\n         return false;\n\n      if (level_index >= pHeader->m_levels)\n         return false;\n\n      uint32 width = math::maximum<uint32>(1U, pHeader->m_width >> level_index);\n      uint32 height = math::maximum<uint32>(1U, pHeader->m_height >> level_index);\n\n      pLevel_info->m_width = width;\n      pLevel_info->m_height = height;\n      pLevel_info->m_faces = pHeader->m_faces;\n      pLevel_info->m_blocks_x = (width + 3) >> 2;\n      pLevel_info->m_blocks_y = (height + 3) >> 2;\n      pLevel_info->m_bytes_per_block = ((pHeader->m_format == cCRNFmtDXT1) || (pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16;\n      pLevel_info->m_format = static_cast<crn_format>((uint32)pHeader->m_format);\n\n      return true;\n   }\n\n   const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize)\n   {\n      if (pSize)\n         *pSize = 0;\n\n      if ((!pData) || (data_size < cCRNHeaderMinSize))\n         return NULL;\n\n      crn_header tmp_header;\n      const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size);\n      if (!pHeader)\n         return NULL;\n\n      if (level_index >= pHeader->m_levels)\n         return NULL;\n\n      uint32 cur_level_ofs = pHeader->m_level_ofs[level_index];\n\n      if (pSize)\n      {\n         uint32 next_level_ofs = data_size;\n         if ((level_index + 1) < (pHeader->m_levels))\n            next_level_ofs = pHeader->m_level_ofs[level_index + 1];\n\n         *pSize = next_level_ofs - cur_level_ofs;\n      }\n\n      return static_cast<const uint8*>(pData) + cur_level_ofs;\n   }\n\n   uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size)\n   {\n      if ((!pData) || (data_size < cCRNHeaderMinSize))\n         return false;\n\n      crn_header tmp_header;\n      const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size);\n      if (!pHeader)\n         return false;\n\n      uint32 size = pHeader->m_header_size;\n\n      size = math::maximum(size, pHeader->m_color_endpoints.m_ofs + pHeader->m_color_endpoints.m_size);\n      size = math::maximum(size, pHeader->m_color_selectors.m_ofs + pHeader->m_color_selectors.m_size);\n      size = math::maximum(size, pHeader->m_alpha_endpoints.m_ofs + pHeader->m_alpha_endpoints.m_size);\n      size = math::maximum(size, pHeader->m_alpha_selectors.m_ofs + pHeader->m_alpha_selectors.m_size);\n      size = math::maximum(size, pHeader->m_tables_ofs + pHeader->m_tables_size);\n\n      return size;\n   }\n\n   bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size)\n   {\n      if ((!pData) || (data_size < cCRNHeaderMinSize))\n         return false;\n\n      crn_header tmp_header;\n      const crn_header* pHeader = crnd_get_header(tmp_header, pData, data_size);\n      if (!pHeader)\n         return false;\n\n      if (pHeader->m_flags & cCRNHeaderFlagSegmented)\n         return false;\n\n      const uint actual_base_data_size = crnd_get_segmented_file_size(pData, data_size);\n      if (base_data_size < actual_base_data_size)\n         return false;\n\n      memcpy(pBase_data, pData, actual_base_data_size);\n\n      crn_header& new_header = *static_cast<crn_header*>(pBase_data);\n      new_header.m_flags = new_header.m_flags | cCRNHeaderFlagSegmented;\n      new_header.m_data_size = actual_base_data_size;\n\n      new_header.m_data_crc16 = crc16((const uint8*)pBase_data + new_header.m_header_size, new_header.m_data_size - new_header.m_header_size);\n\n      new_header.m_header_crc16 = crc16(&new_header.m_data_size, new_header.m_header_size - (uint32)((const uint8*)&new_header.m_data_size - (const uint8*)&new_header));\n\n      CRND_ASSERT(crnd_validate_file(&new_header, actual_base_data_size, NULL));\n\n      return true;\n   }\n\n} // namespace crnd\n\n// File: symbol_codec.cpp\nnamespace crnd\n{\n   static_huffman_data_model::static_huffman_data_model() :\nm_total_syms(0),\nm_pDecode_tables(NULL)\n{\n}\n\nstatic_huffman_data_model::static_huffman_data_model(const static_huffman_data_model& other) :\nm_total_syms(0),\nm_pDecode_tables(NULL)\n{\n   *this = other;\n}\n\nstatic_huffman_data_model::~static_huffman_data_model()\n{\n   if (m_pDecode_tables)\n      crnd_delete(m_pDecode_tables);\n}\n\nstatic_huffman_data_model& static_huffman_data_model::operator=(const static_huffman_data_model& rhs)\n{\n   if (this == &rhs)\n      return *this;\n\n   m_total_syms = rhs.m_total_syms;\n   m_code_sizes = rhs.m_code_sizes;\n   if (m_code_sizes.get_alloc_failed())\n   {\n      clear();\n      return *this;\n   }\n\n   if (rhs.m_pDecode_tables)\n   {\n      if (m_pDecode_tables)\n         *m_pDecode_tables = *rhs.m_pDecode_tables;\n      else\n         m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>(*rhs.m_pDecode_tables);\n   }\n   else\n   {\n      crnd_delete(m_pDecode_tables);\n      m_pDecode_tables = NULL;\n   }\n\n   return *this;\n}\n\nvoid static_huffman_data_model::clear()\n{\n   m_total_syms = 0;\n   m_code_sizes.clear();\n   if (m_pDecode_tables)\n   {\n      crnd_delete(m_pDecode_tables);\n      m_pDecode_tables = NULL;\n   }\n}\n\nbool static_huffman_data_model::init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit)\n{\n   CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1));\n\n   code_size_limit = math::minimum(code_size_limit, prefix_coding::cMaxExpectedCodeSize);\n\n   if (!m_code_sizes.resize(total_syms))\n      return false;\n\n   uint32 min_code_size = cUINT32_MAX;\n   uint32 max_code_size = 0;\n\n   for (uint32 i = 0; i < total_syms; i++)\n   {\n      uint32 s = pCode_sizes[i];\n      m_code_sizes[i] = static_cast<uint8>(s);\n      min_code_size = math::minimum(min_code_size, s);\n      max_code_size = math::maximum(max_code_size, s);\n   }\n\n   if ((max_code_size < 1) || (max_code_size > 32) || (min_code_size > code_size_limit))\n      return false;\n\n   if (max_code_size > code_size_limit)\n      return false;\n\n   if (!m_pDecode_tables)\n      m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>();\n\n   if (!m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits()))\n      return false;\n\n   return true;\n}\n\nbool static_huffman_data_model::prepare_decoder_tables()\n{\n   uint32 total_syms = m_code_sizes.size();\n\n   CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms));\n\n   m_total_syms = total_syms;\n\n   if (!m_pDecode_tables)\n      m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>();\n\n   return m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits());\n}\n\nuint static_huffman_data_model::compute_decoder_table_bits() const\n{\n#if CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE\n   return prefix_coding::cMaxTableBits;\n#else\n   uint32 decoder_table_bits = 0;\n   if (m_total_syms > 16)\n      decoder_table_bits = static_cast<uint8>(math::minimum(1 + math::ceil_log2i(m_total_syms), prefix_coding::cMaxTableBits));\n   return decoder_table_bits;\n#endif\n}\n\nsymbol_codec::symbol_codec() :\n  m_pDecode_buf(NULL),\n  m_pDecode_buf_next(NULL),\n  m_pDecode_buf_end(NULL),\n  m_decode_buf_size(0),\n  m_bit_buf(0),\n  m_bit_count(0)\n{\n}\n\n// Code length encoding symbols:\n// 0-16 - actual code lengths\nconst uint32 cMaxCodelengthCodes      = 21;\n\nconst uint32 cSmallZeroRunCode        = 17;\nconst uint32 cLargeZeroRunCode        = 18;\nconst uint32 cSmallRepeatCode         = 19;\nconst uint32 cLargeRepeatCode         = 20;\n\nconst uint32 cMinSmallZeroRunSize     = 3;\nconst uint32 cMaxSmallZeroRunSize     = 10;\nconst uint32 cMinLargeZeroRunSize     = 11;\nconst uint32 cMaxLargeZeroRunSize     = 138;\n\nconst uint32 cSmallMinNonZeroRunSize  = 3;\nconst uint32 cSmallMaxNonZeroRunSize  = 6;\nconst uint32 cLargeMinNonZeroRunSize  = 7;\nconst uint32 cLargeMaxNonZeroRunSize  = 70;\n\nconst uint32 cSmallZeroRunExtraBits   = 3;\nconst uint32 cLargeZeroRunExtraBits   = 7;\nconst uint32 cSmallNonZeroRunExtraBits = 2;\nconst uint32 cLargeNonZeroRunExtraBits = 6;\n\nstatic const uint8 g_most_probable_codelength_codes[] =\n{\n   cSmallZeroRunCode, cLargeZeroRunCode,\n   cSmallRepeatCode,  cLargeRepeatCode,\n\n   0, 8,\n   7, 9,\n   6, 10,\n   5, 11,\n   4, 12,\n   3, 13,\n   2, 14,\n   1, 15,\n   16\n};\nconst uint32 cNumMostProbableCodelengthCodes = sizeof(g_most_probable_codelength_codes) / sizeof(g_most_probable_codelength_codes[0]);\n\nbool symbol_codec::decode_receive_static_data_model(static_huffman_data_model& model)\n{\n   const uint32 total_used_syms = decode_bits(math::total_bits(prefix_coding::cMaxSupportedSyms));\n\n   if (!total_used_syms)\n   {\n      model.clear();\n      return true;\n   }\n\n   if (!model.m_code_sizes.resize(total_used_syms))\n      return false;\n\n   memset(&model.m_code_sizes[0], 0, sizeof(model.m_code_sizes[0]) * total_used_syms);\n\n   const uint32 num_codelength_codes_to_send = decode_bits(5);\n   if ((num_codelength_codes_to_send < 1) || (num_codelength_codes_to_send > cMaxCodelengthCodes))\n      return false;\n\n   static_huffman_data_model dm;\n   if (!dm.m_code_sizes.resize(cMaxCodelengthCodes))\n      return false;\n\n   for (uint32 i = 0; i < num_codelength_codes_to_send; i++)\n      dm.m_code_sizes[g_most_probable_codelength_codes[i]] = static_cast<uint8>(decode_bits(3));\n\n   if (!dm.prepare_decoder_tables())\n      return false;\n\n   uint32 ofs = 0;\n   while (ofs < total_used_syms)\n   {\n      const uint32 num_remaining = total_used_syms - ofs;\n\n      uint32 code = decode(dm);\n      if (code <= 16)\n         model.m_code_sizes[ofs++] = static_cast<uint8>(code);\n      else if (code == cSmallZeroRunCode)\n      {\n         uint32 len = decode_bits(cSmallZeroRunExtraBits) + cMinSmallZeroRunSize;\n         if (len > num_remaining)\n            return false;\n         ofs += len;\n      }\n      else if (code == cLargeZeroRunCode)\n      {\n         uint32 len = decode_bits(cLargeZeroRunExtraBits) + cMinLargeZeroRunSize;\n         if (len > num_remaining)\n            return false;\n         ofs += len;\n      }\n      else if ((code == cSmallRepeatCode) || (code == cLargeRepeatCode))\n      {\n         uint32 len;\n         if (code == cSmallRepeatCode)\n            len = decode_bits(cSmallNonZeroRunExtraBits) + cSmallMinNonZeroRunSize;\n         else\n            len = decode_bits(cLargeNonZeroRunExtraBits) + cLargeMinNonZeroRunSize;\n\n         if ((!ofs) || (len > num_remaining))\n            return false;\n         const uint32 prev = model.m_code_sizes[ofs - 1];\n         if (!prev)\n            return false;\n         const uint32 end = ofs + len;\n         while (ofs < end)\n            model.m_code_sizes[ofs++] = static_cast<uint8>(prev);\n      }\n      else\n      {\n         CRND_ASSERT(0);\n         return false;\n      }\n   }\n\n   if (ofs != total_used_syms)\n      return false;\n\n   return model.prepare_decoder_tables();\n}\n\nbool symbol_codec::start_decoding(const uint8* pBuf, uint32 buf_size)\n{\n   if (!buf_size)\n      return false;\n\n   m_pDecode_buf = pBuf;\n   m_pDecode_buf_next = pBuf;\n   m_decode_buf_size = buf_size;\n   m_pDecode_buf_end = pBuf + buf_size;\n\n   get_bits_init();\n\n   return true;\n}\n\nvoid symbol_codec::get_bits_init()\n{\n   m_bit_buf = 0;\n   m_bit_count = 0;\n}\n\nuint32 symbol_codec::decode_bits(uint32 num_bits)\n{\n   if (!num_bits)\n      return 0;\n\n   if (num_bits > 16)\n   {\n      uint32 a = get_bits(num_bits - 16);\n      uint32 b = get_bits(16);\n\n      return (a << 16) | b;\n   }\n   else\n      return get_bits(num_bits);\n}\n\nuint32 symbol_codec::get_bits(uint32 num_bits)\n{\n   CRND_ASSERT(num_bits <= 32U);\n\n   while (m_bit_count < (int)num_bits)\n   {\n      bit_buf_type c = 0;\n      if (m_pDecode_buf_next != m_pDecode_buf_end)\n         c = *m_pDecode_buf_next++;\n\n      m_bit_count += 8;\n      CRND_ASSERT(m_bit_count <= cBitBufSize);\n\n      m_bit_buf |= (c << (cBitBufSize - m_bit_count));\n   }\n\n   uint32 result = static_cast<uint32>(m_bit_buf >> (cBitBufSize - num_bits));\n\n   m_bit_buf <<= num_bits;\n   m_bit_count -= num_bits;\n\n   return result;\n}\n\nuint32 symbol_codec::decode(const static_huffman_data_model& model)\n{\n   const prefix_coding::decoder_tables* pTables = model.m_pDecode_tables;\n\n   if (m_bit_count < 24)\n   {\n      if (m_bit_count < 16)\n      {\n         uint32 c0 = 0, c1 = 0;\n         const uint8* p = m_pDecode_buf_next;\n         if (p < m_pDecode_buf_end) c0 = *p++;\n         if (p < m_pDecode_buf_end) c1 = *p++;\n         m_pDecode_buf_next = p;\n         m_bit_count += 16;\n         uint32 c = (c0 << 8) | c1;\n         m_bit_buf |= (c << (32 - m_bit_count));\n      }\n      else\n      {\n         uint32 c = (m_pDecode_buf_next < m_pDecode_buf_end) ? *m_pDecode_buf_next++ : 0;\n         m_bit_count += 8;\n         m_bit_buf |= (c << (32 - m_bit_count));\n      }\n   }\n\n   uint32 k = (m_bit_buf >> 16) + 1;\n   uint32 sym, len;\n\n   if (k <= pTables->m_table_max_code)\n   {\n      uint32 t = pTables->m_lookup[m_bit_buf >> (32 - pTables->m_table_bits)];\n\n      CRND_ASSERT(t != cUINT32_MAX);\n      sym = t & cUINT16_MAX;\n      len = t >> 16;\n\n      CRND_ASSERT(model.m_code_sizes[sym] == len);\n   }\n   else\n   {\n      len = pTables->m_decode_start_code_size;\n\n      for ( ; ; )\n      {\n         if (k <= pTables->m_max_codes[len - 1])\n            break;\n         len++;\n      }\n\n      int val_ptr = pTables->m_val_ptrs[len - 1] + (m_bit_buf >> (32 - len));\n\n      if (((uint32)val_ptr >= model.m_total_syms))\n      {\n         // corrupted stream, or a bug\n         CRND_ASSERT(0);\n         return 0;\n      }\n\n      sym = pTables->m_sorted_symbol_order[val_ptr];\n   }\n\n   m_bit_buf <<= len;\n   m_bit_count -= len;\n\n   return sym;\n}\n\n   uint64 symbol_codec::stop_decoding()\n   {\n#if 0\n      uint32 i = get_bits(4);\n      uint32 k = get_bits(3);\n      i, k;\n      CRND_ASSERT((i == 15) && (k == 3));\n#endif\n\n      uint64 n = static_cast<uint64>(m_pDecode_buf_next - m_pDecode_buf);\n\n      return n;\n   }\n\n} // namespace crnd\n\n// File: crnd_dxt_hc_common.cpp\nnamespace crnd\n{\n   chunk_encoding_desc g_chunk_encodings[cNumChunkEncodings] =\n   {\n      { 1, { { 0, 0, 8, 8, 0 } } },\n\n      { 2, { { 0, 0, 8, 4, 1 }, { 0, 4, 8, 4, 2 } } },\n      { 2, { { 0, 0, 4, 8, 3 }, { 4, 0, 4, 8, 4 } } },\n\n      { 3, { { 0, 0, 8, 4, 1 }, { 0, 4, 4, 4, 7 }, { 4, 4, 4, 4, 8 } } },\n      { 3, { { 0, 4, 8, 4, 2 }, { 0, 0, 4, 4, 5 }, { 4, 0, 4, 4, 6 } } },\n\n      { 3, { { 0, 0, 4, 8, 3 }, { 4, 0, 4, 4, 6 }, { 4, 4, 4, 4, 8 } } },\n      { 3, { { 4, 0, 4, 8, 4 }, { 0, 0, 4, 4, 5 }, { 0, 4, 4, 4, 7 } } },\n\n      { 4, { { 0, 0, 4, 4, 5 }, { 4, 0, 4, 4, 6 }, { 0, 4, 4, 4, 7 }, { 4, 4, 4, 4, 8 } } }\n   };\n\n   chunk_tile_desc g_chunk_tile_layouts[cNumChunkTileLayouts] =\n   {\n      // 2x2\n      { 0, 0, 8, 8, 0 },\n\n      // 2x1\n      { 0, 0, 8, 4, 1 },\n      { 0, 4, 8, 4, 2 },\n\n      // 1x2\n      { 0, 0, 4, 8, 3 },\n      { 4, 0, 4, 8, 4 },\n\n      // 1x1\n      { 0, 0, 4, 4, 5 },\n      { 4, 0, 4, 4, 6 },\n      { 0, 4, 4, 4, 7 },\n      { 4, 4, 4, 4, 8 }\n   };\n\n} // namespace crnd\n\n// File: crnd_dxt.cpp\nnamespace crnd\n{\n   const uint8 g_dxt1_to_linear[cDXT1SelectorValues]     = { 0U, 3U, 1U, 2U };\n   const uint8 g_dxt1_from_linear[cDXT1SelectorValues]   = { 0U, 2U, 3U, 1U };\n\n   const uint8 g_dxt5_to_linear[cDXT5SelectorValues]     = { 0U, 7U, 1U, 2U, 3U, 4U, 5U, 6U };\n   const uint8 g_dxt5_from_linear[cDXT5SelectorValues]   = { 0U, 2U, 3U, 4U, 5U, 6U, 7U, 1U };\n\n   const uint8 g_six_alpha_invert_table[cDXT5SelectorValues] = { 1, 0, 5, 4, 3, 2, 6, 7 };\n   const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues] = { 1, 0, 7, 6, 5, 4, 3, 2 };\n\n   uint16 dxt1_block::pack_color(const color_quad_u8& color, bool scaled, uint32 bias)\n   {\n      uint32 r = color.r;\n      uint32 g = color.g;\n      uint32 b = color.b;\n\n      if (scaled)\n      {\n         r = (r * 31U + bias) / 255U;\n         g = (g * 63U + bias) / 255U;\n         b = (b * 31U + bias) / 255U;\n      }\n\n      r = math::minimum(r, 31U);\n      g = math::minimum(g, 63U);\n      b = math::minimum(b, 31U);\n\n      return static_cast<uint16>(b | (g << 5U) | (r << 11U));\n   }\n\n   uint16 dxt1_block::pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias)\n   {\n      return pack_color(color_quad_u8(r, g, b, 0), scaled, bias);\n   }\n\n   color_quad_u8 dxt1_block::unpack_color(uint16 packed_color, bool scaled, uint32 alpha)\n   {\n      uint32 b = packed_color & 31U;\n      uint32 g = (packed_color >> 5U) & 63U;\n      uint32 r = (packed_color >> 11U) & 31U;\n\n      if (scaled)\n      {\n         b = (b << 3U) | (b >> 2U);\n         g = (g << 2U) | (g >> 4U);\n         r = (r << 3U) | (r >> 2U);\n      }\n\n      return color_quad_u8(r, g, b, alpha);\n   }\n\n   void dxt1_block::unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled)\n   {\n      color_quad_u8 c(unpack_color(packed_color, scaled, 0));\n      r = c.r;\n      g = c.g;\n      b = c.b;\n   }\n\n   uint32 dxt1_block::get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1)\n   {\n      color_quad_u8 c0(unpack_color(color0, true));\n      color_quad_u8 c1(unpack_color(color1, true));\n\n      pDst[0] = c0;\n      pDst[1] = c1;\n      pDst[2].set( (c0.r + c1.r) >> 1U, (c0.g + c1.g) >> 1U, (c0.b + c1.b) >> 1U, 255U);\n      pDst[3].set(0, 0, 0, 0);\n\n      return 3;\n   }\n\n   uint32 dxt1_block::get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1)\n   {\n      color_quad_u8 c0(unpack_color(color0, true));\n      color_quad_u8 c1(unpack_color(color1, true));\n\n      pDst[0] = c0;\n      pDst[1] = c1;\n\n      // 12/14/09 - Supposed to round according to DX docs, but this conflicts with the OpenGL S3TC spec. ?\n      // Turns out some GPU's round and some don't. Great.\n      //pDst[2].set( (c0.r * 2 + c1.r + 1) / 3, (c0.g * 2 + c1.g + 1) / 3, (c0.b * 2 + c1.b + 1) / 3, 255U);\n      //pDst[3].set( (c1.r * 2 + c0.r + 1) / 3, (c1.g * 2 + c0.g + 1) / 3, (c1.b * 2 + c0.b + 1) / 3, 255U);\n\n      pDst[2].set( (c0.r * 2 + c1.r) / 3, (c0.g * 2 + c1.g) / 3, (c0.b * 2 + c1.b) / 3, 255U);\n      pDst[3].set( (c1.r * 2 + c0.r) / 3, (c1.g * 2 + c0.g) / 3, (c1.b * 2 + c0.b) / 3, 255U);\n\n      return 4;\n   }\n\n   uint32 dxt1_block::get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1)\n   {\n      if (color0 > color1)\n         return get_block_colors4(pDst, color0, color1);\n      else\n         return get_block_colors3(pDst, color0, color1);\n   }\n\n   color_quad_u8 dxt1_block::unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha)\n   {\n      CRND_ASSERT(index < 2);\n      return unpack_color( static_cast<uint16>((endpoints >> (index * 16U)) & 0xFFFFU), scaled, alpha );\n   }\n\n   uint32 dxt1_block::pack_endpoints(uint32 lo, uint32 hi)\n   {\n      CRND_ASSERT((lo <= 0xFFFFU) && (hi <= 0xFFFFU));\n      return lo | (hi << 16U);\n   }\n\n   void dxt3_block::set_alpha(uint32 x, uint32 y, uint32 value, bool scaled)\n   {\n      CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));\n\n      if (scaled)\n      {\n         CRND_ASSERT(value <= 0xFF);\n         value = (value * 15U + 128U) / 255U;\n      }\n      else\n      {\n         CRND_ASSERT(value <= 0xF);\n      }\n\n      uint32 ofs = (y << 1U) + (x >> 1U);\n      uint32 c = m_alpha[ofs];\n\n      c &= ~(0xF << ((x & 1U) << 2U));\n      c |= (value << ((x & 1U) << 2U));\n\n      m_alpha[ofs] = static_cast<uint8>(c);\n   }\n\n   uint32 dxt3_block::get_alpha(uint32 x, uint32 y, bool scaled) const\n   {\n      CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));\n\n      uint32 value = m_alpha[(y << 1U) + (x >> 1U)];\n      if (x & 1)\n         value >>= 4;\n      value &= 0xF;\n\n      if (scaled)\n         value = (value << 4U) | value;\n\n      return value;\n   }\n\n   uint32 dxt5_block::get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h)\n   {\n      pDst[0].a = static_cast<uint8>(l);\n      pDst[1].a = static_cast<uint8>(h);\n      pDst[2].a = static_cast<uint8>((l * 4 + h    ) / 5);\n      pDst[3].a = static_cast<uint8>((l * 3 + h * 2) / 5);\n      pDst[4].a = static_cast<uint8>((l * 2 + h * 3) / 5);\n      pDst[5].a = static_cast<uint8>((l     + h * 4) / 5);\n      pDst[6].a = 0;\n      pDst[7].a = 255;\n      return 6;\n   }\n\n   uint32 dxt5_block::get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h)\n   {\n      pDst[0].a = static_cast<uint8>(l);\n      pDst[1].a = static_cast<uint8>(h);\n      pDst[2].a = static_cast<uint8>((l * 6 + h    ) / 7);\n      pDst[3].a = static_cast<uint8>((l * 5 + h * 2) / 7);\n      pDst[4].a = static_cast<uint8>((l * 4 + h * 3) / 7);\n      pDst[5].a = static_cast<uint8>((l * 3 + h * 4) / 7);\n      pDst[6].a = static_cast<uint8>((l * 2 + h * 5) / 7);\n      pDst[7].a = static_cast<uint8>((l     + h * 6) / 7);\n      return 8;\n   }\n\n   uint32 dxt5_block::get_block_values(color_quad_u8* pDst, uint32 l, uint32 h)\n   {\n      if (l > h)\n         return get_block_values8(pDst, l, h);\n      else\n         return get_block_values6(pDst, l, h);\n   }\n\n   uint32 dxt5_block::get_block_values6(uint32* pDst, uint32 l, uint32 h)\n   {\n      pDst[0] = l;\n      pDst[1] = h;\n      pDst[2] = (l * 4 + h    ) / 5;\n      pDst[3] = (l * 3 + h * 2) / 5;\n      pDst[4] = (l * 2 + h * 3) / 5;\n      pDst[5] = (l     + h * 4) / 5;\n      pDst[6] = 0;\n      pDst[7] = 255;\n      return 6;\n   }\n\n   uint32 dxt5_block::get_block_values8(uint32* pDst, uint32 l, uint32 h)\n   {\n      pDst[0] = l;\n      pDst[1] = h;\n      pDst[2] = (l * 6 + h    ) / 7;\n      pDst[3] = (l * 5 + h * 2) / 7;\n      pDst[4] = (l * 4 + h * 3) / 7;\n      pDst[5] = (l * 3 + h * 4) / 7;\n      pDst[6] = (l * 2 + h * 5) / 7;\n      pDst[7] = (l     + h * 6) / 7;\n      return 8;\n   }\n\n   uint32 dxt5_block::unpack_endpoint(uint32 packed, uint32 index)\n   {\n      CRND_ASSERT(index < 2);\n      return (packed >> (8 * index)) & 0xFF;\n   }\n\n   uint32 dxt5_block::pack_endpoints(uint32 lo, uint32 hi)\n   {\n      CRND_ASSERT((lo <= 0xFF) && (hi <= 0xFF));\n      return lo | (hi << 8U);\n   }\n\n   uint32 dxt5_block::get_block_values(uint32* pDst, uint32 l, uint32 h)\n   {\n      if (l > h)\n         return get_block_values8(pDst, l, h);\n      else\n         return get_block_values6(pDst, l, h);\n   }\n\n} // namespace crnd\n\n// File: crnd_decode.cpp\n#define CRND_CREATE_BYTE_STREAMS 0\n\nnamespace crnd\n{\n#if CRND_CREATE_BYTE_STREAMS\n   static void write_array_to_file(const char* pFilename, const vector<uint8>& buf)\n   {\n      FILE* pFile = fopen(pFilename, \"wb\");\n      fwrite(&buf[0], buf.size(), 1, pFile);\n      fclose(pFile);\n   }\n#endif\n\n   struct crnd_chunk_tile_desc\n   {\n      // These values are in blocks\n      uint8 m_x_ofs;\n      uint8 m_y_ofs;\n      uint8 m_width;\n      uint8 m_height;\n   };\n\n   struct crnd_chunk_encoding_desc\n   {\n      uint32 m_num_tiles;\n      chunk_tile_desc m_tiles[4];\n   };\n\n#if 0\n   static crnd_chunk_encoding_desc g_crnd_chunk_encodings[cNumChunkEncodings] =\n   {\n      { 1, { { 0, 0, 2, 2 } } },\n\n      { 2, { { 0, 0, 2, 1 }, { 0, 1, 2, 1 } } },\n      { 2, { { 0, 0, 1, 2 }, { 1, 0, 1, 2 } } },\n\n      { 3, { { 0, 0, 2, 1 }, { 0, 1, 1, 1 }, { 1, 1, 1, 1 } } },\n      { 3, { { 0, 1, 2, 1 }, { 0, 0, 1, 1 }, { 1, 0, 1, 1 } } },\n\n      { 3, { { 0, 0, 1, 2 }, { 1, 0, 1, 1 }, { 1, 1, 1, 1 } } },\n      { 3, { { 1, 0, 1, 2 }, { 0, 0, 1, 1 }, { 0, 1, 1, 1 } } },\n\n      { 1, { { 0, 0, 1, 1 }, { 1, 0, 1, 1 }, { 0, 1, 1, 1 }, { 1, 1, 1, 1 } } }\n   };\n#endif\n\n   struct crnd_encoding_tile_indices\n   {\n      uint8 m_tiles[4];\n   };\n\n   static crnd_encoding_tile_indices g_crnd_chunk_encoding_tiles[cNumChunkEncodings] =\n   {\n      { { 0, 0, 0, 0 } },\n\n      { { 0, 0, 1, 1 } },\n      { { 0, 1, 0, 1 } },\n\n      { { 0, 0, 1, 2 } },\n      { { 1, 2, 0, 0 } },\n\n      { { 0, 1, 0, 2 } },\n      { { 1, 0, 2, 0 } },\n\n      { { 0, 1, 2, 3 } }\n   };\n\n   static uint8 g_crnd_chunk_encoding_num_tiles[cNumChunkEncodings] = { 1, 2, 2, 3, 3, 3, 3, 4 };\n\n   class crn_unpacker\n   {\n   public:\n      inline crn_unpacker() :\n         m_magic(cMagicValue),\n         m_pData(NULL),\n         m_data_size(0),\n         m_pHeader(NULL)\n      {\n      }\n\n      inline ~crn_unpacker()\n      {\n         m_magic = 0;\n      }\n\n      inline bool is_valid() const { return m_magic == cMagicValue; }\n\n      bool init(const void* pData, uint32 data_size)\n      {\n         m_pHeader = crnd_get_header(m_tmp_header, pData, data_size);\n         if (!m_pHeader)\n            return false;\n\n         m_pData = static_cast<const uint8*>(pData);\n         m_data_size = data_size;\n\n         if (!init_tables())\n            return false;\n\n         if (!decode_palettes())\n            return false;\n\n         return true;\n      }\n\n      bool unpack_level(\n         void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n         uint32 level_index)\n      {\n         uint32 cur_level_ofs = m_pHeader->m_level_ofs[level_index];\n\n         uint32 next_level_ofs = m_data_size;\n         if ((level_index + 1) < (m_pHeader->m_levels))\n            next_level_ofs = m_pHeader->m_level_ofs[level_index + 1];\n\n         CRND_ASSERT(next_level_ofs > cur_level_ofs);\n\n         return unpack_level(m_pData + cur_level_ofs, next_level_ofs - cur_level_ofs, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);\n      }\n\n      bool unpack_level(\n         const void* pSrc, uint32 src_size_in_bytes,\n         void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n         uint32 level_index)\n      {\n         dst_size_in_bytes;\n\n#ifdef CRND_BUILD_DEBUG\n         for (uint32 f = 0; f < m_pHeader->m_faces; f++)\n            if (!pDst[f])\n               return false;\n#endif\n\n         const uint32 width = math::maximum(m_pHeader->m_width >> level_index, 1U);\n         const uint32 height = math::maximum(m_pHeader->m_height >> level_index, 1U);\n         const uint32 blocks_x = (width + 3U) >> 2U;\n         const uint32 blocks_y = (height + 3U) >> 2U;\n         const uint32 block_size = ((m_pHeader->m_format == cCRNFmtDXT1) || (m_pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16;\n\n         uint32 minimal_row_pitch = block_size * blocks_x;\n         if (!row_pitch_in_bytes)\n            row_pitch_in_bytes = minimal_row_pitch;\n         else if ((row_pitch_in_bytes < minimal_row_pitch) || (row_pitch_in_bytes & 3))\n            return false;\n         if (dst_size_in_bytes < row_pitch_in_bytes * blocks_y)\n            return false;\n\n         const uint32 chunks_x = (blocks_x + 1) >> 1;\n         const uint32 chunks_y = (blocks_y + 1) >> 1;\n\n#if CRND_CREATE_BYTE_STREAMS\n         crnd_trace(\"Index stream: %u bytes\\n\", src_size_in_bytes);\n#endif\n\n         if (!m_codec.start_decoding(static_cast<const crnd::uint8*>(pSrc), src_size_in_bytes))\n            return false;\n\n         bool status = false;\n         switch (m_pHeader->m_format)\n         {\n         case cCRNFmtDXT1:\n            status = unpack_dxt1((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y);\n            break;\n         case cCRNFmtDXT5:\n         case cCRNFmtDXT5_CCxY:\n         case cCRNFmtDXT5_xGBR:\n         case cCRNFmtDXT5_AGBR:\n         case cCRNFmtDXT5_xGxR:\n            status = unpack_dxt5((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y);\n            break;\n         case cCRNFmtDXT5A:\n            status = unpack_dxt5a((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y);\n            break;\n         case cCRNFmtDXN_XY:\n         case cCRNFmtDXN_YX:\n            status = unpack_dxn((uint8**)pDst, dst_size_in_bytes, row_pitch_in_bytes, blocks_x, blocks_y, chunks_x, chunks_y);\n            break;\n         default:\n            return false;\n         }\n         if (!status)\n            return false;\n\n         m_codec.stop_decoding();\n         return true;\n      }\n\n      inline const void* get_data() const { return m_pData; }\n      inline uint32 get_data_size() const { return m_data_size; }\n\n   private:\n      enum { cMagicValue = 0x1EF9CABD };\n      uint32             m_magic;\n\n      const uint8*       m_pData;\n      uint32             m_data_size;\n      crn_header         m_tmp_header;\n      const crn_header*  m_pHeader;\n\n      symbol_codec       m_codec;\n\n      static_huffman_data_model m_chunk_encoding_dm;\n      static_huffman_data_model m_endpoint_delta_dm[2];\n      static_huffman_data_model m_selector_delta_dm[2];\n\n      crnd::vector<uint32> m_color_endpoints;\n      crnd::vector<uint32> m_color_selectors;\n\n      crnd::vector<uint16> m_alpha_endpoints;\n      crnd::vector<uint16> m_alpha_selectors;\n\n      bool init_tables()\n      {\n         if (!m_codec.start_decoding(m_pData + m_pHeader->m_tables_ofs, m_pHeader->m_tables_size))\n            return false;\n\n         if (!m_codec.decode_receive_static_data_model(m_chunk_encoding_dm))\n            return false;\n\n         if ((!m_pHeader->m_color_endpoints.m_num) && (!m_pHeader->m_alpha_endpoints.m_num))\n            return false;\n\n         if (m_pHeader->m_color_endpoints.m_num)\n         {\n            if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[0])) return false;\n            if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[0])) return false;\n         }\n\n         if (m_pHeader->m_alpha_endpoints.m_num)\n         {\n            if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[1])) return false;\n            if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[1])) return false;\n         }\n\n         m_codec.stop_decoding();\n\n         return true;\n      }\n\n      bool decode_palettes()\n      {\n         if (m_pHeader->m_color_endpoints.m_num)\n         {\n            if (!decode_color_endpoints()) return false;\n            if (!decode_color_selectors()) return false;\n         }\n\n         if (m_pHeader->m_alpha_endpoints.m_num)\n         {\n            if (!decode_alpha_endpoints()) return false;\n            if (!decode_alpha_selectors()) return false;\n         }\n\n         return true;\n      }\n\n      bool decode_color_endpoints()\n      {\n         const uint32 num_color_endpoints = m_pHeader->m_color_endpoints.m_num;\n\n         if (!m_color_endpoints.resize(num_color_endpoints))\n            return false;\n\n         if (!m_codec.start_decoding(m_pData + m_pHeader->m_color_endpoints.m_ofs, m_pHeader->m_color_endpoints.m_size))\n            return false;\n\n         static_huffman_data_model dm[2];\n         for (uint32 i = 0; i < 2; i++)\n            if (!m_codec.decode_receive_static_data_model(dm[i]))\n               return false;\n\n         uint32 a = 0, b = 0, c = 0;\n         uint32 d = 0, e = 0, f = 0;\n\n         uint32* CRND_RESTRICT pDst = &m_color_endpoints[0];\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n#if CRND_CREATE_BYTE_STREAMS\n         vector<uint8> byte_stream;\n#endif\n\n         for (uint32 i = 0; i < num_color_endpoints; i++)\n         {\n            uint32 da, db, dc, dd, de, df;\n            CRND_HUFF_DECODE(m_codec, dm[0], da); a = (a + da) & 31;\n            CRND_HUFF_DECODE(m_codec, dm[1], db); b = (b + db) & 63;\n            CRND_HUFF_DECODE(m_codec, dm[0], dc); c = (c + dc) & 31;\n\n            CRND_HUFF_DECODE(m_codec, dm[0], dd); d = (d + dd) & 31;\n            CRND_HUFF_DECODE(m_codec, dm[1], de); e = (e + de) & 63;\n            CRND_HUFF_DECODE(m_codec, dm[0], df); f = (f + df) & 31;\n\n#if CRND_CREATE_BYTE_STREAMS\n            byte_stream.push_back(da);\n            byte_stream.push_back(db);\n            byte_stream.push_back(dc);\n            byte_stream.push_back(dd);\n            byte_stream.push_back(de);\n            byte_stream.push_back(df);\n#endif\n\n            if (c_crnd_little_endian_platform)\n               *pDst++ = c | (b << 5U) | (a << 11U) | (f << 16U) | (e << 21U) | (d << 27U);\n            else\n               *pDst++ = f | (e << 5U) | (d << 11U) | (c << 16U) | (b << 21U) | (a << 27U);\n         }\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n         m_codec.stop_decoding();\n\n#if CRND_CREATE_BYTE_STREAMS\n         write_array_to_file(L\"colorendpoints.bin\", byte_stream);\n         crnd_trace(\"color endpoints: %u\\n\", (uint)m_pHeader->m_color_endpoints.m_size);\n#endif\n\n         return true;\n      }\n\n      bool decode_color_selectors()\n      {\n         const uint32 cMaxSelectorValue = 3U;\n         const uint32 cMaxUniqueSelectorDeltas = cMaxSelectorValue * 2U + 1U;\n\n         const uint32 num_color_selectors = m_pHeader->m_color_selectors.m_num;\n\n         if (!m_codec.start_decoding(m_pData + m_pHeader->m_color_selectors.m_ofs, m_pHeader->m_color_selectors.m_size))\n            return false;\n\n         static_huffman_data_model dm;\n         if (!m_codec.decode_receive_static_data_model(dm))\n            return false;\n\n         int32 delta0[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas];\n         int32 delta1[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas];\n         int32 l = -(int32)cMaxSelectorValue, m = -(int32)cMaxSelectorValue;\n         for (uint32 i = 0; i < (cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas); i++)\n         {\n            delta0[i] = l;\n            delta1[i] = m;\n\n            if (++l > (int32)cMaxSelectorValue)\n            {\n               l = -(int32)cMaxSelectorValue;\n               m++;\n            }\n         }\n\n         uint32 cur[16];\n         utils::zero_object(cur);\n\n         if (!m_color_selectors.resize(num_color_selectors))\n            return false;\n\n         uint32* CRND_RESTRICT pDst = &m_color_selectors[0];\n\n         const uint8* pFrom_linear = g_dxt1_from_linear;\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n#if CRND_CREATE_BYTE_STREAMS\n         vector<uint8> byte_stream;\n#endif\n\n         for (uint32 i = 0; i < num_color_selectors; i++)\n         {\n            for (uint32 j = 0; j < 8; j++)\n            {\n               int32 sym;\n               CRND_HUFF_DECODE(m_codec, dm, sym);\n\n#if CRND_CREATE_BYTE_STREAMS\n               byte_stream.push_back(sym);\n#endif\n\n               cur[j*2+0] = (delta0[sym] + cur[j*2+0]) & 3;\n               cur[j*2+1] = (delta1[sym] + cur[j*2+1]) & 3;\n            }\n\n            if (c_crnd_little_endian_platform)\n            {\n               *pDst++ =\n                  (pFrom_linear[cur[0 ]]      ) | (pFrom_linear[cur[1 ]] <<  2) | (pFrom_linear[cur[2 ]] <<  4) | (pFrom_linear[cur[3 ]] <<  6) |\n                  (pFrom_linear[cur[4 ]] <<  8) | (pFrom_linear[cur[5 ]] << 10) | (pFrom_linear[cur[6 ]] << 12) | (pFrom_linear[cur[7 ]] << 14) |\n                  (pFrom_linear[cur[8 ]] << 16) | (pFrom_linear[cur[9 ]] << 18) | (pFrom_linear[cur[10]] << 20) | (pFrom_linear[cur[11]] << 22) |\n                  (pFrom_linear[cur[12]] << 24) | (pFrom_linear[cur[13]] << 26) | (pFrom_linear[cur[14]] << 28) | (pFrom_linear[cur[15]] << 30);\n            }\n            else\n            {\n               *pDst++ =\n                  (pFrom_linear[cur[8 ]]      ) | (pFrom_linear[cur[9 ]] <<  2) | (pFrom_linear[cur[10]] <<  4) | (pFrom_linear[cur[11]] <<  6) |\n                  (pFrom_linear[cur[12]] <<  8) | (pFrom_linear[cur[13]] << 10) | (pFrom_linear[cur[14]] << 12) | (pFrom_linear[cur[15]] << 14) |\n                  (pFrom_linear[cur[0 ]] << 16) | (pFrom_linear[cur[1 ]] << 18) | (pFrom_linear[cur[2 ]] << 20) | (pFrom_linear[cur[3 ]] << 22) |\n                  (pFrom_linear[cur[4 ]] << 24) | (pFrom_linear[cur[5 ]] << 26) | (pFrom_linear[cur[6 ]] << 28) | (pFrom_linear[cur[7 ]] << 30);\n            }\n         }\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n         m_codec.stop_decoding();\n\n#if CRND_CREATE_BYTE_STREAMS\n         write_array_to_file(L\"colorselectors.bin\", byte_stream);\n         crnd_trace(\"color selectors: %u\\n\", (uint)m_pHeader->m_color_selectors.m_size);\n#endif\n\n         return true;\n      }\n\n      bool decode_alpha_endpoints()\n      {\n         const uint32 num_alpha_endpoints = m_pHeader->m_alpha_endpoints.m_num;\n\n         if (!m_codec.start_decoding(m_pData + m_pHeader->m_alpha_endpoints.m_ofs, m_pHeader->m_alpha_endpoints.m_size))\n            return false;\n\n         static_huffman_data_model dm;\n         if (!m_codec.decode_receive_static_data_model(dm))\n            return false;\n\n         if (!m_alpha_endpoints.resize(num_alpha_endpoints))\n            return false;\n\n         uint16* CRND_RESTRICT pDst = &m_alpha_endpoints[0];\n         uint32 a = 0, b = 0;\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n         for (uint32 i = 0; i < num_alpha_endpoints; i++)\n         {\n            uint sa; CRND_HUFF_DECODE(m_codec, dm, sa);\n            uint sb; CRND_HUFF_DECODE(m_codec, dm, sb);\n\n            a = (sa + a) & 255;\n            b = (sb + b) & 255;\n\n            *pDst++ = (uint16)(a | (b << 8));\n         }\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n         m_codec.stop_decoding();\n\n         return true;\n      }\n\n      bool decode_alpha_selectors()\n      {\n         const uint32 cMaxSelectorValue = 7U;\n         const uint32 cMaxUniqueSelectorDeltas = cMaxSelectorValue * 2U + 1U;\n\n         const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num;\n\n         if (!m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size))\n            return false;\n\n         static_huffman_data_model dm;\n         if (!m_codec.decode_receive_static_data_model(dm))\n            return false;\n\n         int32 delta0[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas];\n         int32 delta1[cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas];\n         int32 l = -(int32)cMaxSelectorValue, m = -(int32)cMaxSelectorValue;\n         for (uint32 i = 0; i < (cMaxUniqueSelectorDeltas * cMaxUniqueSelectorDeltas); i++)\n         {\n            delta0[i] = l;\n            delta1[i] = m;\n\n            if (++l > (int32)cMaxSelectorValue)\n            {\n               l = -(int32)cMaxSelectorValue;\n               m++;\n            }\n         }\n\n         uint32 cur[16];\n         utils::zero_object(cur);\n\n         if (!m_alpha_selectors.resize(num_alpha_selectors * 3))\n            return false;\n\n         uint16* CRND_RESTRICT pDst = &m_alpha_selectors[0];\n\n         const uint8* pFrom_linear = g_dxt5_from_linear;\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n         for (uint32 i = 0; i < num_alpha_selectors; i++)\n         {\n            for (uint32 j = 0; j < 8; j++)\n            {\n               int32 sym;\n               CRND_HUFF_DECODE(m_codec, dm, sym);\n\n               cur[j*2+0] = (delta0[sym] + cur[j*2+0]) & 7;\n               cur[j*2+1] = (delta1[sym] + cur[j*2+1]) & 7;\n               //cur[j*2+0] = ((sym%15)-7 + cur[j*2+0]) & 7;\n               //cur[j*2+1] = ((sym/15)-7 + cur[j*2+1]) & 7;\n            }\n\n#if 0\n            dxt5_block blk;\n            for (uint32 y = 0; y < 4; y++)\n               for (uint32 x = 0; x < 4; x++)\n                  blk.set_selector(x, y, pFrom_linear[cur[x+y*4]]);\n\n            *pDst++ = blk.get_selectors_as_word(0);\n            *pDst++ = blk.get_selectors_as_word(1);\n            *pDst++ = blk.get_selectors_as_word(2);\n#else\n            *pDst++ = (uint16)((pFrom_linear[cur[0 ]]      ) | (pFrom_linear[cur[1 ]] <<  3) | (pFrom_linear[cur[2 ]] <<  6) | (pFrom_linear[cur[3 ]] <<  9) |\n               (pFrom_linear[cur[4 ]] << 12) | (pFrom_linear[cur[5 ]] << 15));\n\n            *pDst++ = (uint16)((pFrom_linear[cur[5 ]] >> 1) | (pFrom_linear[cur[6 ]] << 2) | (pFrom_linear[cur[7 ]] << 5) |\n               (pFrom_linear[cur[8 ]] << 8) | (pFrom_linear[cur[9 ]] << 11) | (pFrom_linear[cur[10]] << 14));\n\n            *pDst++ = (uint16)((pFrom_linear[cur[10]] >> 2) | (pFrom_linear[cur[11]] << 1) | (pFrom_linear[cur[12]] << 4) |\n               (pFrom_linear[cur[13]] << 7) | (pFrom_linear[cur[14]] << 10) | (pFrom_linear[cur[15]] << 13));\n#endif\n         }\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n         m_codec.stop_decoding();\n\n         return true;\n      }\n\n      static inline uint32 tiled_offset_2d_outer(uint32 y, uint32 AlignedWidth, uint32 LogBpp)\n      {\n         uint32 Macro        = ((y >> 5) * (AlignedWidth >> 5)) << (LogBpp + 7);\n         uint32 Micro        = ((y & 6) << 2) << LogBpp;\n\n         return Macro +\n            ((Micro & ~15) << 1) +\n            (Micro & 15) +\n            ((y & 8) << (3 + LogBpp)) + ((y & 1) << 4);\n      }\n\n      static inline uint32 tiled_offset_2d_inner(uint32 x, uint32 y, uint32 LogBpp, uint32 BaseOffset)\n      {\n         uint32 Macro = (x >> 5) << (LogBpp + 7);\n         uint32 Micro = (x & 7) << LogBpp;\n         uint32 Offset  = BaseOffset + Macro + ((Micro & ~15) << 1) + (Micro & 15);\n\n         return ((Offset & ~511) << 3) + ((Offset & 448) << 2) + (Offset & 63) +\n            ((y & 16) << 7) +\n            (((((y & 8) >> 2) + (x >> 3)) & 3) << 6);\n      }\n\n      static inline void limit(uint& x, uint n)\n      {\n         int v = x - n;\n         int msk = (v >> 31);\n         x = (x & msk) | (v & ~msk);\n      }\n\n      bool unpack_dxt1(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y)\n      {\n         dst_size_in_bytes;\n\n         uint32 chunk_encoding_bits = 1;\n\n         const uint32 num_color_endpoints = m_color_endpoints.size();\n         const uint32 num_color_selectors = m_color_selectors.size();\n\n         uint32 prev_color_endpoint_index = 0;\n         uint32 prev_color_selector_index = 0;\n\n         const uint32 num_faces = m_pHeader->m_faces;\n\n         const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U;\n\n         const int32 cBytesPerBlock = 8;\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n#if CRND_CREATE_BYTE_STREAMS\n         vector<uint8> tile_encoding_stream;\n         vector<uint8> endpoint_indices_stream;\n         vector<uint8> selector_indices_stream;\n#endif\n\n         for (uint32 f = 0; f < num_faces; f++)\n         {\n            uint8* CRND_RESTRICT pRow = pDst[f];\n\n            for (uint32 y = 0; y < chunks_y; y++)\n            {\n               int32 start_x = 0;\n               int32 end_x = chunks_x;\n               int32 dir_x = 1;\n               int32 block_delta = cBytesPerBlock*2;\n               uint8* CRND_RESTRICT pBlock = pRow;\n\n               if (y & 1)\n               {\n                  start_x = chunks_x - 1;\n                  end_x = -1;\n                  dir_x = -1;\n                  block_delta = -cBytesPerBlock*2;\n                  pBlock += (chunks_x - 1) * cBytesPerBlock * 2;\n               }\n\n               const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);\n\n               for (int32 x = start_x; x != end_x; x += dir_x)\n               {\n                  uint32 color_endpoints[4];\n\n                  if (chunk_encoding_bits == 1)\n                  {\n                     CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);\n#if CRND_CREATE_BYTE_STREAMS\n                     tile_encoding_stream.push_back(chunk_encoding_bits & 7);\n                     tile_encoding_stream.push_back((chunk_encoding_bits >> 3) & 7);\n                     tile_encoding_stream.push_back((chunk_encoding_bits >> 6) & 7);\n#endif\n                     chunk_encoding_bits |= 512;\n                  }\n\n                  const uint32 chunk_encoding_index = chunk_encoding_bits & 7;\n                  chunk_encoding_bits >>= 3;\n\n                  const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];\n\n                  for (uint32 i = 0; i < num_tiles; i++)\n                  {\n                     uint32 delta;\n                     CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta);\n#if CRND_CREATE_BYTE_STREAMS\n                     endpoint_indices_stream.push_back(delta);\n#endif\n                     prev_color_endpoint_index += delta;\n                     limit(prev_color_endpoint_index, num_color_endpoints);\n                     color_endpoints[i] = m_color_endpoints[prev_color_endpoint_index];\n                  }\n\n                  const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;\n\n                  const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));\n\n                  uint32* CRND_RESTRICT pD = (uint32*)pBlock;\n\n                  if ((!skip_bottom_row) && (!skip_right_col))\n                  {\n                     //CRND_ASSERT( ((uint8*)&pD[4 + row_pitch_in_dwords] - pDst) <= dst_size_in_bytes );\n\n                     pD[0] = color_endpoints[pTile_indices[0]];\n                     CRND_WRITE_BARRIER\n                     uint32 delta0;\n                     CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta0);\n#if CRND_CREATE_BYTE_STREAMS\n                     selector_indices_stream.push_back(delta0);\n#endif\n                     prev_color_selector_index += delta0;\n                     limit(prev_color_selector_index, num_color_selectors);\n                     pD[1] = m_color_selectors[prev_color_selector_index];\n                     CRND_WRITE_BARRIER\n\n                     pD[2] = color_endpoints[pTile_indices[1]];\n                     CRND_WRITE_BARRIER\n                     uint32 delta1;\n                     CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta1);\n#if CRND_CREATE_BYTE_STREAMS\n                     selector_indices_stream.push_back(delta1);\n#endif\n                     prev_color_selector_index += delta1;\n                     limit(prev_color_selector_index, num_color_selectors);\n                     pD[3] = m_color_selectors[prev_color_selector_index];\n                     CRND_WRITE_BARRIER\n\n                     pD[0 + row_pitch_in_dwords] = color_endpoints[pTile_indices[2]];\n                     CRND_WRITE_BARRIER\n                     uint32 delta2;\n                     CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta2);\n#if CRND_CREATE_BYTE_STREAMS\n                     selector_indices_stream.push_back(delta2);\n#endif\n                     prev_color_selector_index += delta2;\n                     limit(prev_color_selector_index, num_color_selectors);\n                     pD[1 + row_pitch_in_dwords] = m_color_selectors[prev_color_selector_index];\n                     CRND_WRITE_BARRIER\n\n                     pD[2 + row_pitch_in_dwords] = color_endpoints[pTile_indices[3]];\n                     CRND_WRITE_BARRIER\n                     uint32 delta3;\n                     CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta3);\n#if CRND_CREATE_BYTE_STREAMS\n                     selector_indices_stream.push_back(delta3);\n#endif\n                     prev_color_selector_index += delta3;\n                     limit(prev_color_selector_index, num_color_selectors);\n                     pD[3 + row_pitch_in_dwords] = m_color_selectors[prev_color_selector_index];\n                     CRND_WRITE_BARRIER\n                  }\n                  else\n                  {\n                     for (uint32 by = 0; by < 2; by++)\n                     {\n                        pD = (uint32*)((uint8*)pBlock + row_pitch_in_bytes * by);\n                        for (uint32 bx = 0; bx < 2; bx++, pD += 2)\n                        {\n                           uint32 delta;\n                           CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta);\n#if CRND_CREATE_BYTE_STREAMS\n                           selector_indices_stream.push_back(delta);\n#endif\n                           prev_color_selector_index += delta;\n                           limit(prev_color_selector_index, num_color_selectors);\n\n                           if (!((bx && skip_right_col) || (by && skip_bottom_row)))\n                           {\n                              pD[0] = color_endpoints[pTile_indices[bx + by * 2]];\n                              CRND_WRITE_BARRIER\n                              pD[1] = m_color_selectors[prev_color_selector_index];\n                              CRND_WRITE_BARRIER\n                           }\n                        }\n                     }\n                  }\n\n                  pBlock += block_delta;\n\n               } // x\n\n               pRow += row_pitch_in_bytes * 2;\n\n            } // y\n\n         } // f\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n#if CRND_CREATE_BYTE_STREAMS\n         write_array_to_file(L\"tile_encodings.bin\", tile_encoding_stream);\n         write_array_to_file(L\"endpoint_indices.bin\", endpoint_indices_stream);\n         write_array_to_file(L\"selector_indices.bin\", selector_indices_stream);\n#endif\n\n         return true;\n      }\n\n      bool unpack_dxt5(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y)\n      {\n         dst_size_in_bytes;\n\n         uint32 chunk_encoding_bits = 1;\n\n         const uint32 num_color_endpoints = m_color_endpoints.size();\n         const uint32 num_color_selectors = m_color_selectors.size();\n         const uint32 num_alpha_endpoints = m_alpha_endpoints.size();\n         const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num;\n\n         uint32 prev_color_endpoint_index = 0;\n         uint32 prev_color_selector_index = 0;\n         uint32 prev_alpha_endpoint_index = 0;\n         uint32 prev_alpha_selector_index = 0;\n\n         const uint32 num_faces = m_pHeader->m_faces;\n\n         //const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U;\n\n         const int32 cBytesPerBlock = 16;\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n         for (uint32 f = 0; f < num_faces; f++)\n         {\n            uint8* CRND_RESTRICT pRow = pDst[f];\n\n            for (uint32 y = 0; y < chunks_y; y++)\n            {\n               int32 start_x = 0;\n               int32 end_x = chunks_x;\n               int32 dir_x = 1;\n               int32 block_delta = cBytesPerBlock*2;\n               uint8* CRND_RESTRICT pBlock = pRow;\n\n               if (y & 1)\n               {\n                  start_x = chunks_x - 1;\n                  end_x = -1;\n                  dir_x = -1;\n                  block_delta = -cBytesPerBlock*2;\n                  pBlock += (chunks_x - 1) * cBytesPerBlock * 2;\n               }\n\n               const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);\n\n               for (int32 x = start_x; x != end_x; x += dir_x)\n               {\n                  uint32 color_endpoints[4];\n                  uint32 alpha_endpoints[4];\n\n                  if (chunk_encoding_bits == 1)\n                  {\n                     CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);\n                     chunk_encoding_bits |= 512;\n                  }\n\n                  const uint32 chunk_encoding_index = chunk_encoding_bits & 7;\n                  chunk_encoding_bits >>= 3;\n\n                  const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];\n\n                  const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;\n\n                  const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));\n\n                  uint32* CRND_RESTRICT pD = (uint32*)pBlock;\n\n                  for (uint32 i = 0; i < num_tiles; i++)\n                  {\n                     uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);\n                     prev_alpha_endpoint_index += delta;\n                     limit(prev_alpha_endpoint_index, num_alpha_endpoints);\n                     alpha_endpoints[i] = m_alpha_endpoints[prev_alpha_endpoint_index];\n                  }\n\n                  for (uint32 i = 0; i < num_tiles; i++)\n                  {\n                     uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta);\n                     prev_color_endpoint_index += delta;\n                     limit(prev_color_endpoint_index, num_color_endpoints);\n                     color_endpoints[i] = m_color_endpoints[prev_color_endpoint_index];\n                  }\n\n                  pD = (uint32*)pBlock;\n                  for (uint32 by = 0; by < 2; by++)\n                  {\n                     for (uint32 bx = 0; bx < 2; bx++, pD += 4)\n                     {\n                        uint32 delta0; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta0);\n                        prev_alpha_selector_index += delta0;\n                        limit(prev_alpha_selector_index, num_alpha_selectors);\n\n                        uint32 delta1; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta1);\n                        prev_color_selector_index += delta1;\n                        limit(prev_color_selector_index, num_color_selectors);\n\n                        if (!((bx && skip_right_col) || (by && skip_bottom_row)))\n                        {\n                           const uint32 tile_index = pTile_indices[bx + by * 2];\n                           const uint16* pAlpha_selectors = &m_alpha_selectors[prev_alpha_selector_index * 3];\n\n#ifdef CRND_BIG_ENDIAN_PLATFORM\n                           pD[0] = (alpha_endpoints[tile_index] << 16) | pAlpha_selectors[0];\n                           CRND_WRITE_BARRIER\n                           pD[1] = (pAlpha_selectors[1] << 16) | pAlpha_selectors[2];\n                           CRND_WRITE_BARRIER\n                           pD[2] = color_endpoints[tile_index];\n                           CRND_WRITE_BARRIER\n                           pD[3] = m_color_selectors[prev_color_selector_index];\n                           CRND_WRITE_BARRIER\n#else\n                           pD[0] = alpha_endpoints[tile_index] | (pAlpha_selectors[0] << 16);\n                           CRND_WRITE_BARRIER\n                           pD[1] = pAlpha_selectors[1] | (pAlpha_selectors[2] << 16);\n                           CRND_WRITE_BARRIER\n                           pD[2] = color_endpoints[tile_index];\n                           CRND_WRITE_BARRIER\n                           pD[3] = m_color_selectors[prev_color_selector_index];\n                           CRND_WRITE_BARRIER\n#endif\n                        }\n                     }\n\n                     pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes);\n                  }\n\n                  pBlock += block_delta;\n\n               } // x\n\n               pRow += row_pitch_in_bytes * 2;\n\n            } // y\n\n         } // f\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n         return true;\n      }\n\n      bool unpack_dxn(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y)\n      {\n         dst_size_in_bytes;\n\n         uint32 chunk_encoding_bits = 1;\n\n         const uint32 num_alpha_endpoints = m_alpha_endpoints.size();\n         const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num;\n\n         uint32 prev_alpha0_endpoint_index = 0;\n         uint32 prev_alpha0_selector_index = 0;\n         uint32 prev_alpha1_endpoint_index = 0;\n         uint32 prev_alpha1_selector_index = 0;\n\n         const uint32 num_faces = m_pHeader->m_faces;\n\n         //const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U;\n\n         const int32 cBytesPerBlock = 16;\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n         for (uint32 f = 0; f < num_faces; f++)\n         {\n            uint8* CRND_RESTRICT pRow = pDst[f];\n\n            for (uint32 y = 0; y < chunks_y; y++)\n            {\n               int32 start_x = 0;\n               int32 end_x = chunks_x;\n               int32 dir_x = 1;\n               int32 block_delta = cBytesPerBlock*2;\n               uint8* CRND_RESTRICT pBlock = pRow;\n\n               if (y & 1)\n               {\n                  start_x = chunks_x - 1;\n                  end_x = -1;\n                  dir_x = -1;\n                  block_delta = -cBytesPerBlock*2;\n                  pBlock += (chunks_x - 1) * cBytesPerBlock * 2;\n               }\n\n               const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);\n\n               for (int32 x = start_x; x != end_x; x += dir_x)\n               {\n                  uint32 alpha0_endpoints[4];\n                  uint32 alpha1_endpoints[4];\n\n                  if (chunk_encoding_bits == 1)\n                  {\n                     CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);\n                     chunk_encoding_bits |= 512;\n                  }\n\n                  const uint32 chunk_encoding_index = chunk_encoding_bits & 7;\n                  chunk_encoding_bits >>= 3;\n\n                  const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];\n\n                  const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;\n\n                  const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));\n\n                  uint32* CRND_RESTRICT pD = (uint32*)pBlock;\n\n                  for (uint32 i = 0; i < num_tiles; i++)\n                  {\n                     uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);\n                     prev_alpha0_endpoint_index += delta;\n                     limit(prev_alpha0_endpoint_index, num_alpha_endpoints);\n                     alpha0_endpoints[i] = m_alpha_endpoints[prev_alpha0_endpoint_index];\n                  }\n\n                  for (uint32 i = 0; i < num_tiles; i++)\n                  {\n                     uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);\n                     prev_alpha1_endpoint_index += delta;\n                     limit(prev_alpha1_endpoint_index, num_alpha_endpoints);\n                     alpha1_endpoints[i] = m_alpha_endpoints[prev_alpha1_endpoint_index];\n                  }\n\n                  pD = (uint32*)pBlock;\n                  for (uint32 by = 0; by < 2; by++)\n                  {\n                     for (uint32 bx = 0; bx < 2; bx++, pD += 4)\n                     {\n                        uint32 delta0; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta0);\n                        prev_alpha0_selector_index += delta0;\n                        limit(prev_alpha0_selector_index, num_alpha_selectors);\n\n                        uint32 delta1; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta1);\n                        prev_alpha1_selector_index += delta1;\n                        limit(prev_alpha1_selector_index, num_alpha_selectors);\n\n                        if (!((bx && skip_right_col) || (by && skip_bottom_row)))\n                        {\n                           const uint32 tile_index = pTile_indices[bx + by * 2];\n                           const uint16* pAlpha0_selectors = &m_alpha_selectors[prev_alpha0_selector_index * 3];\n                           const uint16* pAlpha1_selectors = &m_alpha_selectors[prev_alpha1_selector_index * 3];\n\n#ifdef CRND_BIG_ENDIAN_PLATFORM\n                           pD[0] = (alpha0_endpoints[tile_index] << 16) | pAlpha0_selectors[0];\n                           CRND_WRITE_BARRIER\n                           pD[1] = (pAlpha0_selectors[1] << 16) | pAlpha0_selectors[2];\n                           CRND_WRITE_BARRIER\n                           pD[2] = (alpha1_endpoints[tile_index] << 16) | pAlpha1_selectors[0];\n                           CRND_WRITE_BARRIER\n                           pD[3] = (pAlpha1_selectors[1] << 16) | pAlpha1_selectors[2];\n                           CRND_WRITE_BARRIER\n#else\n                           pD[0] = alpha0_endpoints[tile_index] | (pAlpha0_selectors[0] << 16);\n                           CRND_WRITE_BARRIER\n                           pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);\n                           CRND_WRITE_BARRIER\n                           pD[2] = alpha1_endpoints[tile_index] | (pAlpha1_selectors[0] << 16);\n                           CRND_WRITE_BARRIER\n                           pD[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16);\n                           CRND_WRITE_BARRIER\n#endif\n                        }\n                     }\n\n                     pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes);\n                  }\n\n                  pBlock += block_delta;\n\n               } // x\n\n               pRow += row_pitch_in_bytes * 2;\n\n            } // y\n\n         } // f\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n         return true;\n      }\n\n      bool unpack_dxt5a(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y)\n      {\n         dst_size_in_bytes;\n\n         uint32 chunk_encoding_bits = 1;\n\n         const uint32 num_alpha_endpoints = m_alpha_endpoints.size();\n         const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num;\n\n         uint32 prev_alpha0_endpoint_index = 0;\n         uint32 prev_alpha0_selector_index = 0;\n\n         const uint32 num_faces = m_pHeader->m_faces;\n\n         const int32 cBytesPerBlock = 8;\n\n         CRND_HUFF_DECODE_BEGIN(m_codec);\n\n         for (uint32 f = 0; f < num_faces; f++)\n         {\n            uint8* CRND_RESTRICT pRow = pDst[f];\n\n            for (uint32 y = 0; y < chunks_y; y++)\n            {\n               int32 start_x = 0;\n               int32 end_x = chunks_x;\n               int32 dir_x = 1;\n               int32 block_delta = cBytesPerBlock*2;\n               uint8* CRND_RESTRICT pBlock = pRow;\n\n               if (y & 1)\n               {\n                  start_x = chunks_x - 1;\n                  end_x = -1;\n                  dir_x = -1;\n                  block_delta = -cBytesPerBlock*2;\n                  pBlock += (chunks_x - 1) * cBytesPerBlock * 2;\n               }\n\n               const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);\n\n               for (int32 x = start_x; x != end_x; x += dir_x)\n               {\n                  uint32 alpha0_endpoints[4];\n\n                  if (chunk_encoding_bits == 1)\n                  {\n                     CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);\n                     chunk_encoding_bits |= 512;\n                  }\n\n                  const uint32 chunk_encoding_index = chunk_encoding_bits & 7;\n                  chunk_encoding_bits >>= 3;\n\n                  const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];\n\n                  const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;\n\n                  const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));\n\n                  uint32* CRND_RESTRICT pD = (uint32*)pBlock;\n\n                  for (uint32 i = 0; i < num_tiles; i++)\n                  {\n                     uint32 delta; CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);\n                     prev_alpha0_endpoint_index += delta;\n                     limit(prev_alpha0_endpoint_index, num_alpha_endpoints);\n                     alpha0_endpoints[i] = m_alpha_endpoints[prev_alpha0_endpoint_index];\n                  }\n\n                  pD = (uint32*)pBlock;\n                  for (uint32 by = 0; by < 2; by++)\n                  {\n                     for (uint32 bx = 0; bx < 2; bx++, pD += 2)\n                     {\n                        uint32 delta; CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta);\n                        prev_alpha0_selector_index += delta;\n                        limit(prev_alpha0_selector_index, num_alpha_selectors);\n\n                        if (!((bx && skip_right_col) || (by && skip_bottom_row)))\n                        {\n                           const uint32 tile_index = pTile_indices[bx + by * 2];\n                           const uint16* pAlpha0_selectors = &m_alpha_selectors[prev_alpha0_selector_index * 3];\n\n#if CRND_BIG_ENDIAN_PLATFORM\n                           pD[0] = (alpha0_endpoints[tile_index] << 16) | pAlpha0_selectors[0];\n                           CRND_WRITE_BARRIER\n                           pD[1] = (pAlpha0_selectors[1] << 16) | pAlpha0_selectors[2];\n                           CRND_WRITE_BARRIER\n#else\n                           pD[0] = alpha0_endpoints[tile_index] | (pAlpha0_selectors[0] << 16);\n                           CRND_WRITE_BARRIER\n                           pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);\n                           CRND_WRITE_BARRIER\n#endif\n                        }\n                     }\n\n                     pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes);\n                  }\n\n                  pBlock += block_delta;\n\n               } // x\n\n               pRow += row_pitch_in_bytes * 2;\n\n            } // y\n\n         } // f\n\n         CRND_HUFF_DECODE_END(m_codec);\n\n         return true;\n      }\n   };\n\n   crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size)\n   {\n      if ((!pData) || (data_size < cCRNHeaderMinSize))\n         return NULL;\n\n      crn_unpacker* p = crnd_new<crn_unpacker>();\n      if (!p)\n         return NULL;\n\n      if (!p->init(pData, data_size))\n      {\n         crnd_delete(p);\n         return NULL;\n      }\n\n      return p;\n   }\n\n   bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size)\n   {\n      if (!pContext)\n         return false;\n\n      crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n      if (!pUnpacker->is_valid())\n         return false;\n\n      if (ppData)\n         *ppData = pUnpacker->get_data();\n\n      if (pData_size)\n         *pData_size = pUnpacker->get_data_size();\n\n      return true;\n   }\n\n   bool crnd_unpack_level(\n      crnd_unpack_context pContext,\n      void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n      uint32 level_index)\n   {\n      if ((!pContext) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels))\n         return false;\n\n      crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n      if (!pUnpacker->is_valid())\n         return false;\n\n      return pUnpacker->unpack_level(pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);\n   }\n\n   bool crnd_unpack_level_segmented(\n      crnd_unpack_context pContext,\n      const void* pSrc, uint32 src_size_in_bytes,\n      void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n      uint32 level_index)\n   {\n      if ((!pContext) || (!pSrc) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels))\n         return false;\n\n      crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n      if (!pUnpacker->is_valid())\n         return false;\n\n      return pUnpacker->unpack_level(pSrc, src_size_in_bytes, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);\n   }\n\n   bool crnd_unpack_end(crnd_unpack_context pContext)\n   {\n      if (!pContext)\n         return false;\n\n      crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n      if (!pUnpacker->is_valid())\n         return false;\n\n      crnd_delete(pUnpacker);\n\n      return true;\n   }\n\n} // namespace crnd\n\n#endif // CRND_HEADER_FILE_ONLY\n\n  //------------------------------------------------------------------------------\n  //\n  // crunch/crnlib uses a modified ZLIB license. Specifically, it's the same as zlib except that \n  // public credits for using the library are *required*.\n  // \n  // Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved.\n  //\n  // This software is provided 'as-is', without any express or implied\n  // warranty.  In no event will the authors be held liable for any damages\n  // arising from the use of this software.\n  // \n  // Permission is granted to anyone to use this software for any purpose,\n  // including commercial applications, and to alter it and redistribute it\n  // freely, subject to the following restrictions:\n  // \n  // 1. The origin of this software must not be misrepresented; you must not\n  // claim that you wrote the original software. \n  // \n  // 2. If you use this software in a product, this acknowledgment in the product \n  // documentation or credits is required:\n  // \n  // \"Crunch Library Copyright (c) 2010-2016 Richard Geldreich, Jr.\"\n  // \n  // 3. Altered source versions must be plainly marked as such, and must not be\n  // misrepresented as being the original software.\n  // \n  // 4. This notice may not be removed or altered from any source distribution.\n  //\n  //------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "Texture2DDecoderNative/crunch/crnlib.h",
    "content": "// File: crnlib.h - Advanced DXTn texture compression library.\n// Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved.\n// See copyright notice and license at the end of this file.\n//\n// This header file contains the public crnlib declarations for DXTn,\n// clustered DXTn, and CRN compression/decompression.\n//\n// Note: This library does NOT need to be linked into your game executable if\n// all you want to do is transcode .CRN files to raw DXTn bits at run-time.\n// The crn_decomp.h header file library contains all the code necessary for\n// decompression.\n//\n// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing\n#ifndef CRNLIB_H\n#define CRNLIB_H\n\n#ifdef _MSC_VER\n#pragma warning (disable: 4127) //  conditional expression is constant\n#endif\n\n#define CRNLIB_VERSION 104\n\n#define CRNLIB_SUPPORT_ATI_COMPRESS 0\n#define CRNLIB_SUPPORT_SQUISH 0\n\ntypedef unsigned char   crn_uint8;\ntypedef unsigned short  crn_uint16;\ntypedef unsigned int    crn_uint32;\ntypedef signed char     crn_int8;\ntypedef signed short    crn_int16;\ntypedef signed int      crn_int32;\ntypedef unsigned int    crn_bool;\n\n// crnlib can compress to these file types.\nenum crn_file_type\n{\n   // .CRN\n   cCRNFileTypeCRN = 0,\n\n   // .DDS using regular DXT or clustered DXT\n   cCRNFileTypeDDS,\n\n   cCRNFileTypeForceDWORD = 0xFFFFFFFF\n};\n\n// Supported compressed pixel formats.\n// Basically all the standard DX9 formats, with some swizzled DXT5 formats\n// (most of them supported by ATI's Compressonator), along with some ATI/X360 GPU specific formats.\nenum crn_format\n{\n   cCRNFmtInvalid = -1,\n\n   cCRNFmtDXT1 = 0,\n\n   cCRNFmtFirstValid = cCRNFmtDXT1,\n\n   // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS.\n   cCRNFmtDXT3,\n\n   cCRNFmtDXT5,\n\n   // Various DXT5 derivatives\n   cCRNFmtDXT5_CCxY,    // Luma-chroma\n   cCRNFmtDXT5_xGxR,    // Swizzled 2-component\n   cCRNFmtDXT5_xGBR,    // Swizzled 3-component\n   cCRNFmtDXT5_AGBR,    // Swizzled 4-component\n\n   // ATI 3DC and X360 DXN\n   cCRNFmtDXN_XY,\n   cCRNFmtDXN_YX,\n\n   // DXT5 alpha blocks only\n   cCRNFmtDXT5A,\n\n   cCRNFmtETC1,\n\n   cCRNFmtTotal,\n\n   cCRNFmtForceDWORD = 0xFFFFFFFF\n};\n\n// Various library/file format limits.\nenum crn_limits\n{\n   // Max. mipmap level resolution on any axis.\n   cCRNMaxLevelResolution     = 4096,\n\n   cCRNMinPaletteSize         = 8,\n   cCRNMaxPaletteSize         = 8192,\n\n   cCRNMaxFaces               = 6,\n   cCRNMaxLevels              = 16,\n\n   cCRNMaxHelperThreads       = 16,\n\n   cCRNMinQualityLevel        = 0,\n   cCRNMaxQualityLevel        = 255\n};\n\n// CRN/DDS compression flags.\n// See the m_flags member in the crn_comp_params struct, below.\nenum crn_comp_flags\n{\n   // Enables perceptual colorspace distance metrics if set.\n   // Important: Be sure to disable this when compressing non-sRGB colorspace images, like normal maps!\n   // Default: Set\n   cCRNCompFlagPerceptual = 1,\n\n   // Enables (up to) 8x8 macroblock usage if set. If disabled, only 4x4 blocks are allowed.\n   // Compression ratio will be lower when disabled, but may cut down on blocky artifacts because the process used to determine\n   // where large macroblocks can be used without artifacts isn't perfect.\n   // Default: Set.\n   cCRNCompFlagHierarchical = 2,\n\n   // cCRNCompFlagQuick disables several output file optimizations - intended for things like quicker previews.\n   // Default: Not set.\n   cCRNCompFlagQuick = 4,\n\n   // DXT1: OK to use DXT1 alpha blocks for better quality or DXT1A transparency.\n   // DXT5: OK to use both DXT5 block types.\n   // Currently only used when writing to .DDS files, as .CRN uses only a subset of the possible DXTn block types.\n   // Default: Set.\n   cCRNCompFlagUseBothBlockTypes = 8,\n\n   // OK to use DXT1A transparent indices to encode black (assumes pixel shader ignores fetched alpha).\n   // Currently only used when writing to .DDS files, .CRN never uses alpha blocks.\n   // Default: Not set.\n   cCRNCompFlagUseTransparentIndicesForBlack = 16,\n\n   // Disables endpoint caching, for more deterministic output.\n   // Currently only used when writing to .DDS files.\n   // Default: Not set.\n   cCRNCompFlagDisableEndpointCaching = 32,\n\n   // If enabled, use the cCRNColorEndpointPaletteSize, etc. params to control the CRN palette sizes. Only useful when writing to .CRN files.\n   // Default: Not set.\n   cCRNCompFlagManualPaletteSizes = 64,\n\n   // If enabled, DXT1A alpha blocks are used to encode single bit transparency.\n   // Default: Not set.\n   cCRNCompFlagDXT1AForTransparency = 128,\n\n   // If enabled, the DXT1 compressor's color distance metric assumes the pixel shader will be converting the fetched RGB results to luma (Y part of YCbCr).\n   // This increases quality when compressing grayscale images, because the compressor can spread the luma error amoung all three channels (i.e. it can generate blocks\n   // with some chroma present if doing so will ultimately lead to lower luma error).\n   // Only enable on grayscale source images.\n   // Default: Not set.\n   cCRNCompFlagGrayscaleSampling = 256,\n\n   // If enabled, debug information will be output during compression.\n   // Default: Not set.\n   cCRNCompFlagDebugging = 0x80000000,\n\n   cCRNCompFlagForceDWORD = 0xFFFFFFFF\n};\n\n// Controls DXTn quality vs. speed control - only used when compressing to .DDS.\nenum crn_dxt_quality\n{\n   cCRNDXTQualitySuperFast,\n   cCRNDXTQualityFast,\n   cCRNDXTQualityNormal,\n   cCRNDXTQualityBetter,\n   cCRNDXTQualityUber,\n\n   cCRNDXTQualityTotal,\n\n   cCRNDXTQualityForceDWORD = 0xFFFFFFFF\n};\n\n// Which DXTn compressor to use when compressing to plain (non-clustered) .DDS.\nenum crn_dxt_compressor_type\n{\n   cCRNDXTCompressorCRN,      // Use crnlib's ETC1 or DXTc block compressor (default, highest quality, comparable or better than ati_compress or squish, and crnlib's ETC1 is a lot fasterw with similiar quality to Erricson's)\n   cCRNDXTCompressorCRNF,     // Use crnlib's \"fast\" DXTc block compressor\n   cCRNDXTCompressorRYG,      // Use RYG's DXTc block compressor (low quality, but very fast)\n\n#if CRNLIB_SUPPORT_ATI_COMPRESS\n   cCRNDXTCompressorATI,\n#endif\n\n#if CRNLIB_SUPPORT_SQUISH\n   cCRNDXTCompressorSquish,\n#endif\n\n   cCRNTotalDXTCompressors,\n\n   cCRNDXTCompressorForceDWORD = 0xFFFFFFFF\n};\n\n// Progress callback function.\n// Processing will stop prematurely (and fail) if the callback returns false.\n// phase_index, total_phases - high level progress\n// subphase_index, total_subphases - progress within current phase\ntypedef crn_bool (*crn_progress_callback_func)(crn_uint32 phase_index, crn_uint32 total_phases, crn_uint32 subphase_index, crn_uint32 total_subphases, void* pUser_data_ptr);\n\n// CRN/DDS compression parameters struct.\nstruct crn_comp_params\n{\n   inline crn_comp_params() { clear(); }\n\n   // Clear struct to default parameters.\n   inline void clear()\n   {\n      m_size_of_obj = sizeof(*this);\n      m_file_type = cCRNFileTypeCRN;\n      m_faces = 1;\n      m_width = 0;\n      m_height = 0;\n      m_levels = 1;\n      m_format = cCRNFmtDXT1;\n      m_flags = cCRNCompFlagPerceptual | cCRNCompFlagHierarchical | cCRNCompFlagUseBothBlockTypes;\n\n      for (crn_uint32 f = 0; f < cCRNMaxFaces; f++)\n         for (crn_uint32 l = 0; l < cCRNMaxLevels; l++)\n            m_pImages[f][l] = NULL;\n\n      m_target_bitrate = 0.0f;\n      m_quality_level = cCRNMaxQualityLevel;\n      m_dxt1a_alpha_threshold = 128;\n      m_dxt_quality = cCRNDXTQualityUber;\n      m_dxt_compressor_type = cCRNDXTCompressorCRN;\n      m_alpha_component = 3;\n\n      m_crn_adaptive_tile_color_psnr_derating = 2.0f;\n      m_crn_adaptive_tile_alpha_psnr_derating = 2.0f;\n      m_crn_color_endpoint_palette_size = 0;\n      m_crn_color_selector_palette_size = 0;\n      m_crn_alpha_endpoint_palette_size = 0;\n      m_crn_alpha_selector_palette_size = 0;\n\n      m_num_helper_threads = 0;\n      m_userdata0 = 0;\n      m_userdata1 = 0;\n      m_pProgress_func = NULL;\n      m_pProgress_func_data = NULL;\n   }\n\n   inline bool operator== (const crn_comp_params& rhs) const\n   {\n#define CRNLIB_COMP(x) do { if ((x) != (rhs.x)) return false; } while(0)\n      CRNLIB_COMP(m_size_of_obj);\n      CRNLIB_COMP(m_file_type);\n      CRNLIB_COMP(m_faces);\n      CRNLIB_COMP(m_width);\n      CRNLIB_COMP(m_height);\n      CRNLIB_COMP(m_levels);\n      CRNLIB_COMP(m_format);\n      CRNLIB_COMP(m_flags);\n      CRNLIB_COMP(m_target_bitrate);\n      CRNLIB_COMP(m_quality_level);\n      CRNLIB_COMP(m_dxt1a_alpha_threshold);\n      CRNLIB_COMP(m_dxt_quality);\n      CRNLIB_COMP(m_dxt_compressor_type);\n      CRNLIB_COMP(m_alpha_component);\n      CRNLIB_COMP(m_crn_adaptive_tile_color_psnr_derating);\n      CRNLIB_COMP(m_crn_adaptive_tile_alpha_psnr_derating);\n      CRNLIB_COMP(m_crn_color_endpoint_palette_size);\n      CRNLIB_COMP(m_crn_color_selector_palette_size);\n      CRNLIB_COMP(m_crn_alpha_endpoint_palette_size);\n      CRNLIB_COMP(m_crn_alpha_selector_palette_size);\n      CRNLIB_COMP(m_num_helper_threads);\n      CRNLIB_COMP(m_userdata0);\n      CRNLIB_COMP(m_userdata1);\n      CRNLIB_COMP(m_pProgress_func);\n      CRNLIB_COMP(m_pProgress_func_data);\n\n      for (crn_uint32 f = 0; f < cCRNMaxFaces; f++)\n         for (crn_uint32 l = 0; l < cCRNMaxLevels; l++)\n            CRNLIB_COMP(m_pImages[f][l]);\n\n#undef CRNLIB_COMP\n      return true;\n   }\n\n   // Returns true if the input parameters are reasonable.\n   inline bool check() const\n   {\n      if ( (m_file_type > cCRNFileTypeDDS) ||\n         (((int)m_quality_level < (int)cCRNMinQualityLevel) || ((int)m_quality_level > (int)cCRNMaxQualityLevel)) ||\n         (m_dxt1a_alpha_threshold > 255) ||\n         ((m_faces != 1) && (m_faces != 6)) ||\n         ((m_width < 1) || (m_width > cCRNMaxLevelResolution)) ||\n         ((m_height < 1) || (m_height > cCRNMaxLevelResolution)) ||\n         ((m_levels < 1) || (m_levels > cCRNMaxLevels)) ||\n         ((m_format < cCRNFmtDXT1) || (m_format >= cCRNFmtTotal)) ||\n         ((m_crn_color_endpoint_palette_size) && ((m_crn_color_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_color_endpoint_palette_size > cCRNMaxPaletteSize))) ||\n         ((m_crn_color_selector_palette_size) && ((m_crn_color_selector_palette_size < cCRNMinPaletteSize) || (m_crn_color_selector_palette_size > cCRNMaxPaletteSize))) ||\n         ((m_crn_alpha_endpoint_palette_size) && ((m_crn_alpha_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_endpoint_palette_size > cCRNMaxPaletteSize))) ||\n         ((m_crn_alpha_selector_palette_size) && ((m_crn_alpha_selector_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_selector_palette_size > cCRNMaxPaletteSize))) ||\n         (m_alpha_component > 3) ||\n         (m_num_helper_threads > cCRNMaxHelperThreads) ||\n         (m_dxt_quality > cCRNDXTQualityUber) ||\n         (m_dxt_compressor_type >= cCRNTotalDXTCompressors) )\n      {\n         return false;\n      }\n      return true;\n   }\n\n   // Helper to set/get flags from m_flags member.\n   inline bool get_flag(crn_comp_flags flag) const { return (m_flags & flag) != 0; }\n   inline void set_flag(crn_comp_flags flag, bool val) { m_flags &= ~flag; if (val) m_flags |= flag; }\n\n   crn_uint32                 m_size_of_obj;\n\n   crn_file_type              m_file_type;               // Output file type: cCRNFileTypeCRN or cCRNFileTypeDDS.\n\n   crn_uint32                 m_faces;                   // 1 (2D map) or 6 (cubemap)\n   crn_uint32                 m_width;                   // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK\n   crn_uint32                 m_height;                  // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK\n   crn_uint32                 m_levels;                  // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK\n\n   crn_format                 m_format;                  // Output pixel format.\n\n   crn_uint32                 m_flags;                   // see crn_comp_flags enum\n\n   // Array of pointers to 32bpp input images.\n   const crn_uint32*          m_pImages[cCRNMaxFaces][cCRNMaxLevels];\n\n   // Target bitrate - if non-zero, the compressor will use an interpolative search to find the\n   // highest quality level that is <= the target bitrate. If it fails to find a bitrate high enough, it'll\n   // try disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and redo the search. This process can be pretty slow.\n   float                      m_target_bitrate;\n\n   // Desired quality level.\n   // Currently, CRN and DDS quality levels are not compatible with eachother from an image quality standpoint.\n   crn_uint32                 m_quality_level;           // [cCRNMinQualityLevel, cCRNMaxQualityLevel]\n\n   // DXTn compression parameters.\n   crn_uint32                 m_dxt1a_alpha_threshold;\n   crn_dxt_quality            m_dxt_quality;\n   crn_dxt_compressor_type    m_dxt_compressor_type;\n\n   // Alpha channel's component. Defaults to 3.\n   crn_uint32                 m_alpha_component;\n\n   // Various low-level CRN specific parameters.\n   float                      m_crn_adaptive_tile_color_psnr_derating;\n   float                      m_crn_adaptive_tile_alpha_psnr_derating;\n\n   crn_uint32                 m_crn_color_endpoint_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n   crn_uint32                 m_crn_color_selector_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n\n   crn_uint32                 m_crn_alpha_endpoint_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n   crn_uint32                 m_crn_alpha_selector_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n\n   // Number of helper threads to create during compression. 0=no threading.\n   crn_uint32                 m_num_helper_threads;\n\n   // CRN userdata0 and userdata1 members, which are written directly to the header of the output file.\n   crn_uint32                 m_userdata0;\n   crn_uint32                 m_userdata1;\n\n   // User provided progress callback.\n   crn_progress_callback_func m_pProgress_func;\n   void*                      m_pProgress_func_data;\n};\n\n// Mipmap generator's mode.\nenum crn_mip_mode\n{\n   cCRNMipModeUseSourceOrGenerateMips,       // Use source texture's mipmaps if it has any, otherwise generate new mipmaps\n   cCRNMipModeUseSourceMips,                 // Use source texture's mipmaps if it has any, otherwise the output has no mipmaps\n   cCRNMipModeGenerateMips,                  // Always generate new mipmaps\n   cCRNMipModeNoMips,                        // Output texture has no mipmaps\n\n   cCRNMipModeTotal,\n\n   cCRNModeForceDWORD = 0xFFFFFFFF\n};\n\nconst char* crn_get_mip_mode_desc(crn_mip_mode m);\nconst char* crn_get_mip_mode_name(crn_mip_mode m);\n\n// Mipmap generator's filter kernel.\nenum crn_mip_filter\n{\n   cCRNMipFilterBox,\n   cCRNMipFilterTent,\n   cCRNMipFilterLanczos4,\n   cCRNMipFilterMitchell,\n   cCRNMipFilterKaiser,                      // Kaiser=default mipmap filter\n\n   cCRNMipFilterTotal,\n\n   cCRNMipFilterForceDWORD = 0xFFFFFFFF\n};\n\nconst char* crn_get_mip_filter_name(crn_mip_filter f);\n\n// Mipmap generator's scale mode.\nenum crn_scale_mode\n{\n   cCRNSMDisabled,\n   cCRNSMAbsolute,\n   cCRNSMRelative,\n   cCRNSMLowerPow2,\n   cCRNSMNearestPow2,\n   cCRNSMNextPow2,\n\n   cCRNSMTotal,\n\n   cCRNSMForceDWORD = 0xFFFFFFFF\n};\n\nconst char* crn_get_scale_mode_desc(crn_scale_mode sm);\n\n// Mipmap generator parameters.\nstruct crn_mipmap_params\n{\n   inline crn_mipmap_params() { clear(); }\n\n   inline void clear()\n   {\n      m_size_of_obj = sizeof(*this);\n      m_mode = cCRNMipModeUseSourceOrGenerateMips;\n      m_filter = cCRNMipFilterKaiser;\n      m_gamma_filtering = true;\n      m_gamma = 2.2f;\n      // Default \"blurriness\" factor of .9 actually sharpens the output a little.\n      m_blurriness = .9f;\n      m_renormalize = false;\n      m_tiled = false;\n      m_max_levels = cCRNMaxLevels;\n      m_min_mip_size = 1;\n\n      m_scale_mode = cCRNSMDisabled;\n      m_scale_x = 1.0f;\n      m_scale_y = 1.0f;\n\n      m_window_left = 0;\n      m_window_top = 0;\n      m_window_right = 0;\n      m_window_bottom = 0;\n\n      m_clamp_scale = false;\n      m_clamp_width = 0;\n      m_clamp_height = 0;\n   }\n\n   inline bool check() const { return true; }\n\n   inline bool operator== (const crn_mipmap_params& rhs) const\n   {\n#define CRNLIB_COMP(x) do { if ((x) != (rhs.x)) return false; } while(0)\n      CRNLIB_COMP(m_size_of_obj);\n      CRNLIB_COMP(m_mode);\n      CRNLIB_COMP(m_filter);\n      CRNLIB_COMP(m_gamma_filtering);\n      CRNLIB_COMP(m_gamma);\n      CRNLIB_COMP(m_blurriness);\n      CRNLIB_COMP(m_renormalize);\n      CRNLIB_COMP(m_tiled);\n      CRNLIB_COMP(m_max_levels);\n      CRNLIB_COMP(m_min_mip_size);\n      CRNLIB_COMP(m_scale_mode);\n      CRNLIB_COMP(m_scale_x);\n      CRNLIB_COMP(m_scale_y);\n      CRNLIB_COMP(m_window_left);\n      CRNLIB_COMP(m_window_top);\n      CRNLIB_COMP(m_window_right);\n      CRNLIB_COMP(m_window_bottom);\n      CRNLIB_COMP(m_clamp_scale);\n      CRNLIB_COMP(m_clamp_width);\n      CRNLIB_COMP(m_clamp_height);\n      return true;\n#undef CRNLIB_COMP\n   }\n   crn_uint32     m_size_of_obj;\n\n   crn_mip_mode   m_mode;\n   crn_mip_filter m_filter;\n\n   crn_bool       m_gamma_filtering;\n   float          m_gamma;\n\n   float          m_blurriness;\n\n   crn_uint32     m_max_levels;\n   crn_uint32     m_min_mip_size;\n\n   crn_bool       m_renormalize;\n   crn_bool       m_tiled;\n\n   crn_scale_mode m_scale_mode;\n   float          m_scale_x;\n   float          m_scale_y;\n\n   crn_uint32     m_window_left;\n   crn_uint32     m_window_top;\n   crn_uint32     m_window_right;\n   crn_uint32     m_window_bottom;\n\n   crn_bool       m_clamp_scale;\n   crn_uint32     m_clamp_width;\n   crn_uint32     m_clamp_height;\n};\n\n// -------- High-level helper function definitions for CDN/DDS compression.\n\n#ifndef CRNLIB_MIN_ALLOC_ALIGNMENT\n#define CRNLIB_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2\n#endif\n\n// Function to set an optional user provided memory allocation/reallocation/msize routines.\n// By default, crnlib just uses malloc(), free(), etc. for all allocations.\ntypedef void*  (*crn_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data);\ntypedef size_t (*crn_msize_func)(void* p, void* pUser_data);\nvoid crn_set_memory_callbacks(crn_realloc_func pRealloc, crn_msize_func pMSize, void* pUser_data);\n\n// Frees memory blocks allocated by crn_compress(), crn_decompress_crn_to_dds(), or crn_decompress_dds_to_images().\nvoid crn_free_block(void *pBlock);\n\n// Compresses a 32-bit/pixel texture to either: a regular DX9 DDS file, a \"clustered\" (or reduced entropy) DX9 DDS file, or a CRN file in memory.\n// Input parameters:\n//  comp_params is the compression parameters struct, defined above.\n//  compressed_size will be set to the size of the returned memory block containing the output file.\n//  The returned block must be freed by calling crn_free_block().\n//  *pActual_quality_level will be set to the actual quality level used to compress the image. May be NULL.\n//  *pActual_bitrate will be set to the output file's effective bitrate, possibly taking into account LZMA compression. May be NULL.\n// Return value:\n//  The compressed file data, or NULL on failure.\n//  compressed_size will be set to the size of the returned memory buffer.\n// Notes:\n//  A \"regular\" DDS file is compressed using normal DXTn compression at the specified DXT quality level.\n//  A \"clustered\" DDS file is compressed using clustered DXTn compression to either the target bitrate or the specified integer quality factor.\n//  The output file is a standard DX9 format DDS file, except the compressor assumes you will be later losslessly compressing the DDS output file using the LZMA algorithm.\n//  A texture is defined as an array of 1 or 6 \"faces\" (6 faces=cubemap), where each \"face\" consists of between [1,cCRNMaxLevels] mipmap levels.\n//  Mipmap levels are simple 32-bit 2D images with a pitch of width*sizeof(uint32), arranged in the usual raster order (top scanline first).\n//  The image pixels may be grayscale (YYYX bytes in memory), grayscale/alpha (YYYA in memory), 24-bit (RGBX in memory), or 32-bit (RGBA) colors (where \"X\"=don't care).\n//  RGB color data is generally assumed to be in the sRGB colorspace. If not, be sure to clear the \"cCRNCompFlagPerceptual\" in the crn_comp_params struct!\nvoid *crn_compress(const crn_comp_params &comp_params, crn_uint32 &compressed_size, crn_uint32 *pActual_quality_level = NULL, float *pActual_bitrate = NULL);\n\n// Like the above function, except this function can also do things like generate mipmaps, and resize or crop the input texture before compression.\n// The actual operations performed are controlled by the crn_mipmap_params struct members.\n// Be sure to set the \"m_gamma_filtering\" member of crn_mipmap_params to false if the input texture is not sRGB.\nvoid *crn_compress(const crn_comp_params &comp_params, const crn_mipmap_params &mip_params, crn_uint32 &compressed_size, crn_uint32 *pActual_quality_level = NULL, float *pActual_bitrate = NULL);\n\n// Transcodes an entire CRN file to DDS using the crn_decomp.h header file library to do most of the heavy lifting.\n// The output DDS file's format is guaranteed to be one of the DXTn formats in the crn_format enum.\n// This is a fast operation, because the CRN format is explicitly designed to be efficiently transcodable to DXTn.\n// For more control over decompression, see the lower-level helper functions in crn_decomp.h, which do not depend at all on crnlib.\nvoid *crn_decompress_crn_to_dds(const void *pCRN_file_data, crn_uint32 &file_size);\n\n// Decompresses an entire DDS file in any supported format to uncompressed 32-bit/pixel image(s).\n// See the crnlib::pixel_format enum in inc/dds_defs.h for a list of the supported DDS formats.\n// You are responsible for freeing each image block, either by calling crn_free_all_images() or manually calling crn_free_block() on each image pointer.\nstruct crn_texture_desc\n{\n   crn_uint32 m_faces;\n   crn_uint32 m_width;\n   crn_uint32 m_height;\n   crn_uint32 m_levels;\n   crn_uint32 m_fmt_fourcc; // Same as crnlib::pixel_format\n};\nbool crn_decompress_dds_to_images(const void *pDDS_file_data, crn_uint32 dds_file_size, crn_uint32 **ppImages, crn_texture_desc &tex_desc);\n\n// Frees all images allocated by crn_decompress_dds_to_images().\nvoid crn_free_all_images(crn_uint32 **ppImages, const crn_texture_desc &desc);\n\n// -------- crn_format related helpers functions.\n\n// Returns the FOURCC format equivalent to the specified crn_format.\ncrn_uint32 crn_get_format_fourcc(crn_format fmt);\n\n// Returns the crn_format's bits per texel.\ncrn_uint32 crn_get_format_bits_per_texel(crn_format fmt);\n\n// Returns the crn_format's number of bytes per block.\ncrn_uint32 crn_get_bytes_per_dxt_block(crn_format fmt);\n\n// Returns the non-swizzled, basic DXTn version of the specified crn_format.\n// This is the format you would supply D3D or OpenGL.\ncrn_format crn_get_fundamental_dxt_format(crn_format fmt);\n\n// -------- String helpers.\n\n// Converts a crn_file_type to a string.\nconst char* crn_get_file_type_ext(crn_file_type file_type);\n\n// Converts a crn_format to a string.\nconst char* crn_get_format_string(crn_format fmt);\n\n// Converts a crn_dxt_quality to a string.\nconst char* crn_get_dxt_quality_string(crn_dxt_quality q);\n\n// -------- Low-level DXTn 4x4 block compressor API\n\n// crnlib's DXTn endpoint optimizer actually supports any number of source pixels (i.e. from 1 to thousands, not just 16),\n// but for simplicity this API only supports 4x4 texel blocks.\ntypedef void *crn_block_compressor_context_t;\n\n// Create a DXTn block compressor.\n// This function only supports the basic/nonswizzled \"fundamental\" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX.\n// Avoid calling this multiple times if you intend on compressing many blocks, because it allocates some memory.\ncrn_block_compressor_context_t crn_create_block_compressor(const crn_comp_params &params);\n\n// Compresses a block of 16 pixels to the destination DXTn block.\n// pDst_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others).\n// pPixels should be an array of 16 crn_uint32's. Each crn_uint32 must be r,g,b,a (r is always first) in memory.\nvoid crn_compress_block(crn_block_compressor_context_t pContext, const crn_uint32 *pPixels, void *pDst_block);\n\n// Frees a DXTn block compressor.\nvoid crn_free_block_compressor(crn_block_compressor_context_t pContext);\n\n// Unpacks a compressed block to pDst_pixels.\n// pSrc_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others).\n// pDst_pixel should be an array of 16 crn_uint32's. Each uint32 will be r,g,b,a (r is always first) in memory.\n// crn_fmt should be one of the \"fundamental\" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX.\n// The various swizzled DXT5 formats (such as cCRNFmtDXT5_xGBR, etc.) will be unpacked as if they where plain DXT5.\n// Returns false if the crn_fmt is invalid.\nbool crn_decompress_block(const void *pSrc_block, crn_uint32 *pDst_pixels, crn_format crn_fmt);\n\n#endif // CRNLIB_H\n\n//------------------------------------------------------------------------------\n//\n// crunch/crnlib uses a modified ZLIB license. Specifically, it's the same as zlib except that \n// public credits for using the library are *required*.\n// \n// Copyright (c) 2010-2016 Richard Geldreich, Jr. All rights reserved.\n//\n// This software is provided 'as-is', without any express or implied\n// warranty.  In no event will the authors be held liable for any damages\n// arising from the use of this software.\n// \n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n// \n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. \n// \n// 2. If you use this software in a product, this acknowledgment in the product \n// documentation or credits is required:\n// \n// \"Crunch Library Copyright (c) 2010-2016 Richard Geldreich, Jr.\"\n// \n// 3. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// \n// 4. This notice may not be removed or altered from any source distribution.\n//\n//------------------------------------------------------------------------------\n"
  },
  {
    "path": "Texture2DDecoderNative/crunch.cpp",
    "content": "#include \"crunch.h\"\n#include <stdint.h>\n#include <algorithm>\n#include \"crunch/crn_decomp.h\"\n\nbool crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size) {\n\tcrnd::crn_texture_info tex_info;\n\tif (!crnd::crnd_get_texture_info(data, data_size, &tex_info))\n\t{\n\t\treturn false;\n\t}\n\n\tcrnd::crnd_unpack_context pContext = crnd::crnd_unpack_begin(data, data_size);\n\tif (!pContext)\n\t{\n\t\treturn false;\n\t}\n\n\tconst crn_uint32 width = std::max(1U, tex_info.m_width >> level_index);\n\tconst crn_uint32 height = std::max(1U, tex_info.m_height >> level_index);\n\tconst crn_uint32 blocks_x = std::max(1U, (width + 3) >> 2);\n\tconst crn_uint32 blocks_y = std::max(1U, (height + 3) >> 2);\n\tconst crn_uint32 row_pitch = blocks_x * crnd::crnd_get_bytes_per_dxt_block(tex_info.m_format);\n\tconst crn_uint32 total_face_size = row_pitch * blocks_y;\n\t*ret = new uint8_t[total_face_size];\n\t*ret_size = total_face_size;\n\tif (!crnd::crnd_unpack_level(pContext, ret, total_face_size, row_pitch, level_index))\n\t{\n\t\tcrnd::crnd_unpack_end(pContext);\n\t\treturn false;\n\t}\n\tcrnd::crnd_unpack_end(pContext);\n\treturn true;\n}"
  },
  {
    "path": "Texture2DDecoderNative/crunch.h",
    "content": "#pragma once\n\n#include <stdint.h>\n\nbool crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size);"
  },
  {
    "path": "Texture2DDecoderNative/dllexport.h",
    "content": "#pragma once\n\n#if defined(_MSC_VER)\n#if _MSC_VER < 1910 // MSVC 2017-\n#error MSVC 2017 or later is required.\n#endif\n#endif\n\n#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__)\n#ifdef _T2D_DLL\n#ifdef __GNUC__\n#define _T2D_EXPORT __attribute__ ((dllexport))\n#else\n#define _T2D_EXPORT __declspec(dllexport)\n#endif\n#else\n#ifdef __GNUC__\n#define _T2D_EXPORT __attribute__ ((dllimport))\n#else\n#define _T2D_EXPORT __declspec(dllimport)\n#endif\n#endif\n#define _T2D_LOCAL\n#else\n#if __GNUC__ >= 4\n#define _T2D_EXPORT __attribute__ ((visibility (\"default\")))\n#define _T2D_LOCAL  __attribute__ ((visibility (\"hidden\")))\n#else\n#define _T2D_EXPORT\n#define _T2D_LOCAL\n#endif\n#endif\n\n#ifdef __cplusplus\n#ifndef _EXTERN_C_STMT\n#define _EXTERN_C_STMT extern \"C\"\n#endif\n#else\n#ifndef _EXTERN_C_STMT\n#define _EXTERN_C_STMT\n#endif\n#endif\n\n#ifndef _T2D_CALL\n#if defined(WIN32) || defined(_WIN32)\n#define _T2D_CALL __stdcall\n#else\n#define _T2D_CALL /* __cdecl */\n#endif\n#endif\n\n#if defined(_MSC_VER)\n#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT ret_type _T2D_CALL\n#else\n#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT _T2D_CALL ret_type\n#endif\n"
  },
  {
    "path": "Texture2DDecoderNative/dllmain.cpp",
    "content": "#include \"dllexport.h\"\n#include \"bool32_t.h\"\n\n#include \"bcn.h\"\n#include \"pvrtc.h\"\n#include \"etc.h\"\n#include \"atc.h\"\n#include \"astc.h\"\n#include \"crunch.h\"\n#include \"unitycrunch.h\"\n\nT2D_API(bool32_t) DecodeDXT1(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_bc1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeDXT5(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_bc3(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodePVRTC(const void* data, int32_t width, int32_t height, void* image, bool32_t is2bpp)\n{\n\treturn decode_pvrtc(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image), is2bpp ? 1 : 0);\n}\n\nT2D_API(bool32_t) DecodeETC1(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_etc1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeETC2(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_etc2(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeETC2A1(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_etc2a1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeETC2A8(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_etc2a8(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeEACR(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_eacr(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeEACRSigned(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_eacr_signed(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeEACRG(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_eacrg(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeEACRGSigned(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_eacrg_signed(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeBC4(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_bc4(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeBC5(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_bc5(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeBC6(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_bc6(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeBC7(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_bc7(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeATCRGB4(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_atc_rgb4(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeATCRGBA8(const void* data, int32_t width, int32_t height, void* image)\n{\n\treturn decode_atc_rgba8(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));\n}\n\nT2D_API(bool32_t) DecodeASTC(const void* data, int32_t width, int32_t height, int32_t blockWidth, int32_t blockHeight, void* image)\n{\n\treturn decode_astc(static_cast<const uint8_t*>(data), width, height, blockWidth, blockHeight, static_cast<uint32_t*>(image));\n}\n\nT2D_API(void) DisposeBuffer(void** ppBuffer)\n{\n\tif (ppBuffer == nullptr)\n\t{\n\t\treturn;\n\t}\n\n\tauto ppTypedBuffer = reinterpret_cast<uint8_t**>(ppBuffer);\n\n\tdelete[](*ppTypedBuffer);\n\n\t*ppBuffer = nullptr;\n}\n\nT2D_API(void) UnpackCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize)\n{\n\tvoid* result;\n\tuint32_t resultSize;\n\n\tif (ppResult != nullptr)\n\t{\n\t\t*ppResult = nullptr;\n\t}\n\n\tif (pResultSize != nullptr)\n\t{\n\t\t*pResultSize = 0;\n\t}\n\n\tif (!crunch_unpack_level(static_cast<const uint8_t*>(data), dataSize, 0, &result, &resultSize)) {\n\t\treturn;\n\t}\n\n\tif (ppResult != nullptr)\n\t{\n\t\t*ppResult = result;\n\t}\n\n\tif (pResultSize != nullptr)\n\t{\n\t\t*pResultSize = resultSize;\n\t}\n}\n\nT2D_API(void) UnpackUnityCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize)\n{\n\tvoid* result;\n\tuint32_t resultSize;\n\n\tif (ppResult != nullptr)\n\t{\n\t\t*ppResult = nullptr;\n\t}\n\n\tif (pResultSize != nullptr)\n\t{\n\t\t*pResultSize = 0;\n\t}\n\n\tif (!unity_crunch_unpack_level(static_cast<const uint8_t*>(data), dataSize, 0, &result, &resultSize)) {\n\t\treturn;\n\t}\n\n\tif (ppResult != nullptr)\n\t{\n\t\t*ppResult = result;\n\t}\n\n\tif (pResultSize != nullptr)\n\t{\n\t\t*pResultSize = resultSize;\n\t}\n}\n"
  },
  {
    "path": "Texture2DDecoderNative/endianness.h",
    "content": "/*\n *\n * License Information\n *\n * endianness.h is derived from https://gist.github.com/jtbr/7a43e6281e6cca353b33ee501421860c\n * The file is licensed under the MIT License shown below.\n *\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n * documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n */\n\n#ifndef _ENDIANNESS_H\n#define _ENDIANNESS_H\n\n#include <stdlib.h>\n#include <stdint.h>\n\n/* Detect platform endianness at compile time */\n\n// If boost were available on all platforms, could use this instead to detect endianness\n// #include <boost/predef/endian.h>\n\n// When available, these headers can improve platform endianness detection\n#ifdef __has_include  // C++17, supported as extension to C++11 in clang, GCC 5+, vs2015\n#if __has_include(<endian.h>)\n#include <endian.h>  // gnu libc normally provides, linux\n#elif __has_include(<machine/endian.h>)\n#include <machine/endian.h>  //open bsd, macos\n#elif __has_include(<sys/param.h>)\n#include <sys/param.h>  // mingw, some bsd (not open/macos)\n#elif __has_include(<sys/isadefs.h>)\n#include <sys/isadefs.h>  // solaris\n#endif\n#endif\n\n#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)\n#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) ||                                            \\\n  (defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) || (defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN) ||  \\\n  (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || (defined(__sun) && defined(__SVR4) && defined(_BIG_ENDIAN)) || \\\n  defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) ||    \\\n  defined(__MIBSEB__) || defined(_M_PPC)\n#define __BIG_ENDIAN__\n#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || /* gcc */                           \\\n  (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) /* linux header */ ||                                  \\\n  (defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN) ||                                                        \\\n  (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) /* mingw header */ ||                                        \\\n  (defined(__sun) && defined(__SVR4) && defined(_LITTLE_ENDIAN)) || /* solaris */                                   \\\n  defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) ||  \\\n  defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64) || /* msvc for intel processors */ \\\n  defined(_M_ARM) /* msvc code on arm executes in little endian mode */\n#define __LITTLE_ENDIAN__\n#endif\n#endif\n\n#ifdef bswap16\n#undef bswap16\n#endif\n#ifdef bswap32\n#undef bswap32\n#endif\n#ifdef bswap64\n#undef bswap64\n#endif\n\n/* Define byte-swap functions, using fast processor-native built-ins where possible */\n// needs to be first because msvc doesn't short-circuit after failing defined(__has_builtin)\n#if defined(_MSC_VER)\n#define bswap16(x) _byteswap_ushort((x))\n#define bswap32(x) _byteswap_ulong((x))\n#define bswap64(x) _byteswap_uint64((x))\n#elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)\n#define bswap16(x) __builtin_bswap16((x))\n#define bswap32(x) __builtin_bswap32((x))\n#define bswap64(x) __builtin_bswap64((x))\n#elif defined(__has_builtin) && __has_builtin(__builtin_bswap64)\n/* for clang; gcc 5 fails on this and && shortcircuit fails; must be after GCC check */\n#define bswap16(x) __builtin_bswap16((x))\n#define bswap32(x) __builtin_bswap32((x))\n#define bswap64(x) __builtin_bswap64((x))\n#else\n/* even in this case, compilers often optimize by using native instructions */\nstatic inline uint16_t bswap16(uint16_t x) {\n    return (((x >> 8) & 0xffu) | ((x & 0xffu) << 8));\n}\nstatic inline uint32_t bswap32(uint32_t x) {\n    return (((x & 0xff000000u) >> 24) | ((x & 0x00ff0000u) >> 8) | ((x & 0x0000ff00u) << 8) |\n            ((x & 0x000000ffu) << 24));\n}\nstatic inline uint64_t bswap64(uint64_t x) {\n    return (((x & 0xff00000000000000ull) >> 56) | ((x & 0x00ff000000000000ull) >> 40) |\n            ((x & 0x0000ff0000000000ull) >> 24) | ((x & 0x000000ff00000000ull) >> 8) |\n            ((x & 0x00000000ff000000ull) << 8) | ((x & 0x0000000000ff0000ull) << 24) |\n            ((x & 0x000000000000ff00ull) << 40) | ((x & 0x00000000000000ffull) << 56));\n}\n#endif\n\n\n/* Defines network - host byte swaps as needed depending upon platform endianness */\n// note that network order is big endian)\n\n#if defined(__LITTLE_ENDIAN__)\n#define ntoh16(x) bswap16((x))\n#define hton16(x) bswap16((x))\n#define ntoh32(x) bswap32((x))\n#define hton32(x) bswap32((x))\n#define ntoh64(x) bswap64((x))\n#define hton64(x) bswap64((x))\n#define lton16(x) (x)\n#define lton32(x) (x)\n#define lton64(x) (x)\n#define ltonf(x) (x)\n#define ltond(x) (x)\n#define bton16(x) bswap16((x))\n#define bton32(x) bswap32((x))\n#define bton64(x) bswap64((x))\n#define btonf(x) htonf((x))\n#define btond(x) htond((x))\n#elif defined(__BIG_ENDIAN__)\n#define ntoh16(x) (x)\n#define hton16(x) (x)\n#define ntoh32(x) (x)\n#define hton32(x) (x)\n#define ntoh64(x) (x)\n#define hton64(x) (x)\n#define bton16(x) (x)\n#define bton32(x) (x)\n#define bton64(x) (x)\n#define btonf(x) (x)\n#define btond(x) (x)\n#define lton16(x) bswap16((x))\n#define lton32(x) bswap32((x))\n#define lton64(x) bswap64((x))\n#define ltonf(x) htonf((x))\n#define ltond(x) htond((x))\n#else\n#warning \"UNKNOWN Platform / endianness; network / host byte swaps not defined.\"\n#endif\n\n\n//! Convert 32-bit float from host to network byte order\nstatic inline float htonf(float f) {\n#ifdef __cplusplus\n    static_assert(sizeof(float) == sizeof(uint32_t), \"Unexpected float format\");\n    uint32_t val = hton32(*(reinterpret_cast<const uint32_t *>(&f)));\n    return *(reinterpret_cast<float *>(&val));\n#else\n    uint32_t val = hton32(*(const uint32_t *)(&f));\n    return *((float *)(&val));\n#endif\n}\n#define ntohf(x) htonf((x))\n\n//! Convert 64-bit double from host to network byte order\nstatic inline double htond(double f) {\n#ifdef __cplusplus\n    static_assert(sizeof(double) == sizeof(uint64_t), \"Unexpected double format\");\n    uint64_t val = hton64(*(reinterpret_cast<const uint64_t *>(&f)));\n    return *(reinterpret_cast<double *>(&val));\n#else\n    uint64_t val = hton64(*(const uint64_t *)(&f));\n    return *((double *)(&val));\n#endif\n}\n#define ntohd(x) htond((x))\n\n#endif  //_ENDIANNESS_H\n"
  },
  {
    "path": "Texture2DDecoderNative/etc.cpp",
    "content": "#include \"etc.h\"\n#include <stdint.h>\n#include <string.h>\n#include \"color.h\"\n\nconst uint_fast8_t WriteOrderTable[16] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15};\nconst uint_fast8_t WriteOrderTableRev[16] = {15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0};\nconst uint_fast8_t Etc1ModifierTable[8][2] = {{2, 8},   {5, 17},  {9, 29},   {13, 42},\n                                              {18, 60}, {24, 80}, {33, 106}, {47, 183}};\nconst uint_fast8_t Etc2aModifierTable[2][8][2] = {\n  {{0, 8}, {0, 17}, {0, 29}, {0, 42}, {0, 60}, {0, 80}, {0, 106}, {0, 183}},\n  {{2, 8}, {5, 17}, {9, 29}, {13, 42}, {18, 60}, {24, 80}, {33, 106}, {47, 183}}};\nconst uint_fast8_t Etc1SubblockTable[2][16] = {{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},\n                                               {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}};\nconst uint_fast8_t Etc2DistanceTable[8] = {3, 6, 11, 16, 23, 32, 41, 64};\nconst int_fast8_t Etc2AlphaModTable[16][8] = {\n  {-3, -6, -9, -15, 2, 5, 8, 14}, {-3, -7, -10, -13, 2, 6, 9, 12}, {-2, -5, -8, -13, 1, 4, 7, 12},\n  {-2, -4, -6, -13, 1, 3, 5, 12}, {-3, -6, -8, -12, 2, 5, 7, 11},  {-3, -7, -9, -11, 2, 6, 8, 10},\n  {-4, -7, -8, -11, 3, 6, 7, 10}, {-3, -5, -8, -11, 2, 4, 7, 10},  {-2, -6, -8, -10, 1, 5, 7, 9},\n  {-2, -5, -8, -10, 1, 4, 7, 9},  {-2, -4, -8, -10, 1, 3, 7, 9},   {-2, -5, -7, -10, 1, 4, 6, 9},\n  {-3, -4, -7, -10, 2, 3, 6, 9},  {-1, -2, -3, -10, 0, 1, 2, 9},   {-4, -6, -8, -9, 3, 5, 7, 8},\n  {-3, -5, -7, -9, 2, 4, 6, 8}};\n\nstatic inline uint_fast8_t clamp(const int n) {\n    return n < 0 ? 0 : n > 255 ? 255 : n;\n}\n\nstatic inline uint32_t applicate_color(uint_fast8_t c[3], int_fast16_t m) {\n    return color(clamp(c[0] + m), clamp(c[1] + m), clamp(c[2] + m), 255);\n}\n\nstatic inline uint32_t applicate_color_alpha(uint_fast8_t c[3], int_fast16_t m, int transparent) {\n    return color(clamp(c[0] + m), clamp(c[1] + m), clamp(c[2] + m), transparent ? 0 : 255);\n}\n\nstatic inline uint32_t applicate_color_raw(uint_fast8_t c[3]) {\n    return color(c[0], c[1], c[2], 255);\n}\n\nstatic void decode_etc1_block(const uint8_t *data, uint32_t *outbuf) {\n    const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7};  // Table codewords\n    const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1];\n    uint_fast8_t c[2][3];\n    if (data[3] & 2) {\n        // diff bit == 1\n        c[0][0] = data[0] & 0xf8;\n        c[0][1] = data[1] & 0xf8;\n        c[0][2] = data[2] & 0xf8;\n        c[1][0] = c[0][0] + (data[0] << 3 & 0x18) - (data[0] << 3 & 0x20);\n        c[1][1] = c[0][1] + (data[1] << 3 & 0x18) - (data[1] << 3 & 0x20);\n        c[1][2] = c[0][2] + (data[2] << 3 & 0x18) - (data[2] << 3 & 0x20);\n        c[0][0] |= c[0][0] >> 5;\n        c[0][1] |= c[0][1] >> 5;\n        c[0][2] |= c[0][2] >> 5;\n        c[1][0] |= c[1][0] >> 5;\n        c[1][1] |= c[1][1] >> 5;\n        c[1][2] |= c[1][2] >> 5;\n    } else {\n        // diff bit == 0\n        c[0][0] = (data[0] & 0xf0) | data[0] >> 4;\n        c[1][0] = (data[0] & 0x0f) | data[0] << 4;\n        c[0][1] = (data[1] & 0xf0) | data[1] >> 4;\n        c[1][1] = (data[1] & 0x0f) | data[1] << 4;\n        c[0][2] = (data[2] & 0xf0) | data[2] >> 4;\n        c[1][2] = (data[2] & 0x0f) | data[2] << 4;\n    }\n\n    uint_fast16_t j = data[6] << 8 | data[7];  // less significant pixel index bits\n    uint_fast16_t k = data[4] << 8 | data[5];  // more significant pixel index bits\n    for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) {\n        uint_fast8_t s = table[i];\n        uint_fast8_t m = Etc1ModifierTable[code[s]][j & 1];\n        outbuf[WriteOrderTable[i]] = applicate_color(c[s], k & 1 ? -m : m);\n    }\n}\n\nstatic void decode_etc2_block(const uint8_t *data, uint32_t *outbuf) {\n    uint_fast16_t j = data[6] << 8 | data[7];  // 15 -> 0\n    uint_fast32_t k = data[4] << 8 | data[5];  // 31 -> 16\n    uint_fast8_t c[3][3] = {};\n\n    if (data[3] & 2) {\n        // diff bit == 1\n        uint_fast8_t r = data[0] & 0xf8;\n        int_fast16_t dr = (data[0] << 3 & 0x18) - (data[0] << 3 & 0x20);\n        uint_fast8_t g = data[1] & 0xf8;\n        int_fast16_t dg = (data[1] << 3 & 0x18) - (data[1] << 3 & 0x20);\n        uint_fast8_t b = data[2] & 0xf8;\n        int_fast16_t db = (data[2] << 3 & 0x18) - (data[2] << 3 & 0x20);\n        if (r + dr < 0 || r + dr > 255) {\n            // T\n            c[0][0] = (data[0] << 3 & 0xc0) | (data[0] << 4 & 0x30) | (data[0] >> 1 & 0xc) | (data[0] & 3);\n            c[0][1] = (data[1] & 0xf0) | data[1] >> 4;\n            c[0][2] = (data[1] & 0x0f) | data[1] << 4;\n            c[1][0] = (data[2] & 0xf0) | data[2] >> 4;\n            c[1][1] = (data[2] & 0x0f) | data[2] << 4;\n            c[1][2] = (data[3] & 0xf0) | data[3] >> 4;\n            const uint_fast8_t d = Etc2DistanceTable[(data[3] >> 1 & 6) | (data[3] & 1)];\n            uint_fast32_t color_set[4] = {applicate_color_raw(c[0]), applicate_color(c[1], d),\n                                          applicate_color_raw(c[1]), applicate_color(c[1], -d)};\n            k <<= 1;\n            for (int i = 0; i < 16; i++, j >>= 1, k >>= 1)\n                outbuf[WriteOrderTable[i]] = color_set[(k & 2) | (j & 1)];\n        } else if (g + dg < 0 || g + dg > 255) {\n            // H\n            c[0][0] = (data[0] << 1 & 0xf0) | (data[0] >> 3 & 0xf);\n            c[0][1] = (data[0] << 5 & 0xe0) | (data[1] & 0x10);\n            c[0][1] |= c[0][1] >> 4;\n            c[0][2] = (data[1] & 8) | (data[1] << 1 & 6) | data[2] >> 7;\n            c[0][2] |= c[0][2] << 4;\n            c[1][0] = (data[2] << 1 & 0xf0) | (data[2] >> 3 & 0xf);\n            c[1][1] = (data[2] << 5 & 0xe0) | (data[3] >> 3 & 0x10);\n            c[1][1] |= c[1][1] >> 4;\n            c[1][2] = (data[3] << 1 & 0xf0) | (data[3] >> 3 & 0xf);\n            uint_fast8_t d = (data[3] & 4) | (data[3] << 1 & 2);\n            if (c[0][0] > c[1][0] ||\n                (c[0][0] == c[1][0] && (c[0][1] > c[1][1] || (c[0][1] == c[1][1] && c[0][2] >= c[1][2]))))\n                ++d;\n            d = Etc2DistanceTable[d];\n            uint_fast32_t color_set[4] = {applicate_color(c[0], d), applicate_color(c[0], -d), applicate_color(c[1], d),\n                                          applicate_color(c[1], -d)};\n            k <<= 1;\n            for (int i = 0; i < 16; i++, j >>= 1, k >>= 1)\n                outbuf[WriteOrderTable[i]] = color_set[(k & 2) | (j & 1)];\n        } else if (b + db < 0 || b + db > 255) {\n            // planar\n            c[0][0] = (data[0] << 1 & 0xfc) | (data[0] >> 5 & 3);\n            c[0][1] = (data[0] << 7 & 0x80) | (data[1] & 0x7e) | (data[0] & 1);\n            c[0][2] = (data[1] << 7 & 0x80) | (data[2] << 2 & 0x60) | (data[2] << 3 & 0x18) | (data[3] >> 5 & 4);\n            c[0][2] |= c[0][2] >> 6;\n            c[1][0] = (data[3] << 1 & 0xf8) | (data[3] << 2 & 4) | (data[3] >> 5 & 3);\n            c[1][1] = (data[4] & 0xfe) | data[4] >> 7;\n            c[1][2] = (data[4] << 7 & 0x80) | (data[5] >> 1 & 0x7c);\n            c[1][2] |= c[1][2] >> 6;\n            c[2][0] = (data[5] << 5 & 0xe0) | (data[6] >> 3 & 0x1c) | (data[5] >> 1 & 3);\n            c[2][1] = (data[6] << 3 & 0xf8) | (data[7] >> 5 & 0x6) | (data[6] >> 4 & 1);\n            c[2][2] = data[7] << 2 | (data[7] >> 4 & 3);\n            for (int y = 0, i = 0; y < 4; y++) {\n                for (int x = 0; x < 4; x++, i++) {\n                    uint8_t r = clamp((x * (c[1][0] - c[0][0]) + y * (c[2][0] - c[0][0]) + 4 * c[0][0] + 2) >> 2);\n                    uint8_t g = clamp((x * (c[1][1] - c[0][1]) + y * (c[2][1] - c[0][1]) + 4 * c[0][1] + 2) >> 2);\n                    uint8_t b = clamp((x * (c[1][2] - c[0][2]) + y * (c[2][2] - c[0][2]) + 4 * c[0][2] + 2) >> 2);\n                    outbuf[i] = color(r, g, b, 255);\n                }\n            }\n        } else {\n            // differential\n            const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7};\n            const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1];\n            c[0][0] = r | r >> 5;\n            c[0][1] = g | g >> 5;\n            c[0][2] = b | b >> 5;\n            c[1][0] = r + dr;\n            c[1][1] = g + dg;\n            c[1][2] = b + db;\n            c[1][0] |= c[1][0] >> 5;\n            c[1][1] |= c[1][1] >> 5;\n            c[1][2] |= c[1][2] >> 5;\n            for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) {\n                uint_fast8_t s = table[i];\n                uint_fast8_t m = Etc1ModifierTable[code[s]][j & 1];\n                outbuf[WriteOrderTable[i]] = applicate_color(c[s], k & 1 ? -m : m);\n            }\n        }\n    } else {\n        // individual (diff bit == 0)\n        const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7};\n        const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1];\n        c[0][0] = (data[0] & 0xf0) | data[0] >> 4;\n        c[1][0] = (data[0] & 0x0f) | data[0] << 4;\n        c[0][1] = (data[1] & 0xf0) | data[1] >> 4;\n        c[1][1] = (data[1] & 0x0f) | data[1] << 4;\n        c[0][2] = (data[2] & 0xf0) | data[2] >> 4;\n        c[1][2] = (data[2] & 0x0f) | data[2] << 4;\n        for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) {\n            uint_fast8_t s = table[i];\n            uint_fast8_t m = Etc1ModifierTable[code[s]][j & 1];\n            outbuf[WriteOrderTable[i]] = applicate_color(c[s], k & 1 ? -m : m);\n        }\n    }\n}\n\nstatic void decode_etc2a1_block(const uint8_t *data, uint32_t *outbuf) {\n    uint_fast16_t j = data[6] << 8 | data[7];  // 15 -> 0\n    uint_fast32_t k = data[4] << 8 | data[5];  // 31 -> 16\n    uint_fast8_t c[3][3] = {};\n\n    int obaq = data[3] >> 1 & 1;\n\n    // diff bit == 1\n    uint_fast8_t r = data[0] & 0xf8;\n    int_fast16_t dr = (data[0] << 3 & 0x18) - (data[0] << 3 & 0x20);\n    uint_fast8_t g = data[1] & 0xf8;\n    int_fast16_t dg = (data[1] << 3 & 0x18) - (data[1] << 3 & 0x20);\n    uint_fast8_t b = data[2] & 0xf8;\n    int_fast16_t db = (data[2] << 3 & 0x18) - (data[2] << 3 & 0x20);\n    if (r + dr < 0 || r + dr > 255) {\n        // T\n        c[0][0] = (data[0] << 3 & 0xc0) | (data[0] << 4 & 0x30) | (data[0] >> 1 & 0xc) | (data[0] & 3);\n        c[0][1] = (data[1] & 0xf0) | data[1] >> 4;\n        c[0][2] = (data[1] & 0x0f) | data[1] << 4;\n        c[1][0] = (data[2] & 0xf0) | data[2] >> 4;\n        c[1][1] = (data[2] & 0x0f) | data[2] << 4;\n        c[1][2] = (data[3] & 0xf0) | data[3] >> 4;\n        const uint_fast8_t d = Etc2DistanceTable[(data[3] >> 1 & 6) | (data[3] & 1)];\n        uint_fast32_t color_set[4] = {applicate_color_raw(c[0]), applicate_color(c[1], d), applicate_color_raw(c[1]),\n                                      applicate_color(c[1], -d)};\n        k <<= 1;\n        for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) {\n            int index = (k & 2) | (j & 1);\n            outbuf[WriteOrderTable[i]] = color_set[index];\n            if (!obaq && index == 2)\n                outbuf[WriteOrderTable[i]] &= TRANSPARENT_MASK;\n        }\n    } else if (g + dg < 0 || g + dg > 255) {\n        // H\n        c[0][0] = (data[0] << 1 & 0xf0) | (data[0] >> 3 & 0xf);\n        c[0][1] = (data[0] << 5 & 0xe0) | (data[1] & 0x10);\n        c[0][1] |= c[0][1] >> 4;\n        c[0][2] = (data[1] & 8) | (data[1] << 1 & 6) | data[2] >> 7;\n        c[0][2] |= c[0][2] << 4;\n        c[1][0] = (data[2] << 1 & 0xf0) | (data[2] >> 3 & 0xf);\n        c[1][1] = (data[2] << 5 & 0xe0) | (data[3] >> 3 & 0x10);\n        c[1][1] |= c[1][1] >> 4;\n        c[1][2] = (data[3] << 1 & 0xf0) | (data[3] >> 3 & 0xf);\n        uint_fast8_t d = (data[3] & 4) | (data[3] << 1 & 2);\n        if (c[0][0] > c[1][0] ||\n            (c[0][0] == c[1][0] && (c[0][1] > c[1][1] || (c[0][1] == c[1][1] && c[0][2] >= c[1][2]))))\n            ++d;\n        d = Etc2DistanceTable[d];\n        uint_fast32_t color_set[4] = {applicate_color(c[0], d), applicate_color(c[0], -d), applicate_color(c[1], d),\n                                      applicate_color(c[1], -d)};\n        k <<= 1;\n        for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) {\n            int index = (k & 2) | (j & 1);\n            outbuf[WriteOrderTable[i]] = color_set[index];\n            if (!obaq && index == 2)\n                outbuf[WriteOrderTable[i]] &= TRANSPARENT_MASK;\n        }\n    } else if (b + db < 0 || b + db > 255) {\n        // planar\n        c[0][0] = (data[0] << 1 & 0xfc) | (data[0] >> 5 & 3);\n        c[0][1] = (data[0] << 7 & 0x80) | (data[1] & 0x7e) | (data[0] & 1);\n        c[0][2] = (data[1] << 7 & 0x80) | (data[2] << 2 & 0x60) | (data[2] << 3 & 0x18) | (data[3] >> 5 & 4);\n        c[0][2] |= c[0][2] >> 6;\n        c[1][0] = (data[3] << 1 & 0xf8) | (data[3] << 2 & 4) | (data[3] >> 5 & 3);\n        c[1][1] = (data[4] & 0xfe) | data[4] >> 7;\n        c[1][2] = (data[4] << 7 & 0x80) | (data[5] >> 1 & 0x7c);\n        c[1][2] |= c[1][2] >> 6;\n        c[2][0] = (data[5] << 5 & 0xe0) | (data[6] >> 3 & 0x1c) | (data[5] >> 1 & 3);\n        c[2][1] = (data[6] << 3 & 0xf8) | (data[7] >> 5 & 0x6) | (data[6] >> 4 & 1);\n        c[2][2] = data[7] << 2 | (data[7] >> 4 & 3);\n        for (int y = 0, i = 0; y < 4; y++) {\n            for (int x = 0; x < 4; x++, i++) {\n                uint8_t r = clamp((x * (c[1][0] - c[0][0]) + y * (c[2][0] - c[0][0]) + 4 * c[0][0] + 2) >> 2);\n                uint8_t g = clamp((x * (c[1][1] - c[0][1]) + y * (c[2][1] - c[0][1]) + 4 * c[0][1] + 2) >> 2);\n                uint8_t b = clamp((x * (c[1][2] - c[0][2]) + y * (c[2][2] - c[0][2]) + 4 * c[0][2] + 2) >> 2);\n                outbuf[i] = color(r, g, b, 255);\n            }\n        }\n    } else {\n        // differential\n        const uint_fast8_t code[2] = {data[3] >> 5, data[3] >> 2 & 7};\n        const uint_fast8_t *table = Etc1SubblockTable[data[3] & 1];\n        c[0][0] = r | r >> 5;\n        c[0][1] = g | g >> 5;\n        c[0][2] = b | b >> 5;\n        c[1][0] = r + dr;\n        c[1][1] = g + dg;\n        c[1][2] = b + db;\n        c[1][0] |= c[1][0] >> 5;\n        c[1][1] |= c[1][1] >> 5;\n        c[1][2] |= c[1][2] >> 5;\n        for (int i = 0; i < 16; i++, j >>= 1, k >>= 1) {\n            uint_fast8_t s = table[i];\n            uint_fast8_t m = Etc2aModifierTable[obaq][code[s]][j & 1];\n            outbuf[WriteOrderTable[i]] = applicate_color_alpha(c[s], k & 1 ? -m : m, !obaq && (k & 1) && !(j & 1));\n        }\n    }\n}\n\nstatic void decode_etc2a8_block(const uint8_t *data, uint32_t *outbuf) {\n    if (data[1] & 0xf0) {\n        // multiplier != 0\n        const uint_fast8_t multiplier = data[1] >> 4;\n        const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf];\n        uint_fast64_t l = bton64(*(uint64_t*)data);\n        for (int i = 0; i < 16; i++, l >>= 3)\n            ((uint8_t *)(outbuf + WriteOrderTableRev[i]))[3] = clamp(data[0] + multiplier * table[l & 7]);\n    } else {\n        // multiplier == 0 (always same as base codeword)\n        for (int i = 0; i < 16; i++, outbuf++)\n            ((uint8_t *)outbuf)[3] = data[0];\n    }\n}\n\nstatic void decode_eac_block(const uint8_t *data, int color, uint32_t *outbuf) {\n    uint_fast8_t multiplier = data[1] >> 1 & 0x78;\n    if (multiplier == 0)\n        multiplier = 1;\n    const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf];\n    uint_fast64_t l = bton64(*(uint64_t*)data);\n    for (int i = 0; i < 16; i++, l >>= 3) {\n        int_fast16_t val = data[0] * 8 + multiplier * table[l & 7] + 4;\n        ((uint8_t *)(outbuf + WriteOrderTableRev[i]))[color] = val < 0 ? 0 : val >= 2048 ? 0xff : val >> 3;\n    }\n}\n\nstatic void decode_eac_signed_block(const uint8_t *data, int color, uint32_t *outbuf) {\n    int8_t base = (int8_t)data[0];\n    uint_fast8_t multiplier = data[1] >> 1 & 0x78;\n    if (multiplier == 0)\n        multiplier = 1;\n    const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf];\n    uint_fast64_t l = bton64(*(uint64_t*)data);\n    for (int i = 0; i < 16; i++, l >>= 3) {\n        int_fast16_t val = base * 8 + multiplier * table[l & 7] + 1023;\n        ((uint8_t *)(outbuf + WriteOrderTableRev[i]))[color] = val < 0 ? 0 : val >= 2048 ? 0xff : val >> 3;\n    }\n}\n\nint decode_etc1(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 8) {\n            decode_etc1_block(data, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n\nint decode_etc2(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 8) {\n            decode_etc2_block(data, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n\nint decode_etc2a1(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 8) {\n            decode_etc2a1_block(data, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n\nint decode_etc2a8(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 16) {\n            decode_etc2_block(data + 8, buffer);\n            decode_etc2a8_block(data, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n\nint decode_eacr(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    uint32_t base_buffer[16];\n    for (int i = 0; i < 16; i++)\n        base_buffer[i] = color(0, 0, 0, 255);\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 8) {\n            memcpy(buffer, base_buffer, sizeof(buffer));\n            decode_eac_block(data, 2, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n\nint decode_eacr_signed(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    uint32_t base_buffer[16];\n    for (int i = 0; i < 16; i++)\n        base_buffer[i] = color(0, 0, 0, 255);\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 8) {\n            memcpy(buffer, base_buffer, sizeof(buffer));\n            decode_eac_signed_block(data, 2, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n\nint decode_eacrg(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    uint32_t base_buffer[16];\n    for (int i = 0; i < 16; i++)\n        base_buffer[i] = color(0, 0, 0, 255);\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 16) {\n            memcpy(buffer, base_buffer, sizeof(buffer));\n            decode_eac_block(data, 2, buffer);\n            decode_eac_block(data + 8, 1, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n\nint decode_eacrg_signed(const uint8_t *data, const long w, const long h, uint32_t *image) {\n    long num_blocks_x = (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    uint32_t buffer[16];\n    uint32_t base_buffer[16];\n    for (int i = 0; i < 16; i++)\n        base_buffer[i] = color(0, 0, 0, 255);\n    for (long by = 0; by < num_blocks_y; by++) {\n        for (long bx = 0; bx < num_blocks_x; bx++, data += 16) {\n            memcpy(buffer, base_buffer, sizeof(buffer));\n            decode_eac_signed_block(data, 2, buffer);\n            decode_eac_signed_block(data + 8, 1, buffer);\n            copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);\n        }\n    }\n    return 1;\n}\n"
  },
  {
    "path": "Texture2DDecoderNative/etc.h",
    "content": "#ifndef ETC_H\n#define ETC_H\n\n#include <stdint.h>\n\nint decode_etc1(const uint8_t *, const long, const long, uint32_t *);\nint decode_etc2(const uint8_t *, const long, const long, uint32_t *);\nint decode_etc2a1(const uint8_t *, const long, const long, uint32_t *);\nint decode_etc2a8(const uint8_t *, const long, const long, uint32_t *);\nint decode_eacr(const uint8_t *, const long, const long, uint32_t *);\nint decode_eacr_signed(const uint8_t *, const long, const long, uint32_t *);\nint decode_eacrg(const uint8_t *, const long, const long, uint32_t *);\nint decode_eacrg_signed(const uint8_t *, const long, const long, uint32_t *);\n\n#endif /* end of include guard: ETC_H */\n"
  },
  {
    "path": "Texture2DDecoderNative/fp16/bitcasts.h",
    "content": "#pragma once\n#ifndef FP16_BITCASTS_H\n#define FP16_BITCASTS_H\n\n#if defined(__cplusplus) && (__cplusplus >= 201103L)\n\t#include <cstdint>\n#elif !defined(__OPENCL_VERSION__)\n\t#include <stdint.h>\n#endif\n\n\nstatic inline float fp32_from_bits(uint32_t w) {\n#if defined(__OPENCL_VERSION__)\n\treturn as_float(w);\n#elif defined(__CUDA_ARCH__)\n\treturn __uint_as_float((unsigned int) w);\n#elif defined(__INTEL_COMPILER)\n\treturn _castu32_f32(w);\n#else\n\tunion {\n\t\tuint32_t as_bits;\n\t\tfloat as_value;\n\t} fp32 = { w };\n\treturn fp32.as_value;\n#endif\n}\n\nstatic inline uint32_t fp32_to_bits(float f) {\n#if defined(__OPENCL_VERSION__)\n\treturn as_uint(f);\n#elif defined(__CUDA_ARCH__)\n\treturn (uint32_t) __float_as_uint(f);\n#elif defined(__INTEL_COMPILER)\n\treturn _castf32_u32(f);\n#else\n\tunion {\n\t\tfloat as_value;\n\t\tuint32_t as_bits;\n\t} fp32 = { f };\n\treturn fp32.as_bits;\n#endif\n}\n\nstatic inline double fp64_from_bits(uint64_t w) {\n#if defined(__OPENCL_VERSION__)\n\treturn as_double(w);\n#elif defined(__CUDA_ARCH__)\n\treturn __longlong_as_double((long long) w);\n#elif defined(__INTEL_COMPILER)\n\treturn _castu64_f64(w);\n#else\n\tunion {\n\t\tuint64_t as_bits;\n\t\tdouble as_value;\n\t} fp64 = { w };\n\treturn fp64.as_value;\n#endif\n}\n\nstatic inline uint64_t fp64_to_bits(double f) {\n#if defined(__OPENCL_VERSION__)\n\treturn as_ulong(f);\n#elif defined(__CUDA_ARCH__)\n\treturn (uint64_t) __double_as_longlong(f);\n#elif defined(__INTEL_COMPILER)\n\treturn _castf64_u64(f);\n#else\n\tunion {\n\t\tdouble as_value;\n\t\tuint64_t as_bits;\n\t} fp64 = { f };\n\treturn fp64.as_bits;\n#endif\n}\n\n#endif /* FP16_BITCASTS_H */\n"
  },
  {
    "path": "Texture2DDecoderNative/fp16/fp16.h",
    "content": "#pragma once\n#ifndef FP16_FP16_H\n#define FP16_FP16_H\n\n#if defined(__cplusplus) && (__cplusplus >= 201103L)\n\t#include <cstdint>\n\t#include <cmath>\n#elif !defined(__OPENCL_VERSION__)\n\t#include <stdint.h>\n\t#include <math.h>\n#endif\n\n#ifdef _MSC_VER\n\t#include <intrin.h>\n#endif\n\n#include \"fp16/bitcasts.h\"\n\n\n/*\n * Convert a 16-bit floating-point number in IEEE half-precision format, in bit representation, to\n * a 32-bit floating-point number in IEEE single-precision format, in bit representation.\n *\n * @note The implementation doesn't use any floating-point operations.\n */\nstatic inline uint32_t fp16_ieee_to_fp32_bits(uint16_t h) {\n\t/*\n\t * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word:\n\t *      +---+-----+------------+-------------------+\n\t *      | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000|\n\t *      +---+-----+------------+-------------------+\n\t * Bits  31  26-30    16-25            0-15\n\t *\n\t * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits.\n\t */\n\tconst uint32_t w = (uint32_t) h << 16;\n\t/*\n\t * Extract the sign of the input number into the high bit of the 32-bit word:\n\t *\n\t *      +---+----------------------------------+\n\t *      | S |0000000 00000000 00000000 00000000|\n\t *      +---+----------------------------------+\n\t * Bits  31                 0-31\n\t */\n\tconst uint32_t sign = w & UINT32_C(0x80000000);\n\t/*\n\t * Extract mantissa and biased exponent of the input number into the bits 0-30 of the 32-bit word:\n\t *\n\t *      +---+-----+------------+-------------------+\n\t *      | 0 |EEEEE|MM MMMM MMMM|0000 0000 0000 0000|\n\t *      +---+-----+------------+-------------------+\n\t * Bits  30  27-31     17-26            0-16\n\t */\n\tconst uint32_t nonsign = w & UINT32_C(0x7FFFFFFF);\n\t/*\n\t * Renorm shift is the number of bits to shift mantissa left to make the half-precision number normalized.\n\t * If the initial number is normalized, some of its high 6 bits (sign == 0 and 5-bit exponent) equals one.\n\t * In this case renorm_shift == 0. If the number is denormalize, renorm_shift > 0. Note that if we shift\n\t * denormalized nonsign by renorm_shift, the unit bit of mantissa will shift into exponent, turning the\n\t * biased exponent into 1, and making mantissa normalized (i.e. without leading 1).\n\t */\n#ifdef _MSC_VER\n\tunsigned long nonsign_bsr;\n\t_BitScanReverse(&nonsign_bsr, (unsigned long) nonsign);\n\tuint32_t renorm_shift = (uint32_t) nonsign_bsr ^ 31;\n#else\n\tuint32_t renorm_shift = __builtin_clz(nonsign);\n#endif\n\trenorm_shift = renorm_shift > 5 ? renorm_shift - 5 : 0;\n\t/*\n\t * Iff half-precision number has exponent of 15, the addition overflows it into bit 31,\n\t * and the subsequent shift turns the high 9 bits into 1. Thus\n\t *   inf_nan_mask ==\n\t *                   0x7F800000 if the half-precision number had exponent of 15 (i.e. was NaN or infinity)\n\t *                   0x00000000 otherwise\n\t */\n\tconst int32_t inf_nan_mask = ((int32_t) (nonsign + 0x04000000) >> 8) & INT32_C(0x7F800000);\n\t/*\n\t * Iff nonsign is 0, it overflows into 0xFFFFFFFF, turning bit 31 into 1. Otherwise, bit 31 remains 0.\n\t * The signed shift right by 31 broadcasts bit 31 into all bits of the zero_mask. Thus\n\t *   zero_mask ==\n\t *                0xFFFFFFFF if the half-precision number was zero (+0.0h or -0.0h)\n\t *                0x00000000 otherwise\n\t */\n\tconst int32_t zero_mask = (int32_t) (nonsign - 1) >> 31;\n\t/*\n\t * 1. Shift nonsign left by renorm_shift to normalize it (if the input was denormal)\n\t * 2. Shift nonsign right by 3 so the exponent (5 bits originally) becomes an 8-bit field and 10-bit mantissa\n\t *    shifts into the 10 high bits of the 23-bit mantissa of IEEE single-precision number.\n\t * 3. Add 0x70 to the exponent (starting at bit 23) to compensate the different in exponent bias\n\t *    (0x7F for single-precision number less 0xF for half-precision number).\n\t * 4. Subtract renorm_shift from the exponent (starting at bit 23) to account for renormalization. As renorm_shift\n\t *    is less than 0x70, this can be combined with step 3.\n\t * 5. Binary OR with inf_nan_mask to turn the exponent into 0xFF if the input was NaN or infinity.\n\t * 6. Binary ANDNOT with zero_mask to turn the mantissa and exponent into zero if the input was zero.\n\t * 7. Combine with the sign of the input number.\n\t */\n\treturn sign | ((((nonsign << renorm_shift >> 3) + ((0x70 - renorm_shift) << 23)) | inf_nan_mask) & ~zero_mask);\n}\n\n/*\n * Convert a 16-bit floating-point number in IEEE half-precision format, in bit representation, to\n * a 32-bit floating-point number in IEEE single-precision format.\n *\n * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals)\n * floating-point operations and bitcasts between integer and floating-point variables.\n */\nstatic inline float fp16_ieee_to_fp32_value(uint16_t h) {\n\t/*\n\t * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word:\n\t *      +---+-----+------------+-------------------+\n\t *      | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000|\n\t *      +---+-----+------------+-------------------+\n\t * Bits  31  26-30    16-25            0-15\n\t *\n\t * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits.\n\t */\n\tconst uint32_t w = (uint32_t) h << 16;\n\t/*\n\t * Extract the sign of the input number into the high bit of the 32-bit word:\n\t *\n\t *      +---+----------------------------------+\n\t *      | S |0000000 00000000 00000000 00000000|\n\t *      +---+----------------------------------+\n\t * Bits  31                 0-31\n\t */\n\tconst uint32_t sign = w & UINT32_C(0x80000000);\n\t/*\n\t * Extract mantissa and biased exponent of the input number into the high bits of the 32-bit word:\n\t *\n\t *      +-----+------------+---------------------+\n\t *      |EEEEE|MM MMMM MMMM|0 0000 0000 0000 0000|\n\t *      +-----+------------+---------------------+\n\t * Bits  27-31    17-26            0-16\n\t */\n\tconst uint32_t two_w = w + w;\n\n\t/*\n\t * Shift mantissa and exponent into bits 23-28 and bits 13-22 so they become mantissa and exponent\n\t * of a single-precision floating-point number:\n\t *\n\t *       S|Exponent |          Mantissa\n\t *      +-+---+-----+------------+----------------+\n\t *      |0|000|EEEEE|MM MMMM MMMM|0 0000 0000 0000|\n\t *      +-+---+-----+------------+----------------+\n\t * Bits   | 23-31   |           0-22\n\t *\n\t * Next, there are some adjustments to the exponent:\n\t * - The exponent needs to be corrected by the difference in exponent bias between single-precision and half-precision\n\t *   formats (0x7F - 0xF = 0x70)\n\t * - Inf and NaN values in the inputs should become Inf and NaN values after conversion to the single-precision number.\n\t *   Therefore, if the biased exponent of the half-precision input was 0x1F (max possible value), the biased exponent\n\t *   of the single-precision output must be 0xFF (max possible value). We do this correction in two steps:\n\t *   - First, we adjust the exponent by (0xFF - 0x1F) = 0xE0 (see exp_offset below) rather than by 0x70 suggested\n\t *     by the difference in the exponent bias (see above).\n\t *   - Then we multiply the single-precision result of exponent adjustment by 2**(-112) to reverse the effect of\n\t *     exponent adjustment by 0xE0 less the necessary exponent adjustment by 0x70 due to difference in exponent bias.\n\t *     The floating-point multiplication hardware would ensure than Inf and NaN would retain their value on at least\n\t *     partially IEEE754-compliant implementations.\n\t *\n\t * Note that the above operations do not handle denormal inputs (where biased exponent == 0). However, they also do not\n\t * operate on denormal inputs, and do not produce denormal results.\n\t */\n\tconst uint32_t exp_offset = UINT32_C(0xE0) << 23;\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__)\n\tconst float exp_scale = 0x1.0p-112f;\n#else\n\tconst float exp_scale = fp32_from_bits(UINT32_C(0x7800000));\n#endif\n\tconst float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale;\n\n\t/*\n\t * Convert denormalized half-precision inputs into single-precision results (always normalized).\n\t * Zero inputs are also handled here.\n\t *\n\t * In a denormalized number the biased exponent is zero, and mantissa has on-zero bits.\n\t * First, we shift mantissa into bits 0-9 of the 32-bit word.\n\t *\n\t *                  zeros           |  mantissa\n\t *      +---------------------------+------------+\n\t *      |0000 0000 0000 0000 0000 00|MM MMMM MMMM|\n\t *      +---------------------------+------------+\n\t * Bits             10-31                0-9\n\t *\n\t * Now, remember that denormalized half-precision numbers are represented as:\n\t *    FP16 = mantissa * 2**(-24).\n\t * The trick is to construct a normalized single-precision number with the same mantissa and thehalf-precision input\n\t * and with an exponent which would scale the corresponding mantissa bits to 2**(-24).\n\t * A normalized single-precision floating-point number is represented as:\n\t *    FP32 = (1 + mantissa * 2**(-23)) * 2**(exponent - 127)\n\t * Therefore, when the biased exponent is 126, a unit change in the mantissa of the input denormalized half-precision\n\t * number causes a change of the constructud single-precision number by 2**(-24), i.e. the same ammount.\n\t *\n\t * The last step is to adjust the bias of the constructed single-precision number. When the input half-precision number\n\t * is zero, the constructed single-precision number has the value of\n\t *    FP32 = 1 * 2**(126 - 127) = 2**(-1) = 0.5\n\t * Therefore, we need to subtract 0.5 from the constructed single-precision number to get the numerical equivalent of\n\t * the input half-precision number.\n\t */\n\tconst uint32_t magic_mask = UINT32_C(126) << 23;\n\tconst float magic_bias = 0.5f;\n\tconst float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias;\n\n\t/*\n\t * - Choose either results of conversion of input as a normalized number, or as a denormalized number, depending on the\n\t *   input exponent. The variable two_w contains input exponent in bits 27-31, therefore if its smaller than 2**27, the\n\t *   input is either a denormal number, or zero.\n\t * - Combine the result of conversion of exponent and mantissa with the sign of the input number.\n\t */\n\tconst uint32_t denormalized_cutoff = UINT32_C(1) << 27;\n\tconst uint32_t result = sign |\n\t\t(two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value));\n\treturn fp32_from_bits(result);\n}\n\n/*\n * Convert a 32-bit floating-point number in IEEE single-precision format to a 16-bit floating-point number in\n * IEEE half-precision format, in bit representation.\n *\n * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals)\n * floating-point operations and bitcasts between integer and floating-point variables.\n */\nstatic inline uint16_t fp16_ieee_from_fp32_value(float f) {\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__)\n\tconst float scale_to_inf = 0x1.0p+112f;\n\tconst float scale_to_zero = 0x1.0p-110f;\n#else\n\tconst float scale_to_inf = fp32_from_bits(UINT32_C(0x77800000));\n\tconst float scale_to_zero = fp32_from_bits(UINT32_C(0x08800000));\n#endif\n\tfloat base = (fabsf(f) * scale_to_inf) * scale_to_zero;\n\n\tconst uint32_t w = fp32_to_bits(f);\n\tconst uint32_t shl1_w = w + w;\n\tconst uint32_t sign = w & UINT32_C(0x80000000);\n\tuint32_t bias = shl1_w & UINT32_C(0xFF000000);\n\tif (bias < UINT32_C(0x71000000)) {\n\t\tbias = UINT32_C(0x71000000);\n\t}\n\n\tbase = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)) + base;\n\tconst uint32_t bits = fp32_to_bits(base);\n\tconst uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00);\n\tconst uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF);\n\tconst uint32_t nonsign = exp_bits + mantissa_bits;\n\treturn (sign >> 16) | (shl1_w > UINT32_C(0xFF000000) ? UINT16_C(0x7E00) : nonsign);\n}\n\n/*\n * Convert a 16-bit floating-point number in ARM alternative half-precision format, in bit representation, to\n * a 32-bit floating-point number in IEEE single-precision format, in bit representation.\n *\n * @note The implementation doesn't use any floating-point operations.\n */\nstatic inline uint32_t fp16_alt_to_fp32_bits(uint16_t h) {\n\t/*\n\t * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word:\n\t *      +---+-----+------------+-------------------+\n\t *      | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000|\n\t *      +---+-----+------------+-------------------+\n\t * Bits  31  26-30    16-25            0-15\n\t *\n\t * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits.\n\t */\n\tconst uint32_t w = (uint32_t) h << 16;\n\t/*\n\t * Extract the sign of the input number into the high bit of the 32-bit word:\n\t *\n\t *      +---+----------------------------------+\n\t *      | S |0000000 00000000 00000000 00000000|\n\t *      +---+----------------------------------+\n\t * Bits  31                 0-31\n\t */\n\tconst uint32_t sign = w & UINT32_C(0x80000000);\n\t/*\n\t * Extract mantissa and biased exponent of the input number into the bits 0-30 of the 32-bit word:\n\t *\n\t *      +---+-----+------------+-------------------+\n\t *      | 0 |EEEEE|MM MMMM MMMM|0000 0000 0000 0000|\n\t *      +---+-----+------------+-------------------+\n\t * Bits  30  27-31     17-26            0-16\n\t */\n\tconst uint32_t nonsign = w & UINT32_C(0x7FFFFFFF);\n\t/*\n\t * Renorm shift is the number of bits to shift mantissa left to make the half-precision number normalized.\n\t * If the initial number is normalized, some of its high 6 bits (sign == 0 and 5-bit exponent) equals one.\n\t * In this case renorm_shift == 0. If the number is denormalize, renorm_shift > 0. Note that if we shift\n\t * denormalized nonsign by renorm_shift, the unit bit of mantissa will shift into exponent, turning the\n\t * biased exponent into 1, and making mantissa normalized (i.e. without leading 1).\n\t */\n#ifdef _MSC_VER\n\tunsigned long nonsign_bsr;\n\t_BitScanReverse(&nonsign_bsr, (unsigned long) nonsign);\n\tuint32_t renorm_shift = (uint32_t) nonsign_bsr ^ 31;\n#else\n\tuint32_t renorm_shift = __builtin_clz(nonsign);\n#endif\n\trenorm_shift = renorm_shift > 5 ? renorm_shift - 5 : 0;\n\t/*\n\t * Iff nonsign is 0, it overflows into 0xFFFFFFFF, turning bit 31 into 1. Otherwise, bit 31 remains 0.\n\t * The signed shift right by 31 broadcasts bit 31 into all bits of the zero_mask. Thus\n\t *   zero_mask ==\n\t *                0xFFFFFFFF if the half-precision number was zero (+0.0h or -0.0h)\n\t *                0x00000000 otherwise\n\t */\n\tconst int32_t zero_mask = (int32_t) (nonsign - 1) >> 31;\n\t/*\n\t * 1. Shift nonsign left by renorm_shift to normalize it (if the input was denormal)\n\t * 2. Shift nonsign right by 3 so the exponent (5 bits originally) becomes an 8-bit field and 10-bit mantissa\n\t *    shifts into the 10 high bits of the 23-bit mantissa of IEEE single-precision number.\n\t * 3. Add 0x70 to the exponent (starting at bit 23) to compensate the different in exponent bias\n\t *    (0x7F for single-precision number less 0xF for half-precision number).\n\t * 4. Subtract renorm_shift from the exponent (starting at bit 23) to account for renormalization. As renorm_shift\n\t *    is less than 0x70, this can be combined with step 3.\n\t * 5. Binary ANDNOT with zero_mask to turn the mantissa and exponent into zero if the input was zero.\n\t * 6. Combine with the sign of the input number.\n\t */\n\treturn sign | (((nonsign << renorm_shift >> 3) + ((0x70 - renorm_shift) << 23)) & ~zero_mask);\n}\n\n/*\n * Convert a 16-bit floating-point number in ARM alternative half-precision format, in bit representation, to\n * a 32-bit floating-point number in IEEE single-precision format.\n *\n * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals)\n * floating-point operations and bitcasts between integer and floating-point variables.\n */\nstatic inline float fp16_alt_to_fp32_value(uint16_t h) {\n\t/*\n\t * Extend the half-precision floating-point number to 32 bits and shift to the upper part of the 32-bit word:\n\t *      +---+-----+------------+-------------------+\n\t *      | S |EEEEE|MM MMMM MMMM|0000 0000 0000 0000|\n\t *      +---+-----+------------+-------------------+\n\t * Bits  31  26-30    16-25            0-15\n\t *\n\t * S - sign bit, E - bits of the biased exponent, M - bits of the mantissa, 0 - zero bits.\n\t */\n\tconst uint32_t w = (uint32_t) h << 16;\n\t/*\n\t * Extract the sign of the input number into the high bit of the 32-bit word:\n\t *\n\t *      +---+----------------------------------+\n\t *      | S |0000000 00000000 00000000 00000000|\n\t *      +---+----------------------------------+\n\t * Bits  31                 0-31\n\t */\n\tconst uint32_t sign = w & UINT32_C(0x80000000);\n\t/*\n\t * Extract mantissa and biased exponent of the input number into the high bits of the 32-bit word:\n\t *\n\t *      +-----+------------+---------------------+\n\t *      |EEEEE|MM MMMM MMMM|0 0000 0000 0000 0000|\n\t *      +-----+------------+---------------------+\n\t * Bits  27-31    17-26            0-16\n\t */\n\tconst uint32_t two_w = w + w;\n\n\t/*\n\t * Shift mantissa and exponent into bits 23-28 and bits 13-22 so they become mantissa and exponent\n\t * of a single-precision floating-point number:\n\t *\n\t *       S|Exponent |          Mantissa\n\t *      +-+---+-----+------------+----------------+\n\t *      |0|000|EEEEE|MM MMMM MMMM|0 0000 0000 0000|\n\t *      +-+---+-----+------------+----------------+\n\t * Bits   | 23-31   |           0-22\n\t *\n\t * Next, the exponent is adjusted for the difference in exponent bias between single-precision and half-precision\n\t * formats (0x7F - 0xF = 0x70). This operation never overflows or generates non-finite values, as the largest\n\t * half-precision exponent is 0x1F and after the adjustment is can not exceed 0x8F < 0xFE (largest single-precision\n\t * exponent for non-finite values).\n\t *\n\t * Note that this operation does not handle denormal inputs (where biased exponent == 0). However, they also do not\n\t * operate on denormal inputs, and do not produce denormal results.\n\t */\n\tconst float exp_offset = UINT32_C(0x70) << 23;\n\tconst float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset);\n\n\t/*\n\t * Convert denormalized half-precision inputs into single-precision results (always normalized).\n\t * Zero inputs are also handled here.\n\t *\n\t * In a denormalized number the biased exponent is zero, and mantissa has on-zero bits.\n\t * First, we shift mantissa into bits 0-9 of the 32-bit word.\n\t *\n\t *                  zeros           |  mantissa\n\t *      +---------------------------+------------+\n\t *      |0000 0000 0000 0000 0000 00|MM MMMM MMMM|\n\t *      +---------------------------+------------+\n\t * Bits             10-31                0-9\n\t *\n\t * Now, remember that denormalized half-precision numbers are represented as:\n\t *    FP16 = mantissa * 2**(-24).\n\t * The trick is to construct a normalized single-precision number with the same mantissa and thehalf-precision input\n\t * and with an exponent which would scale the corresponding mantissa bits to 2**(-24).\n\t * A normalized single-precision floating-point number is represented as:\n\t *    FP32 = (1 + mantissa * 2**(-23)) * 2**(exponent - 127)\n\t * Therefore, when the biased exponent is 126, a unit change in the mantissa of the input denormalized half-precision\n\t * number causes a change of the constructud single-precision number by 2**(-24), i.e. the same ammount.\n\t *\n\t * The last step is to adjust the bias of the constructed single-precision number. When the input half-precision number\n\t * is zero, the constructed single-precision number has the value of\n\t *    FP32 = 1 * 2**(126 - 127) = 2**(-1) = 0.5\n\t * Therefore, we need to subtract 0.5 from the constructed single-precision number to get the numerical equivalent of\n\t * the input half-precision number.\n\t */\n\tconst uint32_t magic_mask = UINT32_C(126) << 23;\n\tconst float magic_bias = 0.5f;\n\tconst float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias;\n\n\t/*\n\t * - Choose either results of conversion of input as a normalized number, or as a denormalized number, depending on the\n\t *   input exponent. The variable two_w contains input exponent in bits 27-31, therefore if its smaller than 2**27, the\n\t *   input is either a denormal number, or zero.\n\t * - Combine the result of conversion of exponent and mantissa with the sign of the input number.\n\t */\n\tconst uint32_t denormalized_cutoff = UINT32_C(1) << 27;\n\tconst uint32_t result = sign |\n\t\t(two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value));\n\treturn fp32_from_bits(result);\n}\n\n/*\n * Convert a 32-bit floating-point number in IEEE single-precision format to a 16-bit floating-point number in\n * ARM alternative half-precision format, in bit representation.\n *\n * @note The implementation relies on IEEE-like (no assumption about rounding mode and no operations on denormals)\n * floating-point operations and bitcasts between integer and floating-point variables.\n */\nstatic inline uint16_t fp16_alt_from_fp32_value(float f) {\n\tconst uint32_t w = fp32_to_bits(f);\n\tconst uint32_t sign = w & UINT32_C(0x80000000);\n\tconst uint32_t shl1_w = w + w;\n\n\tconst uint32_t shl1_max_fp16_fp32 = UINT32_C(0x8FFFC000);\n\tconst uint32_t shl1_base = shl1_w > shl1_max_fp16_fp32 ? shl1_max_fp16_fp32 : shl1_w;\n\tuint32_t shl1_bias = shl1_base & UINT32_C(0xFF000000);\n\tconst uint32_t exp_difference = 23 - 10;\n\tconst uint32_t shl1_bias_min = (127 - 1 - exp_difference) << 24;\n\tif (shl1_bias < shl1_bias_min) {\n\t\tshl1_bias = shl1_bias_min;\n\t}\n\n\tconst float bias = fp32_from_bits((shl1_bias >> 1) + ((exp_difference + 2) << 23));\n\tconst float base = fp32_from_bits((shl1_base >> 1) + (2 << 23)) + bias;\n\n\tconst uint32_t exp_f = fp32_to_bits(base) >> 13;\n\treturn (sign >> 16) | ((exp_f & UINT32_C(0x00007C00)) + (fp32_to_bits(base) & UINT32_C(0x00000FFF)));\n}\n\n#endif /* FP16_FP16_H */\n"
  },
  {
    "path": "Texture2DDecoderNative/fp16.h",
    "content": "#pragma once\n#ifndef FP16_H\n#define FP16_H\n\n#include \"fp16/fp16.h\"\n\n#endif /* FP16_H */\n\n/*\n *\n * License Information\n *\n * FP16 library is derived from https://github.com/Maratyszcza/FP16.\n * The library is licensed under the MIT License shown below.\n *\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2017 Facebook Inc.\n * Copyright (c) 2017 Georgia Institute of Technology\n * Copyright 2019 Google LLC\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n * documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n */\n"
  },
  {
    "path": "Texture2DDecoderNative/pvrtc.cpp",
    "content": "#include \"pvrtc.h\"\n#include <stdint.h>\n#include <string.h>\n#include \"color.h\"\n#include \"endianness.h\"\n\nstatic const int PVRTC1_STANDARD_WEIGHT[] = {0, 3, 5, 8};\nstatic const int PVRTC1_PUNCHTHROUGH_WEIGHT[] = {0, 4, 4, 8};\n\nstatic inline long morton_index(const long x, const long y, const long min_dim) {\n    long offset = 0, shift = 0;\n    for (long mask = 1; mask < min_dim; mask <<= 1, shift++)\n        offset |= (((y & mask) | ((x & mask) << 1))) << shift;\n    offset |= ((x | y) >> shift) << (shift * 2);\n    return offset;\n}\n\nstatic void get_texel_colors(const uint8_t *data, PVRTCTexelInfo *info) {\n    uint16_t ca = lton16(*(uint16_t *)(data + 4));\n    uint16_t cb = lton16(*(uint16_t *)(data + 6));\n    if (ca & 0x8000) {\n        info->a.r = ca >> 10 & 0x1f;\n        info->a.g = ca >> 5 & 0x1f;\n        info->a.b = (ca & 0x1e) | (ca >> 4 & 1);\n        info->a.a = 0xf;\n    } else {\n        info->a.r = (ca >> 7 & 0x1e) | (ca >> 11 & 1);\n        info->a.g = (ca >> 3 & 0x1e) | (ca >> 7 & 1);\n        info->a.b = (ca << 1 & 0x1c) | (ca >> 2 & 3);\n        info->a.a = ca >> 11 & 0xe;\n    }\n    if (cb & 0x8000) {\n        info->b.r = cb >> 10 & 0x1f;\n        info->b.g = cb >> 5 & 0x1f;\n        info->b.b = cb & 0x1f;\n        info->b.a = 0xf;\n    } else {\n        info->b.r = (cb >> 7 & 0x1e) | (cb >> 11 & 1);\n        info->b.g = (cb >> 3 & 0x1e) | (cb >> 7 & 1);\n        info->b.b = (cb << 1 & 0x1e) | (cb >> 3 & 1);\n        info->b.a = cb >> 11 & 0xe;\n    }\n}\n\nstatic void get_texel_weights_4bpp(const uint8_t *data, PVRTCTexelInfo *info) {\n    info->punch_through_flag = 0;\n\n    int mod_mode = data[4] & 1;\n    uint32_t mod_bits = lton32(*(uint32_t *)data);\n\n    if (mod_mode) {\n        for (int i = 0; i < 16; i++, mod_bits >>= 2) {\n            info->weight[i] = PVRTC1_PUNCHTHROUGH_WEIGHT[mod_bits & 3];\n            if ((mod_bits & 3) == 2)\n                info->punch_through_flag |= 1 << i;\n        }\n    } else {\n        for (int i = 0; i < 16; i++, mod_bits >>= 2)\n            info->weight[i] = PVRTC1_STANDARD_WEIGHT[mod_bits & 3];\n    }\n}\n\nstatic void get_texel_weights_2bpp(const uint8_t *data, PVRTCTexelInfo *info) {\n    info->punch_through_flag = 0;\n\n    int mod_mode = data[4] & 1;\n    uint32_t mod_bits = lton32(*(uint32_t *)data);\n\n    if (mod_mode) {\n        int fillflag = data[0] & 1 ? (data[2] & 0x10 ? -1 : -2) : -3;\n        for (int y = 0, i = 1; y < 4; ++y & 1 ? --i : ++i)\n            for (int x = 0; x < 4; x++, i += 2)\n                info->weight[i] = fillflag;\n        for (int y = 0, i = 0; y < 4; ++y & 1 ? ++i : --i)\n            for (int x = 0; x < 4; x++, i += 2, mod_bits >>= 2)\n                info->weight[i] = PVRTC1_STANDARD_WEIGHT[mod_bits & 3];\n        info->weight[0] = (info->weight[0] + 3) & 8;\n        if (data[0] & 1)\n            info->weight[20] = (info->weight[20] + 3) & 8;\n    } else {\n        for (int i = 0; i < 32; i++, mod_bits >>= 1)\n            info->weight[i] = mod_bits & 1 ? 8 : 0;\n    }\n}\n\nstatic void applicate_color_4bpp(const uint8_t *data, PVRTCTexelInfo *const info[9], uint32_t buf[32]) {\n    static const int INTERP_WEIGHT[4][3] = {{2, 2, 0}, {1, 3, 0}, {0, 4, 0}, {0, 3, 1}};\n    PVRTCTexelColorInt clr_a[16] = {}, clr_b[16] = {};\n\n    for (int y = 0, i = 0; y < 4; y++) {\n        for (int x = 0; x < 4; x++, i++) {\n            for (int acy = 0, ac = 0; acy < 3; acy++) {\n                for (int acx = 0; acx < 3; acx++, ac++) {\n                    int interp_weight = INTERP_WEIGHT[x][acx] * INTERP_WEIGHT[y][acy];\n                    clr_a[i].r += info[ac]->a.r * interp_weight;\n                    clr_a[i].g += info[ac]->a.g * interp_weight;\n                    clr_a[i].b += info[ac]->a.b * interp_weight;\n                    clr_a[i].a += info[ac]->a.a * interp_weight;\n                    clr_b[i].r += info[ac]->b.r * interp_weight;\n                    clr_b[i].g += info[ac]->b.g * interp_weight;\n                    clr_b[i].b += info[ac]->b.b * interp_weight;\n                    clr_b[i].a += info[ac]->b.a * interp_weight;\n                }\n            }\n            clr_a[i].r = (clr_a[i].r >> 1) + (clr_a[i].r >> 6);\n            clr_a[i].g = (clr_a[i].g >> 1) + (clr_a[i].g >> 6);\n            clr_a[i].b = (clr_a[i].b >> 1) + (clr_a[i].b >> 6);\n            clr_a[i].a = (clr_a[i].a) + (clr_a[i].a >> 4);\n            clr_b[i].r = (clr_b[i].r >> 1) + (clr_b[i].r >> 6);\n            clr_b[i].g = (clr_b[i].g >> 1) + (clr_b[i].g >> 6);\n            clr_b[i].b = (clr_b[i].b >> 1) + (clr_b[i].b >> 6);\n            clr_b[i].a = (clr_b[i].a) + (clr_b[i].a >> 4);\n        }\n    }\n\n    const PVRTCTexelInfo *self_info = info[4];\n    uint32_t punch_through_flag = self_info->punch_through_flag;\n    for (int i = 0; i < 16; i++, punch_through_flag >>= 1) {\n        buf[i] = color((clr_a[i].r * (8 - self_info->weight[i]) + clr_b[i].r * self_info->weight[i]) / 8,\n                       (clr_a[i].g * (8 - self_info->weight[i]) + clr_b[i].g * self_info->weight[i]) / 8,\n                       (clr_a[i].b * (8 - self_info->weight[i]) + clr_b[i].b * self_info->weight[i]) / 8,\n                       punch_through_flag & 1\n                         ? 0\n                         : (clr_a[i].a * (8 - self_info->weight[i]) + clr_b[i].a * self_info->weight[i]) / 8);\n    }\n}\n\nstatic void applicate_color_2bpp(const uint8_t *data, PVRTCTexelInfo *const info[9], uint32_t buf[32]) {\n    static const int INTERP_WEIGHT_X[8][3] = {{4, 4, 0}, {3, 5, 0}, {2, 6, 0}, {1, 7, 0},\n                                              {0, 8, 0}, {0, 7, 1}, {0, 6, 2}, {0, 5, 3}};\n    static const int INTERP_WEIGHT_Y[4][3] = {{2, 2, 0}, {1, 3, 0}, {0, 4, 0}, {0, 3, 1}};\n    PVRTCTexelColorInt clr_a[32] = {}, clr_b[32] = {};\n\n    for (int y = 0, i = 0; y < 4; y++) {\n        for (int x = 0; x < 8; x++, i++) {\n            for (int acy = 0, ac = 0; acy < 3; acy++) {\n                for (int acx = 0; acx < 3; acx++, ac++) {\n                    int interp_weight = INTERP_WEIGHT_X[x][acx] * INTERP_WEIGHT_Y[y][acy];\n                    clr_a[i].r += info[ac]->a.r * interp_weight;\n                    clr_a[i].g += info[ac]->a.g * interp_weight;\n                    clr_a[i].b += info[ac]->a.b * interp_weight;\n                    clr_a[i].a += info[ac]->a.a * interp_weight;\n                    clr_b[i].r += info[ac]->b.r * interp_weight;\n                    clr_b[i].g += info[ac]->b.g * interp_weight;\n                    clr_b[i].b += info[ac]->b.b * interp_weight;\n                    clr_b[i].a += info[ac]->b.a * interp_weight;\n                }\n            }\n            clr_a[i].r = (clr_a[i].r >> 2) + (clr_a[i].r >> 7);\n            clr_a[i].g = (clr_a[i].g >> 2) + (clr_a[i].g >> 7);\n            clr_a[i].b = (clr_a[i].b >> 2) + (clr_a[i].b >> 7);\n            clr_a[i].a = (clr_a[i].a >> 1) + (clr_a[i].a >> 5);\n            clr_b[i].r = (clr_b[i].r >> 2) + (clr_b[i].r >> 7);\n            clr_b[i].g = (clr_b[i].g >> 2) + (clr_b[i].g >> 7);\n            clr_b[i].b = (clr_b[i].b >> 2) + (clr_b[i].b >> 7);\n            clr_b[i].a = (clr_b[i].a >> 1) + (clr_b[i].a >> 5);\n        }\n    }\n\n    static const int POSYA[4][2] = {{1, 24}, {4, -8}, {4, -8}, {4, -8}};\n    static const int POSYB[4][2] = {{4, 8}, {4, 8}, {4, 8}, {7, -24}};\n    static const int POSXL[8][2] = {{3, 7}, {4, -1}, {4, -1}, {4, -1}, {4, -1}, {4, -1}, {4, -1}, {4, -1}};\n    static const int POSXR[8][2] = {{4, 1}, {4, 1}, {4, 1}, {4, 1}, {4, 1}, {4, 1}, {4, 1}, {5, -7}};\n\n    PVRTCTexelInfo *self_info = info[4];\n    uint32_t punch_through_flag = self_info->punch_through_flag;\n    for (int y = 0, i = 0; y < 4; y++) {\n        for (int x = 0; x < 8; x++, i++, punch_through_flag >>= 1) {\n            switch (self_info->weight[i]) {\n            case -1:\n                self_info->weight[i] =\n                  (info[POSYA[y][0]]->weight[i + POSYA[y][1]] + info[POSYB[y][0]]->weight[i + POSYB[y][1]] + 1) / 2;\n                break;\n            case -2:\n                self_info->weight[i] =\n                  (info[POSXL[x][0]]->weight[i + POSXL[x][1]] + info[POSXR[x][0]]->weight[i + POSXR[x][1]] + 1) / 2;\n                break;\n            case -3:\n                self_info->weight[i] =\n                  (info[POSYA[y][0]]->weight[i + POSYA[y][1]] + info[POSYB[y][0]]->weight[i + POSYB[y][1]] +\n                   info[POSXL[x][0]]->weight[i + POSXL[x][1]] + info[POSXR[x][0]]->weight[i + POSXR[x][1]] + 2) /\n                  4;\n                break;\n            }\n            buf[i] = color((clr_a[i].r * (8 - self_info->weight[i]) + clr_b[i].r * self_info->weight[i]) / 8,\n                           (clr_a[i].g * (8 - self_info->weight[i]) + clr_b[i].g * self_info->weight[i]) / 8,\n                           (clr_a[i].b * (8 - self_info->weight[i]) + clr_b[i].b * self_info->weight[i]) / 8,\n                           punch_through_flag & 1\n                             ? 0\n                             : (clr_a[i].a * (8 - self_info->weight[i]) + clr_b[i].a * self_info->weight[i]) / 8);\n        }\n    }\n}\n\nint decode_pvrtc(const uint8_t *data, const long w, const long h, uint32_t *image, const int is2bpp) {\n    long bw = is2bpp ? 8 : 4;\n    long num_blocks_x = is2bpp ? (w + 7) / 8 : (w + 3) / 4;\n    long num_blocks_y = (h + 3) / 4;\n    long num_blocks = num_blocks_x * num_blocks_y;\n    long min_num_blocks = num_blocks_x <= num_blocks_y ? num_blocks_x : num_blocks_y;\n\n    if ((num_blocks_x & (num_blocks_x - 1)) || (num_blocks_y & (num_blocks_y - 1))) {\n        //extern const char* error_msg;\n        //error_msg = \"the number of blocks of each side must be a power of 2\";\n        return 0;\n    }\n\n    PVRTCTexelInfo *texel_info = (PVRTCTexelInfo *)malloc(sizeof(PVRTCTexelInfo) * num_blocks);\n    if (texel_info == NULL) {\n        //extern const char* error_msg;\n        //error_msg = \"memory allocation failed\";\n        return 0;\n    }\n\n    void (*get_texel_weights_func)(const uint8_t *, PVRTCTexelInfo *) =\n      is2bpp ? get_texel_weights_2bpp : get_texel_weights_4bpp;\n    void (*applicate_color_func)(const uint8_t *, PVRTCTexelInfo *const[9], uint32_t[32]) =\n      is2bpp ? applicate_color_2bpp : applicate_color_4bpp;\n\n    const uint8_t *d = data;\n    for (long i = 0; i < num_blocks; i++, d += 8) {\n        get_texel_colors(d, &texel_info[i]);\n        get_texel_weights_func(d, &texel_info[i]);\n    }\n\n    uint32_t buffer[32];\n    PVRTCTexelInfo *local_info[9];\n    long pos_x[3], pos_y[3];\n\n    for (long by = 0; by < num_blocks_y; by++) {\n        pos_y[0] = by == 0 ? num_blocks_y - 1 : by - 1;\n        pos_y[1] = by;\n        pos_y[2] = by == num_blocks_y - 1 ? 0 : by + 1;\n        for (long bx = 0, x = 0; bx < num_blocks_x; bx++, x += 4) {\n            pos_x[0] = bx == 0 ? num_blocks_x - 1 : bx - 1;\n            pos_x[1] = bx;\n            pos_x[2] = bx == num_blocks_x - 1 ? 0 : bx + 1;\n            for (long cy = 0, c = 0; cy < 3; cy++)\n                for (long cx = 0; cx < 3; cx++, c++)\n                    local_info[c] = &texel_info[morton_index(pos_x[cx], pos_y[cy], min_num_blocks)];\n            applicate_color_func(data + morton_index(bx, by, min_num_blocks) * 8, local_info, buffer);\n            copy_block_buffer(bx, by, w, h, bw, 4, buffer, image);\n        }\n    }\n\n    free(texel_info);\n    return 1;\n}\n"
  },
  {
    "path": "Texture2DDecoderNative/pvrtc.h",
    "content": "#ifndef PVRTC_H\n#define PVRTC_H\n\n#include <stdint.h>\n\ntypedef struct {\n    uint8_t r;\n    uint8_t g;\n    uint8_t b;\n    uint8_t a;\n} PVRTCTexelColor;\n\ntypedef struct {\n    int r;\n    int g;\n    int b;\n    int a;\n} PVRTCTexelColorInt;\n\ntypedef struct {\n    PVRTCTexelColor a;\n    PVRTCTexelColor b;\n    int8_t weight[32];\n    uint32_t punch_through_flag;\n} PVRTCTexelInfo;\n\nint decode_pvrtc(const uint8_t *, const long, const long, uint32_t *, const int);\n\n#endif /* end of include guard: PVRTC_H */\n"
  },
  {
    "path": "Texture2DDecoderNative/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Texture2DDecoderNative.rc\n\n// ¶һĬֵ\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        101\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1001\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "Texture2DDecoderNative/unitycrunch/crn_decomp.h",
    "content": "// File: crn_decomp.h - Fast CRN->DXTc texture transcoder header file library\n// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC\n// See Copyright Notice and license at the end of this file.\n//\n// This single header file contains *all* of the code necessary to unpack .CRN files to raw DXTn bits.\n// It does NOT depend on the crn compression library.\n//\n// Note: This is a single file, stand-alone C++ library which is controlled by the use of the following macro:\n//   If CRND_INCLUDE_CRND_H is NOT defined, the header is included.\n//\n// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing\n#ifndef CRND_INCLUDE_CRND_H\n#define CRND_INCLUDE_CRND_H\n\n// Include crn_defs.h (only to bring in some basic CRN-related types and structures).\n#include \"crn_defs.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n#ifdef _WIN32\n#include <memory.h>\n#else\n#include <malloc.h>\n#endif\n#include <stdarg.h>\n#include <new>  // needed for placement new, _msize, _expand\n\n#define CRND_RESTRICT __restrict\n\n#ifdef _MSC_VER\n#pragma warning(disable : 4127)  // warning C4127: conditional expression is constant\n#endif\n\n#ifdef CRND_DEVEL\n#ifndef _WIN32_WINNT\n#define _WIN32_WINNT 0x500\n#endif\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#ifndef\n#define NOMINMAX\n#endif\n#include \"windows.h\"  // only for IsDebuggerPresent(), DebugBreak(), and OutputDebugStringA()\n#endif\n\n// File: crnd_types.h\nnamespace unitycrnd {\nconst crn_uint8 cUINT8_MIN = 0;\nconst crn_uint8 cUINT8_MAX = 0xFFU;\nconst uint16 cUINT16_MIN = 0;\nconst uint16 cUINT16_MAX = 0xFFFFU;\nconst uint32 cUINT32_MIN = 0;\nconst uint32 cUINT32_MAX = 0xFFFFFFFFU;\n\nconst int8 cINT8_MIN = -128;\nconst int8 cINT8_MAX = 127;\nconst int16 cINT16_MIN = -32768;\nconst int16 cINT16_MAX = 32767;\nconst int32 cINT32_MIN = (-2147483647 - 1);\nconst int32 cINT32_MAX = 2147483647;\n\nenum eClear { cClear };\n\nconst uint32 cIntBits = 32U;\n\ntemplate <typename T>\nstruct int_traits {\n  enum { cMin = unitycrnd::cINT32_MIN,\n         cMax = unitycrnd::cINT32_MAX,\n         cSigned = true };\n};\n\ntemplate <>\nstruct int_traits<int8> {\n  enum { cMin = unitycrnd::cINT8_MIN,\n         cMax = unitycrnd::cINT8_MAX,\n         cSigned = true };\n};\ntemplate <>\nstruct int_traits<int16> {\n  enum { cMin = unitycrnd::cINT16_MIN,\n         cMax = unitycrnd::cINT16_MAX,\n         cSigned = true };\n};\ntemplate <>\nstruct int_traits<int32> {\n  enum { cMin = unitycrnd::cINT32_MIN,\n         cMax = unitycrnd::cINT32_MAX,\n         cSigned = true };\n};\n\ntemplate <>\nstruct int_traits<uint8> {\n  enum { cMin = 0,\n         cMax = unitycrnd::cUINT8_MAX,\n         cSigned = false };\n};\ntemplate <>\nstruct int_traits<uint16> {\n  enum { cMin = 0,\n         cMax = unitycrnd::cUINT16_MAX,\n         cSigned = false };\n};\ntemplate <>\nstruct int_traits<uint32> {\n  enum { cMin = 0,\n         cMax = unitycrnd::cUINT32_MAX,\n         cSigned = false };\n};\n\nstruct empty_type {};\n\n}  // namespace unitycrnd\n\n// File: crnd_platform.h\nnamespace unitycrnd {\n\nbool crnd_is_debugger_present();\nvoid crnd_debug_break();\nvoid crnd_output_debug_string(const char* p);\n\n// actually in crnd_assert.cpp\nvoid crnd_assert(const char* pExp, const char* pFile, unsigned line);\nvoid crnd_fail(const char* pExp, const char* pFile, unsigned line);\n\n}  // namespace unitycrnd\n\n// File: crnd_assert.h\nnamespace unitycrnd {\nvoid crnd_assert(const char* pExp, const char* pFile, unsigned line);\n\n#ifdef NDEBUG\n#define CRND_ASSERT(x) ((void)0)\n#undef CRND_ASSERTS_ENABLED\n#else\n#define CRND_ASSERT(_exp) (void)((!!(_exp)) || (unitycrnd::crnd_assert(#_exp, __FILE__, __LINE__), 0))\n#define CRND_ASSERTS_ENABLED\n#endif\n\nvoid crnd_trace(const char* pFmt, va_list args);\nvoid crnd_trace(const char* pFmt, ...);\n\n}  // namespace unitycrnd\n\n// File: crnd_helpers.h\nnamespace unitycrnd {\nnamespace helpers {\ntemplate <typename T>\nstruct rel_ops {\n  friend bool operator!=(const T& x, const T& y) { return (!(x == y)); }\n  friend bool operator>(const T& x, const T& y) { return (y < x); }\n  friend bool operator<=(const T& x, const T& y) { return (!(y < x)); }\n  friend bool operator>=(const T& x, const T& y) { return (!(x < y)); }\n};\n\ntemplate <typename T>\ninline T* construct(T* p) {\n  return new (static_cast<void*>(p)) T;\n}\n\ntemplate <typename T, typename U>\ninline T* construct(T* p, const U& init) {\n  return new (static_cast<void*>(p)) T(init);\n}\n\ntemplate <typename T>\nvoid construct_array(T* p, uint32 n) {\n  T* q = p + n;\n  for (; p != q; ++p)\n    new (static_cast<void*>(p)) T;\n}\n\ntemplate <typename T, typename U>\nvoid construct_array(T* p, uint32 n, const U& init) {\n  T* q = p + n;\n  for (; p != q; ++p)\n    new (static_cast<void*>(p)) T(init);\n}\n\ntemplate <typename T>\ninline void destruct(T* p) {\n  p->~T();\n}\n\ntemplate <typename T>\ninline void destruct_array(T* p, uint32 n) {\n  T* q = p + n;\n  for (; p != q; ++p)\n    p->~T();\n}\n\n}  // namespace helpers\n\n}  // namespace unitycrnd\n\n// File: crnd_traits.h\nnamespace unitycrnd {\ntemplate <typename T>\nstruct scalar_type {\n  enum { cFlag = false };\n  static inline void construct(T* p) { helpers::construct(p); }\n  static inline void construct(T* p, const T& init) { helpers::construct(p, init); }\n  static inline void construct_array(T* p, uint32 n) { helpers::construct_array(p, n); }\n  static inline void destruct(T* p) { helpers::destruct(p); }\n  static inline void destruct_array(T* p, uint32 n) { helpers::destruct_array(p, n); }\n};\n\ntemplate <typename T>\nstruct scalar_type<T*> {\n  enum { cFlag = true };\n  static inline void construct(T** p) { memset(p, 0, sizeof(T*)); }\n  static inline void construct(T** p, T* init) { *p = init; }\n  static inline void construct_array(T** p, uint32 n) { memset(p, 0, sizeof(T*) * n); }\n  static inline void destruct(T**) {}\n  static inline void destruct_array(T**, uint32) {}\n};\n\n#define CRND_DEFINE_BUILT_IN_TYPE(X)                                                    \\\n  template <>                                                                           \\\n  struct scalar_type<X> {                                                               \\\n    enum { cFlag = true };                                                              \\\n    static inline void construct(X* p) { memset(p, 0, sizeof(X)); }                     \\\n    static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); }  \\\n    static inline void construct_array(X* p, uint32 n) { memset(p, 0, sizeof(X) * n); } \\\n    static inline void destruct(X*) {}                                                  \\\n    static inline void destruct_array(X*, uint32) {}                                    \\\n  };\n\nCRND_DEFINE_BUILT_IN_TYPE(bool)\nCRND_DEFINE_BUILT_IN_TYPE(char)\nCRND_DEFINE_BUILT_IN_TYPE(unsigned char)\nCRND_DEFINE_BUILT_IN_TYPE(short)\nCRND_DEFINE_BUILT_IN_TYPE(unsigned short)\nCRND_DEFINE_BUILT_IN_TYPE(int)\nCRND_DEFINE_BUILT_IN_TYPE(unsigned int)\nCRND_DEFINE_BUILT_IN_TYPE(long)\nCRND_DEFINE_BUILT_IN_TYPE(unsigned long)\nCRND_DEFINE_BUILT_IN_TYPE(int64)\nCRND_DEFINE_BUILT_IN_TYPE(uint64)\nCRND_DEFINE_BUILT_IN_TYPE(float)\nCRND_DEFINE_BUILT_IN_TYPE(double)\nCRND_DEFINE_BUILT_IN_TYPE(long double)\n\n#undef CRND_DEFINE_BUILT_IN_TYPE\n\n// See: http://erdani.org/publications/cuj-2004-06.pdf\n\ntemplate <typename T>\nstruct bitwise_movable {\n  enum { cFlag = false };\n};\n\n// Defines type Q as bitwise movable.\n#define CRND_DEFINE_BITWISE_MOVABLE(Q) \\\n  template <>                          \\\n  struct bitwise_movable<Q> {          \\\n    enum { cFlag = true };             \\\n  };\n\n// From yasli_traits.h:\n// Credit goes to Boost;\n// also found in the C++ Templates book by Vandevoorde and Josuttis\n\ntypedef char (&yes_t)[1];\ntypedef char (&no_t)[2];\n\ntemplate <class U>\nyes_t class_test(int U::*);\ntemplate <class U>\nno_t class_test(...);\n\ntemplate <class T>\nstruct is_class {\n  enum { value = (sizeof(class_test<T>(0)) == sizeof(yes_t)) };\n};\n\ntemplate <typename T>\nstruct is_pointer {\n  enum { value = false };\n};\n\ntemplate <typename T>\nstruct is_pointer<T*> {\n  enum { value = true };\n};\n\n#define CRND_IS_POD(T) __is_pod(T)\n\n}  // namespace unitycrnd\n\n// File: crnd_mem.h\nnamespace unitycrnd {\nvoid* crnd_malloc(size_t size, size_t* pActual_size = NULL);\nvoid* crnd_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true);\nvoid crnd_free(void* p);\nsize_t crnd_msize(void* p);\n\ntemplate <typename T>\ninline T* crnd_new() {\n  T* p = static_cast<T*>(crnd_malloc(sizeof(T)));\n  if (!p)\n    return NULL;\n\n  return helpers::construct(p);\n}\n\ntemplate <typename T>\ninline T* crnd_new(const T& init) {\n  T* p = static_cast<T*>(crnd_malloc(sizeof(T)));\n  if (!p)\n    return NULL;\n\n  return helpers::construct(p, init);\n}\n\ntemplate <typename T>\ninline T* crnd_new_array(uint32 num) {\n  if (!num)\n    num = 1;\n\n  uint8* q = static_cast<uint8*>(crnd_malloc(CRND_MIN_ALLOC_ALIGNMENT + sizeof(T) * num));\n  if (!q)\n    return NULL;\n\n  T* p = reinterpret_cast<T*>(q + CRND_MIN_ALLOC_ALIGNMENT);\n\n  reinterpret_cast<uint32*>(p)[-1] = num;\n  reinterpret_cast<uint32*>(p)[-2] = ~num;\n\n  helpers::construct_array(p, num);\n  return p;\n}\n\ntemplate <typename T>\ninline void crnd_delete(T* p) {\n  if (p) {\n    helpers::destruct(p);\n    crnd_free(p);\n  }\n}\n\ntemplate <typename T>\ninline void crnd_delete_array(T* p) {\n  if (p) {\n    const uint32 num = reinterpret_cast<uint32*>(p)[-1];\n    CRND_ASSERT(num && (num == ~reinterpret_cast<uint32*>(p)[-2]));\n\n    helpers::destruct_array(p, num);\n\n    crnd_free(reinterpret_cast<uint8*>(p) - CRND_MIN_ALLOC_ALIGNMENT);\n  }\n}\n\n}  // namespace unitycrnd\n\n// File: crnd_math.h\nnamespace unitycrnd {\nnamespace math {\nconst float cNearlyInfinite = 1.0e+37f;\n\nconst float cDegToRad = 0.01745329252f;\nconst float cRadToDeg = 57.29577951f;\n\nextern uint32 g_bitmasks[32];\n\n// Yes I know these should probably be pass by ref, not val:\n// http://www.stepanovpapers.com/notes.pdf\n// Just don't use them on non-simple (non built-in) types!\ntemplate <typename T>\ninline T minimum(T a, T b) {\n  return (a < b) ? a : b;\n}\n\ntemplate <typename T>\ninline T minimum(T a, T b, T c) {\n  return minimum(minimum(a, b), c);\n}\n\ntemplate <typename T>\ninline T maximum(T a, T b) {\n  return (a > b) ? a : b;\n}\n\ntemplate <typename T>\ninline T maximum(T a, T b, T c) {\n  return maximum(maximum(a, b), c);\n}\n\ntemplate <typename T>\ninline T clamp(T value, T low, T high) {\n  return (value < low) ? low : ((value > high) ? high : value);\n}\n\ntemplate <typename T>\ninline T square(T value) {\n  return value * value;\n}\n\ninline bool is_power_of_2(uint32 x) {\n  return x && ((x & (x - 1U)) == 0U);\n}\n\n// From \"Hackers Delight\"\ninline int next_pow2(uint32 val) {\n  val--;\n  val |= val >> 16;\n  val |= val >> 8;\n  val |= val >> 4;\n  val |= val >> 2;\n  val |= val >> 1;\n  return val + 1;\n}\n\n// Returns the total number of bits needed to encode v.\ninline uint32 total_bits(uint32 v) {\n  uint32 l = 0;\n  while (v > 0U) {\n    v >>= 1;\n    l++;\n  }\n  return l;\n}\n\ninline uint floor_log2i(uint v) {\n  uint l = 0;\n  while (v > 1U) {\n    v >>= 1;\n    l++;\n  }\n  return l;\n}\n\ninline uint ceil_log2i(uint v) {\n  uint l = floor_log2i(v);\n  if ((l != cIntBits) && (v > (1U << l)))\n    l++;\n  return l;\n}\n}\n}\n\n// File: crnd_utils.h\nnamespace unitycrnd {\nnamespace utils {\ntemplate <typename T>\ninline void zero_object(T& obj) {\n  memset(&obj, 0, sizeof(obj));\n}\n\ntemplate <typename T>\ninline void zero_this(T* pObj) {\n  memset(pObj, 0, sizeof(*pObj));\n}\n\ntemplate <typename T>\ninline void swap(T& left, T& right) {\n  T temp(left);\n  left = right;\n  right = temp;\n}\n\ninline void invert_buf(void* pBuf, uint32 size) {\n  uint8* p = static_cast<uint8*>(pBuf);\n\n  const uint32 half_size = size >> 1;\n  for (uint32 i = 0; i < half_size; i++)\n    swap(p[i], p[size - 1U - i]);\n}\n\nstatic inline uint16 swap16(uint16 x) {\n  return static_cast<uint16>((x << 8) | (x >> 8));\n}\nstatic inline uint32 swap32(uint32 x) {\n  return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24));\n}\n\nuint32 compute_max_mips(uint32 width, uint32 height);\n\n}  // namespace utils\n\n}  // namespace unitycrnd\n\n// File: crnd_vector.h\nnamespace unitycrnd {\nstruct elemental_vector {\n  void* m_p;\n  uint32 m_size;\n  uint32 m_capacity;\n\n  typedef void (*object_mover)(void* pDst, void* pSrc, uint32 num);\n\n  bool increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pRelocate);\n};\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4127)  //  warning C4127: conditional expression is constant\n#endif\n\ntemplate <typename T>\nclass vector : public helpers::rel_ops<vector<T> > {\n public:\n  typedef T* iterator;\n  typedef const T* const_iterator;\n  typedef T value_type;\n  typedef T& reference;\n  typedef const T& const_reference;\n  typedef T* pointer;\n  typedef const T* const_pointer;\n\n  inline vector()\n      : m_p(NULL),\n        m_size(0),\n        m_capacity(0),\n        m_alloc_failed(false) {\n  }\n\n  inline vector(const vector& other)\n      : m_p(NULL),\n        m_size(0),\n        m_capacity(0),\n        m_alloc_failed(false) {\n    *this = other;\n  }\n\n  inline vector(uint32 size)\n      : m_p(NULL),\n        m_size(0),\n        m_capacity(0),\n        m_alloc_failed(false) {\n    resize(size);\n  }\n\n  inline ~vector() {\n    clear();\n  }\n\n  // I don't like this. Not at all. But exceptions, or just failing suck worse.\n  inline bool get_alloc_failed() const { return m_alloc_failed; }\n  inline void clear_alloc_failed() { m_alloc_failed = false; }\n\n  inline bool assign(const vector& other) {\n    if (this == &other)\n      return true;\n\n    if (m_capacity == other.m_size)\n      resize(0);\n    else {\n      clear();\n\n      if (!increase_capacity(other.m_size, false))\n        return false;\n    }\n\n    if (scalar_type<T>::cFlag)\n      memcpy(m_p, other.m_p, other.m_size * sizeof(T));\n    else {\n      T* pDst = m_p;\n      const T* pSrc = other.m_p;\n      for (uint32 i = other.m_size; i > 0; i--)\n        helpers::construct(pDst++, *pSrc++);\n    }\n\n    m_size = other.m_size;\n\n    return true;\n  }\n\n  inline vector& operator=(const vector& other) {\n    assign(other);\n    return *this;\n  }\n\n  inline const T* begin() const { return m_p; }\n  T* begin() { return m_p; }\n\n  inline const T* end() const { return m_p + m_size; }\n  T* end() { return m_p + m_size; }\n\n  inline bool empty() const { return !m_size; }\n  inline uint32 size() const { return m_size; }\n  inline uint32 capacity() const { return m_capacity; }\n\n  inline const T& operator[](uint32 i) const {\n    CRND_ASSERT(i < m_size);\n    return m_p[i];\n  }\n  inline T& operator[](uint32 i) {\n    CRND_ASSERT(i < m_size);\n    return m_p[i];\n  }\n\n  inline const T& front() const {\n    CRND_ASSERT(m_size);\n    return m_p[0];\n  }\n  inline T& front() {\n    CRND_ASSERT(m_size);\n    return m_p[0];\n  }\n\n  inline const T& back() const {\n    CRND_ASSERT(m_size);\n    return m_p[m_size - 1];\n  }\n  inline T& back() {\n    CRND_ASSERT(m_size);\n    return m_p[m_size - 1];\n  }\n\n  inline void clear() {\n    if (m_p) {\n      scalar_type<T>::destruct_array(m_p, m_size);\n      crnd_free(m_p);\n      m_p = NULL;\n      m_size = 0;\n      m_capacity = 0;\n    }\n\n    m_alloc_failed = false;\n  }\n\n  inline bool reserve(uint32 new_capacity) {\n    if (!increase_capacity(new_capacity, false))\n      return false;\n\n    return true;\n  }\n\n  inline bool resize(uint32 new_size) {\n    if (m_size != new_size) {\n      if (new_size < m_size)\n        scalar_type<T>::destruct_array(m_p + new_size, m_size - new_size);\n      else {\n        if (new_size > m_capacity) {\n          if (!increase_capacity(new_size, new_size == (m_size + 1)))\n            return false;\n        }\n\n        scalar_type<T>::construct_array(m_p + m_size, new_size - m_size);\n      }\n\n      m_size = new_size;\n    }\n\n    return true;\n  }\n\n  inline bool push_back(const T& obj) {\n    CRND_ASSERT(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size)));\n\n    if (m_size >= m_capacity) {\n      if (!increase_capacity(m_size + 1, true))\n        return false;\n    }\n\n    scalar_type<T>::construct(m_p + m_size, obj);\n    m_size++;\n\n    return true;\n  }\n\n  inline void pop_back() {\n    CRND_ASSERT(m_size);\n\n    if (m_size) {\n      m_size--;\n      scalar_type<T>::destruct(&m_p[m_size]);\n    }\n  }\n\n  inline void insert(uint32 index, const T* p, uint32 n) {\n    CRND_ASSERT(index <= m_size);\n    if (!n)\n      return;\n\n    const uint32 orig_size = m_size;\n    resize(m_size + n);\n\n    const T* pSrc = m_p + orig_size - 1;\n    T* pDst = const_cast<T*>(pSrc) + n;\n\n    const uint32 num_to_move = orig_size - index;\n\n    for (uint32 i = 0; i < num_to_move; i++) {\n      CRND_ASSERT((pDst - m_p) < (int)m_size);\n      *pDst-- = *pSrc--;\n    }\n\n    pSrc = p;\n    pDst = m_p + index;\n\n    for (uint32 i = 0; i < n; i++) {\n      CRND_ASSERT((pDst - m_p) < (int)m_size);\n      *pDst++ = *p++;\n    }\n  }\n\n  inline void erase(uint32 start, uint32 n) {\n    CRND_ASSERT((start + n) <= m_size);\n\n    if (!n)\n      return;\n\n    const uint32 num_to_move = m_size - (start + n);\n\n    T* pDst = m_p + start;\n    T* pDst_end = pDst + num_to_move;\n    const T* pSrc = m_p + start + n;\n\n    while (pDst != pDst_end)\n      *pDst++ = *pSrc++;\n\n    scalar_type<T>::destruct_array(pDst_end, n);\n\n    m_size -= n;\n  }\n\n  inline void erase(uint32 index) {\n    erase(index, 1);\n  }\n\n  inline void erase(T* p) {\n    CRND_ASSERT((p >= m_p) && (p < (m_p + m_size)));\n    erase(p - m_p);\n  }\n\n  inline bool operator==(const vector& rhs) const {\n    if (m_size != rhs.m_size)\n      return false;\n    else if (m_size) {\n      if (scalar_type<T>::cFlag)\n        return memcmp(m_p, rhs.m_p, sizeof(T) * m_size) == 0;\n      else {\n        const T* pSrc = m_p;\n        const T* pDst = rhs.m_p;\n        for (uint32 i = m_size; i; i--)\n          if (!(*pSrc++ == *pDst++))\n            return false;\n      }\n    }\n\n    return true;\n  }\n\n  inline bool operator<(const vector& rhs) const {\n    const uint32 min_size = math::minimum(m_size, rhs.m_size);\n\n    const T* pSrc = m_p;\n    const T* pSrc_end = m_p + min_size;\n    const T* pDst = rhs.m_p;\n\n    while ((pSrc < pSrc_end) && (*pSrc == *pDst)) {\n      pSrc++;\n      pDst++;\n    }\n\n    if (pSrc < pSrc_end)\n      return *pSrc < *pDst;\n\n    return m_size < rhs.m_size;\n  }\n\n  void swap(vector& other) {\n    utils::swap(m_p, other.m_p);\n    utils::swap(m_size, other.m_size);\n    utils::swap(m_capacity, other.m_capacity);\n  }\n\n private:\n  T* m_p;\n  uint32 m_size;\n  uint32 m_capacity;\n  bool m_alloc_failed;\n\n  template <typename Q>\n  struct is_vector {\n    enum { cFlag = false };\n  };\n  template <typename Q>\n  struct is_vector<vector<Q> > {\n    enum { cFlag = true };\n  };\n\n  static void object_mover(void* pDst_void, void* pSrc_void, uint32 num) {\n    T* pSrc = static_cast<T*>(pSrc_void);\n    T* const pSrc_end = pSrc + num;\n    T* pDst = static_cast<T*>(pDst_void);\n\n    while (pSrc != pSrc_end) {\n      helpers::construct<T>(pDst, *pSrc);\n      pSrc->~T();\n      pSrc++;\n      pDst++;\n    }\n  }\n\n  inline bool increase_capacity(uint32 min_new_capacity, bool grow_hint) {\n    if (!reinterpret_cast<elemental_vector*>(this)->increase_capacity(\n            min_new_capacity, grow_hint, sizeof(T),\n            ((scalar_type<T>::cFlag) || (is_vector<T>::cFlag) || (bitwise_movable<T>::cFlag) || CRND_IS_POD(T)) ? NULL : object_mover)) {\n      m_alloc_failed = true;\n      return false;\n    }\n    return true;\n  }\n};\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\nextern void vector_test();\n\n}  // namespace unitycrnd\n\n// File: crnd_private.h\nnamespace unitycrnd {\nconst crn_header* crnd_get_header(const void* pData, uint32 data_size);\n\n}  // namespace unitycrnd\n\n// File: checksum.h\nnamespace unitycrnd {\n// crc16() intended for small buffers - doesn't use an acceleration table.\nconst uint16 cInitCRC16 = 0;\nuint16 crc16(const void* pBuf, uint32 len, uint16 crc = cInitCRC16);\n\n}  // namespace unitycrnd\n\n// File: crnd_color.h\nnamespace unitycrnd {\ntemplate <typename component_type>\nstruct color_quad_component_traits {\n  enum {\n    cSigned = false,\n    cFloat = false,\n    cMin = cUINT8_MIN,\n    cMax = cUINT8_MAX\n  };\n};\n\ntemplate <>\nstruct color_quad_component_traits<int16> {\n  enum {\n    cSigned = true,\n    cFloat = false,\n    cMin = cINT16_MIN,\n    cMax = cINT16_MAX\n  };\n};\n\ntemplate <>\nstruct color_quad_component_traits<uint16> {\n  enum {\n    cSigned = false,\n    cFloat = false,\n    cMin = cUINT16_MIN,\n    cMax = cUINT16_MAX\n  };\n};\n\ntemplate <>\nstruct color_quad_component_traits<int32> {\n  enum {\n    cSigned = true,\n    cFloat = false,\n    cMin = cINT32_MIN,\n    cMax = cINT32_MAX\n  };\n};\n\ntemplate <>\nstruct color_quad_component_traits<uint32> {\n  enum {\n    cSigned = false,\n    cFloat = false,\n    cMin = cUINT32_MIN,\n    cMax = cUINT32_MAX\n  };\n};\n\ntemplate <>\nstruct color_quad_component_traits<float> {\n  enum {\n    cSigned = false,\n    cFloat = true,\n    cMin = cINT32_MIN,\n    cMax = cINT32_MAX\n  };\n};\n\ntemplate <>\nstruct color_quad_component_traits<double> {\n  enum {\n    cSigned = false,\n    cFloat = true,\n    cMin = cINT32_MIN,\n    cMax = cINT32_MAX\n  };\n};\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4201)  //  warning C4201: nonstandard extension used : nameless struct/union\n#pragma warning(disable : 4127)  //  warning C4127: conditional expression is constant\n#endif\n\ntemplate <typename component_type, typename parameter_type>\nclass color_quad : public helpers::rel_ops<color_quad<component_type, parameter_type> > {\n  static parameter_type clamp(parameter_type v) {\n    if (component_traits::cFloat)\n      return v;\n    else {\n      if (v < component_traits::cMin)\n        return component_traits::cMin;\n      else if (v > component_traits::cMax)\n        return component_traits::cMax;\n      return v;\n    }\n  }\n\n public:\n  typedef component_type component_t;\n  typedef parameter_type parameter_t;\n  typedef color_quad_component_traits<component_type> component_traits;\n\n  enum { cNumComps = 4 };\n\n  union {\n    struct\n    {\n      component_type r;\n      component_type g;\n      component_type b;\n      component_type a;\n    };\n\n    component_type c[cNumComps];\n  };\n\n  inline color_quad() {\n  }\n\n  inline color_quad(eClear)\n      : r(0), g(0), b(0), a(0) {\n  }\n\n  inline color_quad(const color_quad& other)\n      : r(other.r), g(other.g), b(other.b), a(other.a) {\n  }\n\n  inline color_quad(parameter_type y, parameter_type alpha = component_traits::cMax) {\n    set(y, alpha);\n  }\n\n  inline color_quad(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) {\n    set(red, green, blue, alpha);\n  }\n\n  template <typename other_component_type, typename other_parameter_type>\n  inline color_quad(const color_quad<other_component_type, other_parameter_type>& other)\n      : r(clamp(other.r)), g(clamp(other.g)), b(clamp(other.b)), a(clamp(other.a)) {\n  }\n\n  inline void clear() {\n    r = 0;\n    g = 0;\n    b = 0;\n    a = 0;\n  }\n\n  inline color_quad& operator=(const color_quad& other) {\n    r = other.r;\n    g = other.g;\n    b = other.b;\n    a = other.a;\n    return *this;\n  }\n\n  template <typename other_component_type, typename other_parameter_type>\n  inline color_quad& operator=(const color_quad<other_component_type, other_parameter_type>& other) {\n    r = clamp(other.r);\n    g = clamp(other.g);\n    b = clamp(other.b);\n    a = clamp(other.a);\n    return *this;\n  }\n\n  inline color_quad& set(parameter_type y, parameter_type alpha = component_traits::cMax) {\n    y = clamp(y);\n    r = static_cast<component_type>(y);\n    g = static_cast<component_type>(y);\n    b = static_cast<component_type>(y);\n    a = static_cast<component_type>(alpha);\n    return *this;\n  }\n\n  inline color_quad& set(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) {\n    r = static_cast<component_type>(clamp(red));\n    g = static_cast<component_type>(clamp(green));\n    b = static_cast<component_type>(clamp(blue));\n    a = static_cast<component_type>(clamp(alpha));\n    return *this;\n  }\n\n  inline color_quad& set_noclamp_rgba(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha) {\n    r = static_cast<component_type>(red);\n    g = static_cast<component_type>(green);\n    b = static_cast<component_type>(blue);\n    a = static_cast<component_type>(alpha);\n    return *this;\n  }\n\n  inline color_quad& set_noclamp_rgb(parameter_type red, parameter_type green, parameter_type blue) {\n    r = static_cast<component_type>(red);\n    g = static_cast<component_type>(green);\n    b = static_cast<component_type>(blue);\n    return *this;\n  }\n\n  static inline parameter_type get_min_comp() { return component_traits::cMin; }\n  static inline parameter_type get_max_comp() { return component_traits::cMax; }\n  static inline bool get_comps_are_signed() { return component_traits::cSigned; }\n\n  inline component_type operator[](uint32 i) const {\n    CRND_ASSERT(i < cNumComps);\n    return c[i];\n  }\n  inline component_type& operator[](uint32 i) {\n    CRND_ASSERT(i < cNumComps);\n    return c[i];\n  }\n\n  inline color_quad& set_component(uint32 i, parameter_type f) {\n    CRND_ASSERT(i < cNumComps);\n\n    c[i] = static_cast<component_type>(clamp(f));\n\n    return *this;\n  }\n\n  inline color_quad& clamp(const color_quad& l, const color_quad& h) {\n    for (uint32 i = 0; i < cNumComps; i++)\n      c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l[i], h[i]));\n    return *this;\n  }\n\n  inline color_quad& clamp(parameter_type l, parameter_type h) {\n    for (uint32 i = 0; i < cNumComps; i++)\n      c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l, h));\n    return *this;\n  }\n\n  // Returns CCIR 601 luma (consistent with color_utils::RGB_To_Y).\n  inline parameter_type get_luma() const {\n    return static_cast<parameter_type>((19595U * r + 38470U * g + 7471U * b + 32768) >> 16U);\n  }\n\n  // Returns REC 709 luma.\n  inline parameter_type get_luma_rec709() const {\n    return static_cast<parameter_type>((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U);\n  }\n\n  inline uint32 squared_distance(const color_quad& c, bool alpha = true) const {\n    return math::square(r - c.r) + math::square(g - c.g) + math::square(b - c.b) + (alpha ? math::square(a - c.a) : 0);\n  }\n\n  inline bool rgb_equals(const color_quad& rhs) const {\n    return (r == rhs.r) && (g == rhs.g) && (b == rhs.b);\n  }\n\n  inline bool operator==(const color_quad& rhs) const {\n    return (r == rhs.r) && (g == rhs.g) && (b == rhs.b) && (a == rhs.a);\n  }\n\n  inline bool operator<(const color_quad& rhs) const {\n    for (uint32 i = 0; i < cNumComps; i++) {\n      if (c[i] < rhs.c[i])\n        return true;\n      else if (!(c[i] == rhs.c[i]))\n        return false;\n    }\n    return false;\n  }\n\n  inline color_quad& operator+=(const color_quad& other) {\n    for (uint32 i = 0; i < 4; i++)\n      c[i] = static_cast<component_type>(clamp(c[i] + other.c[i]));\n    return *this;\n  }\n\n  inline color_quad& operator-=(const color_quad& other) {\n    for (uint32 i = 0; i < 4; i++)\n      c[i] = static_cast<component_type>(clamp(c[i] - other.c[i]));\n    return *this;\n  }\n\n  inline color_quad& operator*=(parameter_type v) {\n    for (uint32 i = 0; i < 4; i++)\n      c[i] = static_cast<component_type>(clamp(c[i] * v));\n    return *this;\n  }\n\n  inline color_quad& operator/=(parameter_type v) {\n    for (uint32 i = 0; i < 4; i++)\n      c[i] = static_cast<component_type>(c[i] / v);\n    return *this;\n  }\n\n  inline color_quad get_swizzled(uint32 x, uint32 y, uint32 z, uint32 w) const {\n    CRND_ASSERT((x | y | z | w) < 4);\n    return color_quad(c[x], c[y], c[z], c[w]);\n  }\n\n  inline friend color_quad operator+(const color_quad& lhs, const color_quad& rhs) {\n    color_quad result(lhs);\n    result += rhs;\n    return result;\n  }\n\n  inline friend color_quad operator-(const color_quad& lhs, const color_quad& rhs) {\n    color_quad result(lhs);\n    result -= rhs;\n    return result;\n  }\n\n  inline friend color_quad operator*(const color_quad& lhs, parameter_type v) {\n    color_quad result(lhs);\n    result *= v;\n    return result;\n  }\n\n  friend inline color_quad operator/(const color_quad& lhs, parameter_type v) {\n    color_quad result(lhs);\n    result /= v;\n    return result;\n  }\n\n  friend inline color_quad operator*(parameter_type v, const color_quad& rhs) {\n    color_quad result(rhs);\n    result *= v;\n    return result;\n  }\n\n  inline uint32 get_min_component_index(bool alpha = true) const {\n    uint32 index = 0;\n    uint32 limit = alpha ? cNumComps : (cNumComps - 1);\n    for (uint32 i = 1; i < limit; i++)\n      if (c[i] < c[index])\n        index = i;\n    return index;\n  }\n\n  inline uint32 get_max_component_index(bool alpha = true) const {\n    uint32 index = 0;\n    uint32 limit = alpha ? cNumComps : (cNumComps - 1);\n    for (uint32 i = 1; i < limit; i++)\n      if (c[i] > c[index])\n        index = i;\n    return index;\n  }\n\n  inline void get_float4(float* pDst) {\n    for (uint32 i = 0; i < 4; i++)\n      pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);\n  }\n\n  inline void get_float3(float* pDst) {\n    for (uint32 i = 0; i < 3; i++)\n      pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);\n  }\n\n  static inline color_quad make_black() {\n    return color_quad(0, 0, 0, component_traits::cMax);\n  }\n\n  static inline color_quad make_white() {\n    return color_quad(component_traits::cMax, component_traits::cMax, component_traits::cMax, component_traits::cMax);\n  }\n};  // class color_quad\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\ntemplate <typename c, typename q>\nstruct scalar_type<color_quad<c, q> > {\n  enum { cFlag = true };\n  static inline void construct(color_quad<c, q>* p) {}\n  static inline void construct(color_quad<c, q>* p, const color_quad<c, q>& init) { memcpy(p, &init, sizeof(color_quad<c, q>)); }\n  static inline void construct_array(color_quad<c, q>* p, uint32 n) { p, n; }\n  static inline void destruct(color_quad<c, q>* p) { p; }\n  static inline void destruct_array(color_quad<c, q>* p, uint32 n) { p, n; }\n};\n\ntypedef color_quad<uint8, int> color_quad_u8;\ntypedef color_quad<int16, int> color_quad_i16;\ntypedef color_quad<uint16, int> color_quad_u16;\ntypedef color_quad<int32, int> color_quad_i32;\ntypedef color_quad<uint32, uint32> color_quad_u32;\ntypedef color_quad<float, float> color_quad_f;\ntypedef color_quad<double, double> color_quad_d;\n\n}  // namespace unitycrnd\n\n// File: crnd_dxt.h\nnamespace unitycrnd {\nenum dxt_format {\n  cDXTInvalid = -1,\n\n  // cDXT1/1A must appear first!\n  cDXT1,\n  cDXT1A,\n\n  cDXT3,\n  cDXT5,\n  cDXT5A,\n\n  cDXN_XY,  // inverted relative to standard ATI2, 360's DXN\n  cDXN_YX   // standard ATI2\n};\n\nenum dxt_constants {\n  cDXTBlockShift = 2U,\n  cDXTBlockSize = 1U << cDXTBlockShift,\n\n  cDXT1BytesPerBlock = 8U,\n  cDXT5NBytesPerBlock = 16U,\n\n  cDXT1SelectorBits = 2U,\n  cDXT1SelectorValues = 1U << cDXT1SelectorBits,\n  cDXT1SelectorMask = cDXT1SelectorValues - 1U,\n\n  cDXT5SelectorBits = 3U,\n  cDXT5SelectorValues = 1U << cDXT5SelectorBits,\n  cDXT5SelectorMask = cDXT5SelectorValues - 1U\n};\n\nconst float cDXT1MaxLinearValue = 3.0f;\nconst float cDXT1InvMaxLinearValue = 1.0f / 3.0f;\n\nconst float cDXT5MaxLinearValue = 7.0f;\nconst float cDXT5InvMaxLinearValue = 1.0f / 7.0f;\n\n// Converts DXT1 raw color selector index to a linear value.\nextern const uint8 g_dxt1_to_linear[cDXT1SelectorValues];\n\n// Converts DXT5 raw alpha selector index to a linear value.\nextern const uint8 g_dxt5_to_linear[cDXT5SelectorValues];\n\n// Converts DXT1 linear color selector index to a raw value (inverse of g_dxt1_to_linear).\nextern const uint8 g_dxt1_from_linear[cDXT1SelectorValues];\n\n// Converts DXT5 linear alpha selector index to a raw value (inverse of g_dxt5_to_linear).\nextern const uint8 g_dxt5_from_linear[cDXT5SelectorValues];\n\nextern const uint8 g_six_alpha_invert_table[cDXT5SelectorValues];\nextern const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues];\n\nstruct dxt1_block {\n  uint8 m_low_color[2];\n  uint8 m_high_color[2];\n\n  enum { cNumSelectorBytes = 4 };\n  uint8 m_selectors[cNumSelectorBytes];\n\n  inline void clear() {\n    utils::zero_this(this);\n  }\n\n  // These methods assume the in-memory rep is in LE byte order.\n  inline uint32 get_low_color() const {\n    return m_low_color[0] | (m_low_color[1] << 8U);\n  }\n\n  inline uint32 get_high_color() const {\n    return m_high_color[0] | (m_high_color[1] << 8U);\n  }\n\n  inline void set_low_color(uint16 c) {\n    m_low_color[0] = static_cast<uint8>(c & 0xFF);\n    m_low_color[1] = static_cast<uint8>((c >> 8) & 0xFF);\n  }\n\n  inline void set_high_color(uint16 c) {\n    m_high_color[0] = static_cast<uint8>(c & 0xFF);\n    m_high_color[1] = static_cast<uint8>((c >> 8) & 0xFF);\n  }\n\n  inline uint32 get_selector(uint32 x, uint32 y) const {\n    CRND_ASSERT((x < 4U) && (y < 4U));\n    return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask;\n  }\n\n  inline void set_selector(uint32 x, uint32 y, uint32 val) {\n    CRND_ASSERT((x < 4U) && (y < 4U) && (val < 4U));\n\n    m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits)));\n    m_selectors[y] |= (val << (x * cDXT1SelectorBits));\n  }\n\n  static uint16 pack_color(const color_quad_u8& color, bool scaled, uint32 bias = 127U);\n  static uint16 pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias = 127U);\n\n  static color_quad_u8 unpack_color(uint16 packed_color, bool scaled, uint32 alpha = 255U);\n  static void unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled);\n\n  static uint32 get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1);\n  static uint32 get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1);\n  // pDst must point to an array at least cDXT1SelectorValues long.\n  static uint32 get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1);\n\n  static color_quad_u8 unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha = 255U);\n  static uint32 pack_endpoints(uint32 lo, uint32 hi);\n};\n\nCRND_DEFINE_BITWISE_MOVABLE(dxt1_block);\n\nstruct dxt3_block {\n  enum { cNumAlphaBytes = 8 };\n  uint8 m_alpha[cNumAlphaBytes];\n\n  void set_alpha(uint32 x, uint32 y, uint32 value, bool scaled);\n  uint32 get_alpha(uint32 x, uint32 y, bool scaled) const;\n};\n\nCRND_DEFINE_BITWISE_MOVABLE(dxt3_block);\n\nstruct dxt5_block {\n  uint8 m_endpoints[2];\n\n  enum { cNumSelectorBytes = 6 };\n  uint8 m_selectors[cNumSelectorBytes];\n\n  inline void clear() {\n    utils::zero_this(this);\n  }\n\n  inline uint32 get_low_alpha() const {\n    return m_endpoints[0];\n  }\n\n  inline uint32 get_high_alpha() const {\n    return m_endpoints[1];\n  }\n\n  inline void set_low_alpha(uint32 i) {\n    CRND_ASSERT(i <= cUINT8_MAX);\n    m_endpoints[0] = static_cast<uint8>(i);\n  }\n\n  inline void set_high_alpha(uint32 i) {\n    CRND_ASSERT(i <= cUINT8_MAX);\n    m_endpoints[1] = static_cast<uint8>(i);\n  }\n\n  uint32 get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); }\n\n  uint32 get_selectors_as_word(uint32 index) {\n    CRND_ASSERT(index < 3);\n    return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8);\n  }\n\n  inline uint32 get_selector(uint32 x, uint32 y) const {\n    CRND_ASSERT((x < 4U) && (y < 4U));\n\n    uint32 selector_index = (y * 4) + x;\n    uint32 bit_index = selector_index * cDXT5SelectorBits;\n\n    uint32 byte_index = bit_index >> 3;\n    uint32 bit_ofs = bit_index & 7;\n\n    uint32 v = m_selectors[byte_index];\n    if (byte_index < (cNumSelectorBytes - 1))\n      v |= (m_selectors[byte_index + 1] << 8);\n\n    return (v >> bit_ofs) & 7;\n  }\n\n  inline void set_selector(uint32 x, uint32 y, uint32 val) {\n    CRND_ASSERT((x < 4U) && (y < 4U) && (val < 8U));\n\n    uint32 selector_index = (y * 4) + x;\n    uint32 bit_index = selector_index * cDXT5SelectorBits;\n\n    uint32 byte_index = bit_index >> 3;\n    uint32 bit_ofs = bit_index & 7;\n\n    uint32 v = m_selectors[byte_index];\n    if (byte_index < (cNumSelectorBytes - 1))\n      v |= (m_selectors[byte_index + 1] << 8);\n\n    v &= (~(7 << bit_ofs));\n    v |= (val << bit_ofs);\n\n    m_selectors[byte_index] = static_cast<uint8>(v);\n    if (byte_index < (cNumSelectorBytes - 1))\n      m_selectors[byte_index + 1] = static_cast<uint8>(v >> 8);\n  }\n\n  // Results written to alpha channel.\n  static uint32 get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h);\n  static uint32 get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h);\n  static uint32 get_block_values(color_quad_u8* pDst, uint32 l, uint32 h);\n\n  static uint32 get_block_values6(uint32* pDst, uint32 l, uint32 h);\n  static uint32 get_block_values8(uint32* pDst, uint32 l, uint32 h);\n  // pDst must point to an array at least cDXT5SelectorValues long.\n  static uint32 get_block_values(uint32* pDst, uint32 l, uint32 h);\n\n  static uint32 unpack_endpoint(uint32 packed, uint32 index);\n  static uint32 pack_endpoints(uint32 lo, uint32 hi);\n};\n\nCRND_DEFINE_BITWISE_MOVABLE(dxt5_block);\n\n}  // namespace unitycrnd\n\n// File: crnd_prefix_coding.h\n#ifdef _XBOX\n#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 1\n#else\n#define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 0\n#endif\n\nnamespace unitycrnd {\nnamespace prefix_coding {\nconst uint32 cMaxExpectedCodeSize = 16;\nconst uint32 cMaxSupportedSyms = 8192;\nconst uint32 cMaxTableBits = 11;\n\nclass decoder_tables {\n public:\n  inline decoder_tables()\n      : m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) {\n  }\n\n  inline decoder_tables(const decoder_tables& other)\n      : m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) {\n    *this = other;\n  }\n\n  decoder_tables& operator=(const decoder_tables& other) {\n    if (this == &other)\n      return *this;\n\n    clear();\n\n    memcpy(this, &other, sizeof(*this));\n\n    if (other.m_lookup) {\n      m_lookup = crnd_new_array<uint32>(m_cur_lookup_size);\n      if (m_lookup)\n        memcpy(m_lookup, other.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);\n    }\n\n    if (other.m_sorted_symbol_order) {\n      m_sorted_symbol_order = crnd_new_array<uint16>(m_cur_sorted_symbol_order_size);\n      if (m_sorted_symbol_order)\n        memcpy(m_sorted_symbol_order, other.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);\n    }\n\n    return *this;\n  }\n\n  inline void clear() {\n    if (m_lookup) {\n      crnd_delete_array(m_lookup);\n      m_lookup = 0;\n      m_cur_lookup_size = 0;\n    }\n\n    if (m_sorted_symbol_order) {\n      crnd_delete_array(m_sorted_symbol_order);\n      m_sorted_symbol_order = NULL;\n      m_cur_sorted_symbol_order_size = 0;\n    }\n  }\n\n  inline ~decoder_tables() {\n    if (m_lookup)\n      crnd_delete_array(m_lookup);\n\n    if (m_sorted_symbol_order)\n      crnd_delete_array(m_sorted_symbol_order);\n  }\n\n  bool init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits);\n\n  // DO NOT use any complex classes here - it is bitwise copied.\n\n  uint32 m_num_syms;\n  uint32 m_total_used_syms;\n  uint32 m_table_bits;\n  uint32 m_table_shift;\n  uint32 m_table_max_code;\n  uint32 m_decode_start_code_size;\n\n  uint8 m_min_code_size;\n  uint8 m_max_code_size;\n\n  uint32 m_max_codes[cMaxExpectedCodeSize + 1];\n  int32 m_val_ptrs[cMaxExpectedCodeSize + 1];\n\n  uint32 m_cur_lookup_size;\n  uint32* m_lookup;\n\n  uint32 m_cur_sorted_symbol_order_size;\n  uint16* m_sorted_symbol_order;\n\n  inline uint32 get_unshifted_max_code(uint32 len) const {\n    CRND_ASSERT((len >= 1) && (len <= cMaxExpectedCodeSize));\n    uint32 k = m_max_codes[len - 1];\n    if (!k)\n      return unitycrnd::cUINT32_MAX;\n    return (k - 1) >> (16 - len);\n  }\n};\n\n}  // namespace prefix_coding\n\n}  // namespace unitycrnd\n\n// File: crnd_symbol_codec.h\nnamespace unitycrnd {\nclass static_huffman_data_model {\n public:\n  static_huffman_data_model();\n  static_huffman_data_model(const static_huffman_data_model& other);\n  ~static_huffman_data_model();\n\n  static_huffman_data_model& operator=(const static_huffman_data_model& rhs);\n\n  bool init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit);\n  void clear();\n\n  inline bool is_valid() const { return m_pDecode_tables != NULL; }\n\n  inline uint32 get_total_syms() const { return m_total_syms; }\n\n  inline uint32 get_code_size(uint32 sym) const { return m_code_sizes[sym]; }\n\n  inline const uint8* get_code_sizes() const { return m_code_sizes.empty() ? NULL : &m_code_sizes[0]; }\n\n public:\n  uint32 m_total_syms;\n  unitycrnd::vector<uint8> m_code_sizes;\n  prefix_coding::decoder_tables* m_pDecode_tables;\n\n private:\n  bool prepare_decoder_tables();\n  uint compute_decoder_table_bits() const;\n\n  friend class symbol_codec;\n};\n\nclass symbol_codec {\n public:\n  symbol_codec();\n\n  bool start_decoding(const uint8* pBuf, uint32 buf_size);\n  bool decode_receive_static_data_model(static_huffman_data_model& model);\n\n  uint32 decode_bits(uint32 num_bits);\n  uint32 decode(const static_huffman_data_model& model);\n\n  uint64 stop_decoding();\n\n public:\n  const uint8* m_pDecode_buf;\n  const uint8* m_pDecode_buf_next;\n  const uint8* m_pDecode_buf_end;\n  uint32 m_decode_buf_size;\n\n  typedef uint32 bit_buf_type;\n  enum { cBitBufSize = 32U };\n  bit_buf_type m_bit_buf;\n\n  int m_bit_count;\n\n private:\n  void get_bits_init();\n  uint32 get_bits(uint32 num_bits);\n};\n\n}  // namespace unitycrnd\n\nnamespace unitycrnd {\nvoid crnd_assert(const char* pExp, const char* pFile, unsigned line) {\n  char buf[512];\n\n#if defined(_WIN32) && defined(_MSC_VER)\n  sprintf_s(buf, sizeof(buf), \"%s(%u): Assertion failure: \\\"%s\\\"\\n\", pFile, line, pExp);\n#else\n  sprintf(buf, \"%s(%u): Assertion failure: \\\"%s\\\"\\n\", pFile, line, pExp);\n#endif\n\n  crnd_output_debug_string(buf);\n\n  puts(buf);\n\n  if (crnd_is_debugger_present())\n    crnd_debug_break();\n}\n\nvoid crnd_trace(const char* pFmt, va_list args) {\n  if (crnd_is_debugger_present()) {\n    char buf[512];\n#if defined(_WIN32) && defined(_MSC_VER)\n    vsprintf_s(buf, sizeof(buf), pFmt, args);\n#else\n    vsprintf(buf, pFmt, args);\n#endif\n\n    crnd_output_debug_string(buf);\n  }\n};\n\nvoid crnd_trace(const char* pFmt, ...) {\n  va_list args;\n  va_start(args, pFmt);\n  crnd_trace(pFmt, args);\n  va_end(args);\n};\n\n}  // namespace unitycrnd\n\n// File: checksum.cpp\n// From the public domain stb.h header.\nnamespace unitycrnd {\nuint16 crc16(const void* pBuf, uint32 len, uint16 crc) {\n  crc = ~crc;\n\n  const uint8* p = reinterpret_cast<const uint8*>(pBuf);\n  while (len) {\n    const uint16 q = *p++ ^ (crc >> 8U);\n    crc <<= 8U;\n\n    uint16 r = (q >> 4U) ^ q;\n    crc ^= r;\n    r <<= 5U;\n    crc ^= r;\n    r <<= 7U;\n    crc ^= r;\n\n    len--;\n  }\n\n  return static_cast<uint16>(~crc);\n}\n\n}  // namespace unitycrnd\n\n// File: crnd_vector.cpp\nnamespace unitycrnd {\nbool elemental_vector::increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pMover) {\n  CRND_ASSERT(m_size <= m_capacity);\n  CRND_ASSERT(min_new_capacity < (0x7FFF0000U / element_size));\n\n  if (m_capacity >= min_new_capacity)\n    return true;\n\n  uint32 new_capacity = min_new_capacity;\n  if ((grow_hint) && (!math::is_power_of_2(new_capacity)))\n    new_capacity = math::next_pow2(new_capacity);\n\n  CRND_ASSERT(new_capacity && (new_capacity > m_capacity));\n\n  const uint32 desired_size = element_size * new_capacity;\n  size_t actual_size;\n  if (!pMover) {\n    void* new_p = crnd_realloc(m_p, desired_size, &actual_size, true);\n    if (!new_p)\n      return false;\n    m_p = new_p;\n  } else {\n    void* new_p = crnd_malloc(desired_size, &actual_size);\n    if (!new_p)\n      return false;\n\n    (*pMover)(new_p, m_p, m_size);\n\n    if (m_p)\n      crnd_free(m_p);\n\n    m_p = new_p;\n  }\n\n  if (actual_size > desired_size)\n    m_capacity = static_cast<uint32>(actual_size / element_size);\n  else\n    m_capacity = new_capacity;\n\n  return true;\n}\n\n}  // namespace unitycrnd\n\n// File: crnd_utils.cpp\nnamespace unitycrnd {\nnamespace utils {\nuint32 compute_max_mips(uint32 width, uint32 height) {\n  if ((width | height) == 0)\n    return 0;\n\n  uint32 num_mips = 1;\n\n  while ((width > 1U) || (height > 1U)) {\n    width >>= 1U;\n    height >>= 1U;\n    num_mips++;\n  }\n\n  return num_mips;\n}\n\n}  // namespace utils\n\n}  // namespace unitycrnd\n\n// File: crnd_prefix_coding.cpp\nnamespace unitycrnd {\nnamespace prefix_coding {\nbool decoder_tables::init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits) {\n  uint32 min_codes[cMaxExpectedCodeSize];\n  if ((!num_syms) || (table_bits > cMaxTableBits))\n    return false;\n\n  m_num_syms = num_syms;\n\n  uint32 num_codes[cMaxExpectedCodeSize + 1];\n  utils::zero_object(num_codes);\n\n  for (uint32 i = 0; i < num_syms; i++) {\n    uint32 c = pCodesizes[i];\n    if (c)\n      num_codes[c]++;\n  }\n\n  uint32 sorted_positions[cMaxExpectedCodeSize + 1];\n\n  uint32 cur_code = 0;\n\n  uint32 total_used_syms = 0;\n  uint32 max_code_size = 0;\n  uint32 min_code_size = cUINT32_MAX;\n  for (uint32 i = 1; i <= cMaxExpectedCodeSize; i++) {\n    const uint32 n = num_codes[i];\n\n    if (!n)\n      m_max_codes[i - 1] = 0;  //UINT_MAX;\n    else {\n      min_code_size = math::minimum(min_code_size, i);\n      max_code_size = math::maximum(max_code_size, i);\n\n      min_codes[i - 1] = cur_code;\n\n      m_max_codes[i - 1] = cur_code + n - 1;\n      m_max_codes[i - 1] = 1 + ((m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1));\n\n      m_val_ptrs[i - 1] = total_used_syms;\n\n      sorted_positions[i] = total_used_syms;\n\n      cur_code += n;\n      total_used_syms += n;\n    }\n\n    cur_code <<= 1;\n  }\n\n  m_total_used_syms = total_used_syms;\n\n  if (total_used_syms > m_cur_sorted_symbol_order_size) {\n    m_cur_sorted_symbol_order_size = total_used_syms;\n\n    if (!math::is_power_of_2(total_used_syms))\n      m_cur_sorted_symbol_order_size = math::minimum<uint32>(num_syms, math::next_pow2(total_used_syms));\n\n    if (m_sorted_symbol_order)\n      crnd_delete_array(m_sorted_symbol_order);\n\n    m_sorted_symbol_order = crnd_new_array<uint16>(m_cur_sorted_symbol_order_size);\n    if (!m_sorted_symbol_order)\n      return false;\n  }\n\n  m_min_code_size = static_cast<uint8>(min_code_size);\n  m_max_code_size = static_cast<uint8>(max_code_size);\n\n  for (uint32 i = 0; i < num_syms; i++) {\n    uint32 c = pCodesizes[i];\n    if (c) {\n      CRND_ASSERT(num_codes[c]);\n\n      uint32 sorted_pos = sorted_positions[c]++;\n\n      CRND_ASSERT(sorted_pos < total_used_syms);\n\n      m_sorted_symbol_order[sorted_pos] = static_cast<uint16>(i);\n    }\n  }\n\n  if (table_bits <= m_min_code_size)\n    table_bits = 0;\n  m_table_bits = table_bits;\n\n  if (table_bits) {\n    uint32 table_size = 1 << table_bits;\n    if (table_size > m_cur_lookup_size) {\n      m_cur_lookup_size = table_size;\n\n      if (m_lookup)\n        crnd_delete_array(m_lookup);\n\n      m_lookup = crnd_new_array<uint32>(table_size);\n      if (!m_lookup)\n        return false;\n    }\n\n    memset(m_lookup, 0xFF, (uint)sizeof(m_lookup[0]) * (1UL << table_bits));\n\n    for (uint32 codesize = 1; codesize <= table_bits; codesize++) {\n      if (!num_codes[codesize])\n        continue;\n\n      const uint32 fillsize = table_bits - codesize;\n      const uint32 fillnum = 1 << fillsize;\n\n      const uint32 min_code = min_codes[codesize - 1];\n      const uint32 max_code = get_unshifted_max_code(codesize);\n      const uint32 val_ptr = m_val_ptrs[codesize - 1];\n\n      for (uint32 code = min_code; code <= max_code; code++) {\n        const uint32 sym_index = m_sorted_symbol_order[val_ptr + code - min_code];\n        CRND_ASSERT(pCodesizes[sym_index] == codesize);\n\n        for (uint32 j = 0; j < fillnum; j++) {\n          const uint32 t = j + (code << fillsize);\n\n          CRND_ASSERT(t < (1U << table_bits));\n\n          CRND_ASSERT(m_lookup[t] == cUINT32_MAX);\n\n          m_lookup[t] = sym_index | (codesize << 16U);\n        }\n      }\n    }\n  }\n\n  for (uint32 i = 0; i < cMaxExpectedCodeSize; i++)\n    m_val_ptrs[i] -= min_codes[i];\n\n  m_table_max_code = 0;\n  m_decode_start_code_size = m_min_code_size;\n\n  if (table_bits) {\n    uint32 i;\n    for (i = table_bits; i >= 1; i--) {\n      if (num_codes[i]) {\n        m_table_max_code = m_max_codes[i - 1];\n        break;\n      }\n    }\n    if (i >= 1) {\n      m_decode_start_code_size = table_bits + 1;\n      for (uint32 j = table_bits + 1; j <= max_code_size; j++) {\n        if (num_codes[j]) {\n          m_decode_start_code_size = j;\n          break;\n        }\n      }\n    }\n  }\n\n  // sentinels\n  m_max_codes[cMaxExpectedCodeSize] = cUINT32_MAX;\n  m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF;\n\n  m_table_shift = 32 - m_table_bits;\n  return true;\n}\n\n}  // namespace prefix_codig\n\n}  // namespace unitycrnd\n\n// File: crnd_platform.cpp\nnamespace unitycrnd {\nbool crnd_is_debugger_present() {\n#ifdef CRND_DEVEL\n  return IsDebuggerPresent() != 0;\n#else\n  return false;\n#endif\n}\n\nvoid crnd_debug_break() {\n#ifdef CRND_DEVEL\n  DebugBreak();\n#endif\n}\n\nvoid crnd_output_debug_string(const char* p) {\n  (void)p;\n#ifdef CRND_DEVEL\n  OutputDebugStringA(p);\n#endif\n}\n\n}  // namespace unitycrnd\n\n// File: crnd_mem.cpp\nnamespace unitycrnd {\nconst uint32 MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U;\n\nstatic void* crnd_default_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void*) {\n  void* p_new;\n\n  if (!p) {\n    p_new = ::malloc(size);\n\n    if (pActual_size) {\n#ifdef _WIN32\n      *pActual_size = p_new ? ::_msize(p_new) : 0;\n#else\n      *pActual_size = p_new ? malloc_usable_size(p_new) : 0;\n#endif\n    }\n  } else if (!size) {\n    ::free(p);\n    p_new = NULL;\n\n    if (pActual_size)\n      *pActual_size = 0;\n  } else {\n    void* p_final_block = p;\n#ifdef _WIN32\n    p_new = ::_expand(p, size);\n#else\n    p_new = NULL;\n#endif\n\n    if (p_new)\n      p_final_block = p_new;\n    else if (movable) {\n      p_new = ::realloc(p, size);\n\n      if (p_new)\n        p_final_block = p_new;\n    }\n\n    if (pActual_size) {\n#ifdef _WIN32\n      *pActual_size = ::_msize(p_final_block);\n#else\n      *pActual_size = ::malloc_usable_size(p_final_block);\n#endif\n    }\n  }\n\n  return p_new;\n}\n\nstatic size_t crnd_default_msize(void* p, void* pUser_data) {\n  pUser_data;\n#ifdef _WIN32\n  return p ? _msize(p) : 0;\n#else\n  return p ? malloc_usable_size(p) : 0;\n#endif\n}\n\nstatic crnd_realloc_func g_pRealloc = crnd_default_realloc;\nstatic crnd_msize_func g_pMSize = crnd_default_msize;\nstatic void* g_pUser_data;\n\nvoid crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data) {\n  if ((!pRealloc) || (!pMSize)) {\n    g_pRealloc = crnd_default_realloc;\n    g_pMSize = crnd_default_msize;\n    g_pUser_data = NULL;\n  } else {\n    g_pRealloc = pRealloc;\n    g_pMSize = pMSize;\n    g_pUser_data = pUser_data;\n  }\n}\n\nstatic inline void crnd_mem_error(const char* p_msg) {\n  crnd_assert(p_msg, __FILE__, __LINE__);\n}\n\nvoid* crnd_malloc(size_t size, size_t* pActual_size) {\n  size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U);\n  if (!size)\n    size = sizeof(uint32);\n\n  if (size > MAX_POSSIBLE_BLOCK_SIZE) {\n    crnd_mem_error(\"crnd_malloc: size too big\");\n    return NULL;\n  }\n\n  size_t actual_size = size;\n  uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));\n\n  if (pActual_size)\n    *pActual_size = actual_size;\n\n  if ((!p_new) || (actual_size < size)) {\n    crnd_mem_error(\"crnd_malloc: out of memory\");\n    return NULL;\n  }\n\n  CRND_ASSERT(((uint32) reinterpret_cast<uintptr_t>(p_new) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0);\n\n  return p_new;\n}\n\nvoid* crnd_realloc(void* p, size_t size, size_t* pActual_size, bool movable) {\n  if ((uint32) reinterpret_cast<uintptr_t>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) {\n    crnd_mem_error(\"crnd_realloc: bad ptr\");\n    return NULL;\n  }\n\n  if (size > MAX_POSSIBLE_BLOCK_SIZE) {\n    crnd_mem_error(\"crnd_malloc: size too big\");\n    return NULL;\n  }\n\n  size_t actual_size = size;\n  void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);\n\n  if (pActual_size)\n    *pActual_size = actual_size;\n\n  CRND_ASSERT(((uint32) reinterpret_cast<uintptr_t>(p_new) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0);\n\n  return p_new;\n}\n\nvoid crnd_free(void* p) {\n  if (!p)\n    return;\n\n  if ((uint32) reinterpret_cast<uintptr_t>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) {\n    crnd_mem_error(\"crnd_free: bad ptr\");\n    return;\n  }\n\n  (*g_pRealloc)(p, 0, NULL, true, g_pUser_data);\n}\n\nsize_t crnd_msize(void* p) {\n  if (!p)\n    return 0;\n\n  if ((uint32) reinterpret_cast<uintptr_t>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) {\n    crnd_mem_error(\"crnd_msize: bad ptr\");\n    return 0;\n  }\n\n  return (*g_pMSize)(p, g_pUser_data);\n}\n\n}  // namespace unitycrnd\n\n// File: crnd_math.cpp\nnamespace unitycrnd {\nnamespace math {\nuint32 g_bitmasks[32] =\n    {\n        1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U,\n        1U << 4U, 1U << 5U, 1U << 6U, 1U << 7U,\n        1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U,\n        1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U,\n        1U << 16U, 1U << 17U, 1U << 18U, 1U << 19U,\n        1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U,\n        1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U,\n        1U << 28U, 1U << 29U, 1U << 30U, 1U << 31U};\n\n}  // namespace math\n}  // namespace unitycrnd\n\n// File: crnd_info.cpp\nnamespace unitycrnd {\n#define CRND_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U))\n\nuint32 crnd_crn_format_to_fourcc(crn_format fmt) {\n  switch (fmt) {\n    case cCRNFmtDXT1:\n      return CRND_FOURCC('D', 'X', 'T', '1');\n    case cCRNFmtDXT3:\n      return CRND_FOURCC('D', 'X', 'T', '3');\n    case cCRNFmtDXT5:\n      return CRND_FOURCC('D', 'X', 'T', '5');\n    case cCRNFmtDXN_XY:\n      return CRND_FOURCC('A', '2', 'X', 'Y');\n    case cCRNFmtDXN_YX:\n      return CRND_FOURCC('A', 'T', 'I', '2');\n    case cCRNFmtDXT5A:\n      return CRND_FOURCC('A', 'T', 'I', '1');\n    case cCRNFmtDXT5_CCxY:\n      return CRND_FOURCC('C', 'C', 'x', 'Y');\n    case cCRNFmtDXT5_xGxR:\n      return CRND_FOURCC('x', 'G', 'x', 'R');\n    case cCRNFmtDXT5_xGBR:\n      return CRND_FOURCC('x', 'G', 'B', 'R');\n    case cCRNFmtDXT5_AGBR:\n      return CRND_FOURCC('A', 'G', 'B', 'R');\n    case cCRNFmtETC1:\n      return CRND_FOURCC('E', 'T', 'C', '1');\n    case cCRNFmtETC2:\n      return CRND_FOURCC('E', 'T', 'C', '2');\n    case cCRNFmtETC2A:\n      return CRND_FOURCC('E', 'T', '2', 'A');\n    case cCRNFmtETC1S:\n      return CRND_FOURCC('E', 'T', '1', 'S');\n    case cCRNFmtETC2AS:\n      return CRND_FOURCC('E', '2', 'A', 'S');\n    default:\n      break;\n  }\n  CRND_ASSERT(false);\n  return 0;\n}\n\ncrn_format crnd_get_fundamental_dxt_format(crn_format fmt) {\n  switch (fmt) {\n    case cCRNFmtDXT5_CCxY:\n    case cCRNFmtDXT5_xGxR:\n    case cCRNFmtDXT5_xGBR:\n    case cCRNFmtDXT5_AGBR:\n      return cCRNFmtDXT5;\n    default:\n      break;\n  }\n  return fmt;\n}\n\nuint32 crnd_get_crn_format_bits_per_texel(crn_format fmt) {\n  switch (fmt) {\n    case cCRNFmtDXT1:\n    case cCRNFmtDXT5A:\n    case cCRNFmtETC1:\n    case cCRNFmtETC2:\n    case cCRNFmtETC1S:\n      return 4;\n    case cCRNFmtDXT3:\n    case cCRNFmtDXT5:\n    case cCRNFmtDXN_XY:\n    case cCRNFmtDXN_YX:\n    case cCRNFmtDXT5_CCxY:\n    case cCRNFmtDXT5_xGxR:\n    case cCRNFmtDXT5_xGBR:\n    case cCRNFmtDXT5_AGBR:\n    case cCRNFmtETC2A:\n    case cCRNFmtETC2AS:\n      return 8;\n    default:\n      break;\n  }\n  CRND_ASSERT(false);\n  return 0;\n}\n\nuint32 crnd_get_bytes_per_dxt_block(crn_format fmt) {\n  return (crnd_get_crn_format_bits_per_texel(fmt) << 4) >> 3;\n}\n\n// TODO: tmp_header isn't used/This function is a helper to support old headers.\nconst crn_header* crnd_get_header(const void* pData, uint32 data_size) {\n  if ((!pData) || (data_size < sizeof(crn_header)))\n    return NULL;\n\n  const crn_header& file_header = *static_cast<const crn_header*>(pData);\n  if (file_header.m_sig != crn_header::cCRNSigValue)\n    return NULL;\n\n  if ((file_header.m_header_size < sizeof(crn_header)) || (data_size < file_header.m_data_size))\n    return NULL;\n\n  return &file_header;\n}\n\nbool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info) {\n  if (pFile_info) {\n    if (pFile_info->m_struct_size != sizeof(crn_file_info))\n      return false;\n\n    memset(&pFile_info->m_struct_size + 1, 0, sizeof(crn_file_info) - sizeof(pFile_info->m_struct_size));\n  }\n\n  if ((!pData) || (data_size < cCRNHeaderMinSize))\n    return false;\n\n  const crn_header* pHeader = crnd_get_header(pData, data_size);\n  if (!pHeader)\n    return false;\n\n  const uint32 header_crc = crc16(&pHeader->m_data_size, (uint32)(pHeader->m_header_size - ((const uint8*)&pHeader->m_data_size - (const uint8*)pHeader)));\n  if (header_crc != pHeader->m_header_crc16)\n    return false;\n\n  const uint32 data_crc = crc16((const uint8*)pData + pHeader->m_header_size, pHeader->m_data_size - pHeader->m_header_size);\n  if (data_crc != pHeader->m_data_crc16)\n    return false;\n\n  if ((pHeader->m_faces != 1) && (pHeader->m_faces != 6))\n    return false;\n  if ((pHeader->m_width < 1) || (pHeader->m_width > cCRNMaxLevelResolution))\n    return false;\n  if ((pHeader->m_height < 1) || (pHeader->m_height > cCRNMaxLevelResolution))\n    return false;\n  if ((pHeader->m_levels < 1) || (pHeader->m_levels > utils::compute_max_mips(pHeader->m_width, pHeader->m_height)))\n    return false;\n  if (((int)pHeader->m_format < cCRNFmtDXT1) || ((int)pHeader->m_format >= cCRNFmtTotal))\n    return false;\n\n  if (pFile_info) {\n    pFile_info->m_actual_data_size = pHeader->m_data_size;\n    pFile_info->m_header_size = pHeader->m_header_size;\n    pFile_info->m_total_palette_size = pHeader->m_color_endpoints.m_size + pHeader->m_color_selectors.m_size + pHeader->m_alpha_endpoints.m_size + pHeader->m_alpha_selectors.m_size;\n    pFile_info->m_tables_size = pHeader->m_tables_size;\n\n    pFile_info->m_levels = pHeader->m_levels;\n\n    for (uint32 i = 0; i < pHeader->m_levels; i++) {\n      uint32 next_ofs = pHeader->m_data_size;\n\n      // assumes the levels are packed together sequentially\n      if ((i + 1) < pHeader->m_levels)\n        next_ofs = pHeader->m_level_ofs[i + 1];\n\n      pFile_info->m_level_compressed_size[i] = next_ofs - pHeader->m_level_ofs[i];\n    }\n\n    pFile_info->m_color_endpoint_palette_entries = pHeader->m_color_endpoints.m_num;\n    pFile_info->m_color_selector_palette_entries = pHeader->m_color_selectors.m_num;\n    ;\n    pFile_info->m_alpha_endpoint_palette_entries = pHeader->m_alpha_endpoints.m_num;\n    ;\n    pFile_info->m_alpha_selector_palette_entries = pHeader->m_alpha_selectors.m_num;\n    ;\n  }\n\n  return true;\n}\n\nbool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pInfo) {\n  if ((!pData) || (data_size < sizeof(crn_header)) || (!pInfo))\n    return false;\n\n  if (pInfo->m_struct_size != sizeof(crn_texture_info))\n    return false;\n\n  const crn_header* pHeader = crnd_get_header(pData, data_size);\n  if (!pHeader)\n    return false;\n\n  pInfo->m_width = pHeader->m_width;\n  pInfo->m_height = pHeader->m_height;\n  pInfo->m_levels = pHeader->m_levels;\n  pInfo->m_faces = pHeader->m_faces;\n  pInfo->m_format = static_cast<crn_format>((uint32)pHeader->m_format);\n  pInfo->m_bytes_per_block = pHeader->m_format == cCRNFmtDXT1 || pHeader->m_format == cCRNFmtDXT5A || pHeader->m_format == cCRNFmtETC1 || pHeader->m_format == cCRNFmtETC2 || pHeader->m_format == cCRNFmtETC1S ? 8 : 16;\n  pInfo->m_userdata0 = pHeader->m_userdata0;\n  pInfo->m_userdata1 = pHeader->m_userdata1;\n\n  return true;\n}\n\nbool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info) {\n  if ((!pData) || (data_size < cCRNHeaderMinSize) || (!pLevel_info))\n    return false;\n\n  if (pLevel_info->m_struct_size != sizeof(crn_level_info))\n    return false;\n\n  const crn_header* pHeader = crnd_get_header(pData, data_size);\n  if (!pHeader)\n    return false;\n\n  if (level_index >= pHeader->m_levels)\n    return false;\n\n  uint32 width = math::maximum<uint32>(1U, pHeader->m_width >> level_index);\n  uint32 height = math::maximum<uint32>(1U, pHeader->m_height >> level_index);\n\n  pLevel_info->m_width = width;\n  pLevel_info->m_height = height;\n  pLevel_info->m_faces = pHeader->m_faces;\n  pLevel_info->m_blocks_x = (width + 3) >> 2;\n  pLevel_info->m_blocks_y = (height + 3) >> 2;\n  pLevel_info->m_bytes_per_block = ((pHeader->m_format == cCRNFmtDXT1) || (pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16;\n  pLevel_info->m_format = static_cast<crn_format>((uint32)pHeader->m_format);\n\n  return true;\n}\n\nconst void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize) {\n  if (pSize)\n    *pSize = 0;\n\n  if ((!pData) || (data_size < cCRNHeaderMinSize))\n    return NULL;\n\n  const crn_header* pHeader = crnd_get_header(pData, data_size);\n  if (!pHeader)\n    return NULL;\n\n  if (level_index >= pHeader->m_levels)\n    return NULL;\n\n  uint32 cur_level_ofs = pHeader->m_level_ofs[level_index];\n\n  if (pSize) {\n    uint32 next_level_ofs = data_size;\n    if ((level_index + 1) < (pHeader->m_levels))\n      next_level_ofs = pHeader->m_level_ofs[level_index + 1];\n\n    *pSize = next_level_ofs - cur_level_ofs;\n  }\n\n  return static_cast<const uint8*>(pData) + cur_level_ofs;\n}\n\nuint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size) {\n  if ((!pData) || (data_size < cCRNHeaderMinSize))\n    return false;\n\n  const crn_header* pHeader = crnd_get_header(pData, data_size);\n  if (!pHeader)\n    return false;\n\n  uint32 size = pHeader->m_header_size;\n\n  size = math::maximum(size, pHeader->m_color_endpoints.m_ofs + pHeader->m_color_endpoints.m_size);\n  size = math::maximum(size, pHeader->m_color_selectors.m_ofs + pHeader->m_color_selectors.m_size);\n  size = math::maximum(size, pHeader->m_alpha_endpoints.m_ofs + pHeader->m_alpha_endpoints.m_size);\n  size = math::maximum(size, pHeader->m_alpha_selectors.m_ofs + pHeader->m_alpha_selectors.m_size);\n  size = math::maximum(size, pHeader->m_tables_ofs + pHeader->m_tables_size);\n\n  return size;\n}\n\nbool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size) {\n  if ((!pData) || (data_size < cCRNHeaderMinSize))\n    return false;\n\n  const crn_header* pHeader = crnd_get_header(pData, data_size);\n  if (!pHeader)\n    return false;\n\n  if (pHeader->m_flags & cCRNHeaderFlagSegmented)\n    return false;\n\n  const uint actual_base_data_size = crnd_get_segmented_file_size(pData, data_size);\n  if (base_data_size < actual_base_data_size)\n    return false;\n\n  memcpy(pBase_data, pData, actual_base_data_size);\n\n  crn_header& new_header = *static_cast<crn_header*>(pBase_data);\n  new_header.m_flags = new_header.m_flags | cCRNHeaderFlagSegmented;\n  new_header.m_data_size = actual_base_data_size;\n\n  new_header.m_data_crc16 = crc16((const uint8*)pBase_data + new_header.m_header_size, new_header.m_data_size - new_header.m_header_size);\n\n  new_header.m_header_crc16 = crc16(&new_header.m_data_size, new_header.m_header_size - (uint32)((const uint8*)&new_header.m_data_size - (const uint8*)&new_header));\n\n  CRND_ASSERT(crnd_validate_file(&new_header, actual_base_data_size, NULL));\n\n  return true;\n}\n\n}  // namespace unitycrnd\n\n// File: symbol_codec.cpp\nnamespace unitycrnd {\nstatic_huffman_data_model::static_huffman_data_model()\n    : m_total_syms(0),\n      m_pDecode_tables(NULL) {\n}\n\nstatic_huffman_data_model::static_huffman_data_model(const static_huffman_data_model& other)\n    : m_total_syms(0),\n      m_pDecode_tables(NULL) {\n  *this = other;\n}\n\nstatic_huffman_data_model::~static_huffman_data_model() {\n  if (m_pDecode_tables)\n    crnd_delete(m_pDecode_tables);\n}\n\nstatic_huffman_data_model& static_huffman_data_model::operator=(const static_huffman_data_model& rhs) {\n  if (this == &rhs)\n    return *this;\n\n  m_total_syms = rhs.m_total_syms;\n  m_code_sizes = rhs.m_code_sizes;\n  if (m_code_sizes.get_alloc_failed()) {\n    clear();\n    return *this;\n  }\n\n  if (rhs.m_pDecode_tables) {\n    if (m_pDecode_tables)\n      *m_pDecode_tables = *rhs.m_pDecode_tables;\n    else\n      m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>(*rhs.m_pDecode_tables);\n  } else {\n    crnd_delete(m_pDecode_tables);\n    m_pDecode_tables = NULL;\n  }\n\n  return *this;\n}\n\nvoid static_huffman_data_model::clear() {\n  m_total_syms = 0;\n  m_code_sizes.clear();\n  if (m_pDecode_tables) {\n    crnd_delete(m_pDecode_tables);\n    m_pDecode_tables = NULL;\n  }\n}\n\nbool static_huffman_data_model::init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit) {\n  CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1));\n\n  code_size_limit = math::minimum(code_size_limit, prefix_coding::cMaxExpectedCodeSize);\n\n  if (!m_code_sizes.resize(total_syms))\n    return false;\n\n  uint32 min_code_size = cUINT32_MAX;\n  uint32 max_code_size = 0;\n\n  for (uint32 i = 0; i < total_syms; i++) {\n    uint32 s = pCode_sizes[i];\n    m_code_sizes[i] = static_cast<uint8>(s);\n    min_code_size = math::minimum(min_code_size, s);\n    max_code_size = math::maximum(max_code_size, s);\n  }\n\n  if ((max_code_size < 1) || (max_code_size > 32) || (min_code_size > code_size_limit))\n    return false;\n\n  if (max_code_size > code_size_limit)\n    return false;\n\n  if (!m_pDecode_tables)\n    m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>();\n\n  if (!m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits()))\n    return false;\n\n  return true;\n}\n\nbool static_huffman_data_model::prepare_decoder_tables() {\n  uint32 total_syms = m_code_sizes.size();\n\n  CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms));\n\n  m_total_syms = total_syms;\n\n  if (!m_pDecode_tables)\n    m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>();\n\n  return m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits());\n}\n\nuint static_huffman_data_model::compute_decoder_table_bits() const {\n#if CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE\n  return prefix_coding::cMaxTableBits;\n#else\n  uint32 decoder_table_bits = 0;\n  if (m_total_syms > 16)\n    decoder_table_bits = static_cast<uint8>(math::minimum(1 + math::ceil_log2i(m_total_syms), prefix_coding::cMaxTableBits));\n  return decoder_table_bits;\n#endif\n}\n\nsymbol_codec::symbol_codec()\n    : m_pDecode_buf(NULL),\n      m_pDecode_buf_next(NULL),\n      m_pDecode_buf_end(NULL),\n      m_decode_buf_size(0),\n      m_bit_buf(0),\n      m_bit_count(0) {\n}\n\n// Code length encoding symbols:\n// 0-16 - actual code lengths\nconst uint32 cMaxCodelengthCodes = 21;\n\nconst uint32 cSmallZeroRunCode = 17;\nconst uint32 cLargeZeroRunCode = 18;\nconst uint32 cSmallRepeatCode = 19;\nconst uint32 cLargeRepeatCode = 20;\n\nconst uint32 cMinSmallZeroRunSize = 3;\nconst uint32 cMaxSmallZeroRunSize = 10;\nconst uint32 cMinLargeZeroRunSize = 11;\nconst uint32 cMaxLargeZeroRunSize = 138;\n\nconst uint32 cSmallMinNonZeroRunSize = 3;\nconst uint32 cSmallMaxNonZeroRunSize = 6;\nconst uint32 cLargeMinNonZeroRunSize = 7;\nconst uint32 cLargeMaxNonZeroRunSize = 70;\n\nconst uint32 cSmallZeroRunExtraBits = 3;\nconst uint32 cLargeZeroRunExtraBits = 7;\nconst uint32 cSmallNonZeroRunExtraBits = 2;\nconst uint32 cLargeNonZeroRunExtraBits = 6;\n\nstatic const uint8 g_most_probable_codelength_codes[] =\n    {\n        cSmallZeroRunCode, cLargeZeroRunCode,\n        cSmallRepeatCode, cLargeRepeatCode,\n\n        0, 8,\n        7, 9,\n        6, 10,\n        5, 11,\n        4, 12,\n        3, 13,\n        2, 14,\n        1, 15,\n        16};\nconst uint32 cNumMostProbableCodelengthCodes = sizeof(g_most_probable_codelength_codes) / sizeof(g_most_probable_codelength_codes[0]);\n\nbool symbol_codec::decode_receive_static_data_model(static_huffman_data_model& model) {\n  const uint32 total_used_syms = decode_bits(math::total_bits(prefix_coding::cMaxSupportedSyms));\n\n  if (!total_used_syms) {\n    model.clear();\n    return true;\n  }\n\n  if (!model.m_code_sizes.resize(total_used_syms))\n    return false;\n\n  memset(&model.m_code_sizes[0], 0, sizeof(model.m_code_sizes[0]) * total_used_syms);\n\n  const uint32 num_codelength_codes_to_send = decode_bits(5);\n  if ((num_codelength_codes_to_send < 1) || (num_codelength_codes_to_send > cMaxCodelengthCodes))\n    return false;\n\n  static_huffman_data_model dm;\n  if (!dm.m_code_sizes.resize(cMaxCodelengthCodes))\n    return false;\n\n  for (uint32 i = 0; i < num_codelength_codes_to_send; i++)\n    dm.m_code_sizes[g_most_probable_codelength_codes[i]] = static_cast<uint8>(decode_bits(3));\n\n  if (!dm.prepare_decoder_tables())\n    return false;\n\n  uint32 ofs = 0;\n  while (ofs < total_used_syms) {\n    const uint32 num_remaining = total_used_syms - ofs;\n\n    uint32 code = decode(dm);\n    if (code <= 16)\n      model.m_code_sizes[ofs++] = static_cast<uint8>(code);\n    else if (code == cSmallZeroRunCode) {\n      uint32 len = decode_bits(cSmallZeroRunExtraBits) + cMinSmallZeroRunSize;\n      if (len > num_remaining)\n        return false;\n      ofs += len;\n    } else if (code == cLargeZeroRunCode) {\n      uint32 len = decode_bits(cLargeZeroRunExtraBits) + cMinLargeZeroRunSize;\n      if (len > num_remaining)\n        return false;\n      ofs += len;\n    } else if ((code == cSmallRepeatCode) || (code == cLargeRepeatCode)) {\n      uint32 len;\n      if (code == cSmallRepeatCode)\n        len = decode_bits(cSmallNonZeroRunExtraBits) + cSmallMinNonZeroRunSize;\n      else\n        len = decode_bits(cLargeNonZeroRunExtraBits) + cLargeMinNonZeroRunSize;\n\n      if ((!ofs) || (len > num_remaining))\n        return false;\n      const uint32 prev = model.m_code_sizes[ofs - 1];\n      if (!prev)\n        return false;\n      const uint32 end = ofs + len;\n      while (ofs < end)\n        model.m_code_sizes[ofs++] = static_cast<uint8>(prev);\n    } else {\n      CRND_ASSERT(0);\n      return false;\n    }\n  }\n\n  if (ofs != total_used_syms)\n    return false;\n\n  return model.prepare_decoder_tables();\n}\n\nbool symbol_codec::start_decoding(const uint8* pBuf, uint32 buf_size) {\n  if (!buf_size)\n    return false;\n\n  m_pDecode_buf = pBuf;\n  m_pDecode_buf_next = pBuf;\n  m_decode_buf_size = buf_size;\n  m_pDecode_buf_end = pBuf + buf_size;\n\n  get_bits_init();\n\n  return true;\n}\n\nvoid symbol_codec::get_bits_init() {\n  m_bit_buf = 0;\n  m_bit_count = 0;\n}\n\nuint32 symbol_codec::decode_bits(uint32 num_bits) {\n  if (!num_bits)\n    return 0;\n\n  if (num_bits > 16) {\n    uint32 a = get_bits(num_bits - 16);\n    uint32 b = get_bits(16);\n\n    return (a << 16) | b;\n  } else\n    return get_bits(num_bits);\n}\n\nuint32 symbol_codec::get_bits(uint32 num_bits) {\n  CRND_ASSERT(num_bits <= 32U);\n\n  while (m_bit_count < (int)num_bits) {\n    bit_buf_type c = 0;\n    if (m_pDecode_buf_next != m_pDecode_buf_end)\n      c = *m_pDecode_buf_next++;\n\n    m_bit_count += 8;\n    CRND_ASSERT(m_bit_count <= cBitBufSize);\n\n    m_bit_buf |= (c << (cBitBufSize - m_bit_count));\n  }\n\n  uint32 result = static_cast<uint32>(m_bit_buf >> (cBitBufSize - num_bits));\n\n  m_bit_buf <<= num_bits;\n  m_bit_count -= num_bits;\n\n  return result;\n}\n\nuint32 symbol_codec::decode(const static_huffman_data_model& model) {\n  const prefix_coding::decoder_tables* pTables = model.m_pDecode_tables;\n\n  if (m_bit_count < 24) {\n    if (m_bit_count < 16) {\n      uint32 c0 = 0, c1 = 0;\n      const uint8* p = m_pDecode_buf_next;\n      if (p < m_pDecode_buf_end)\n        c0 = *p++;\n      if (p < m_pDecode_buf_end)\n        c1 = *p++;\n      m_pDecode_buf_next = p;\n      m_bit_count += 16;\n      uint32 c = (c0 << 8) | c1;\n      m_bit_buf |= (c << (32 - m_bit_count));\n    } else {\n      uint32 c = (m_pDecode_buf_next < m_pDecode_buf_end) ? *m_pDecode_buf_next++ : 0;\n      m_bit_count += 8;\n      m_bit_buf |= (c << (32 - m_bit_count));\n    }\n  }\n\n  uint32 k = (m_bit_buf >> 16) + 1;\n  uint32 sym, len;\n\n  if (k <= pTables->m_table_max_code) {\n    uint32 t = pTables->m_lookup[m_bit_buf >> (32 - pTables->m_table_bits)];\n\n    CRND_ASSERT(t != cUINT32_MAX);\n    sym = t & cUINT16_MAX;\n    len = t >> 16;\n\n    CRND_ASSERT(model.m_code_sizes[sym] == len);\n  } else {\n    len = pTables->m_decode_start_code_size;\n\n    for (;;) {\n      if (k <= pTables->m_max_codes[len - 1])\n        break;\n      len++;\n    }\n\n    int val_ptr = pTables->m_val_ptrs[len - 1] + (m_bit_buf >> (32 - len));\n\n    if (((uint32)val_ptr >= model.m_total_syms)) {\n      // corrupted stream, or a bug\n      CRND_ASSERT(0);\n      return 0;\n    }\n\n    sym = pTables->m_sorted_symbol_order[val_ptr];\n  }\n\n  m_bit_buf <<= len;\n  m_bit_count -= len;\n\n  return sym;\n}\n\nuint64 symbol_codec::stop_decoding() {\n  return static_cast<uint64>(m_pDecode_buf_next - m_pDecode_buf);\n}\n\n}  // namespace unitycrnd\n\n// File: crnd_dxt.cpp\nnamespace unitycrnd {\nconst uint8 g_dxt1_to_linear[cDXT1SelectorValues] = {0U, 3U, 1U, 2U};\nconst uint8 g_dxt1_from_linear[cDXT1SelectorValues] = {0U, 2U, 3U, 1U};\nconst uint8 g_etc1_from_linear[cDXT1SelectorValues] = {3U, 2U, 0U, 1U};\n\nconst uint8 g_dxt5_to_linear[cDXT5SelectorValues] = {0U, 7U, 1U, 2U, 3U, 4U, 5U, 6U};\nconst uint8 g_dxt5_from_linear[cDXT5SelectorValues] = {0U, 2U, 3U, 4U, 5U, 6U, 7U, 1U};\n\nconst uint8 g_six_alpha_invert_table[cDXT5SelectorValues] = {1, 0, 5, 4, 3, 2, 6, 7};\nconst uint8 g_eight_alpha_invert_table[cDXT5SelectorValues] = {1, 0, 7, 6, 5, 4, 3, 2};\n\nuint16 dxt1_block::pack_color(const color_quad_u8& color, bool scaled, uint32 bias) {\n  uint32 r = color.r;\n  uint32 g = color.g;\n  uint32 b = color.b;\n\n  if (scaled) {\n    r = (r * 31U + bias) / 255U;\n    g = (g * 63U + bias) / 255U;\n    b = (b * 31U + bias) / 255U;\n  }\n\n  r = math::minimum(r, 31U);\n  g = math::minimum(g, 63U);\n  b = math::minimum(b, 31U);\n\n  return static_cast<uint16>(b | (g << 5U) | (r << 11U));\n}\n\nuint16 dxt1_block::pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias) {\n  return pack_color(color_quad_u8(r, g, b, 0), scaled, bias);\n}\n\ncolor_quad_u8 dxt1_block::unpack_color(uint16 packed_color, bool scaled, uint32 alpha) {\n  uint32 b = packed_color & 31U;\n  uint32 g = (packed_color >> 5U) & 63U;\n  uint32 r = (packed_color >> 11U) & 31U;\n\n  if (scaled) {\n    b = (b << 3U) | (b >> 2U);\n    g = (g << 2U) | (g >> 4U);\n    r = (r << 3U) | (r >> 2U);\n  }\n\n  return color_quad_u8(r, g, b, alpha);\n}\n\nvoid dxt1_block::unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled) {\n  color_quad_u8 c(unpack_color(packed_color, scaled, 0));\n  r = c.r;\n  g = c.g;\n  b = c.b;\n}\n\nuint32 dxt1_block::get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1) {\n  color_quad_u8 c0(unpack_color(color0, true));\n  color_quad_u8 c1(unpack_color(color1, true));\n\n  pDst[0] = c0;\n  pDst[1] = c1;\n  pDst[2].set((c0.r + c1.r) >> 1U, (c0.g + c1.g) >> 1U, (c0.b + c1.b) >> 1U, 255U);\n  pDst[3].set(0, 0, 0, 0);\n\n  return 3;\n}\n\nuint32 dxt1_block::get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1) {\n  color_quad_u8 c0(unpack_color(color0, true));\n  color_quad_u8 c1(unpack_color(color1, true));\n\n  pDst[0] = c0;\n  pDst[1] = c1;\n\n  // 12/14/09 - Supposed to round according to DX docs, but this conflicts with the OpenGL S3TC spec. ?\n  // Turns out some GPU's round and some don't. Great.\n  //pDst[2].set( (c0.r * 2 + c1.r + 1) / 3, (c0.g * 2 + c1.g + 1) / 3, (c0.b * 2 + c1.b + 1) / 3, 255U);\n  //pDst[3].set( (c1.r * 2 + c0.r + 1) / 3, (c1.g * 2 + c0.g + 1) / 3, (c1.b * 2 + c0.b + 1) / 3, 255U);\n\n  pDst[2].set((c0.r * 2 + c1.r) / 3, (c0.g * 2 + c1.g) / 3, (c0.b * 2 + c1.b) / 3, 255U);\n  pDst[3].set((c1.r * 2 + c0.r) / 3, (c1.g * 2 + c0.g) / 3, (c1.b * 2 + c0.b) / 3, 255U);\n\n  return 4;\n}\n\nuint32 dxt1_block::get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1) {\n  if (color0 > color1)\n    return get_block_colors4(pDst, color0, color1);\n  else\n    return get_block_colors3(pDst, color0, color1);\n}\n\ncolor_quad_u8 dxt1_block::unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha) {\n  CRND_ASSERT(index < 2);\n  return unpack_color(static_cast<uint16>((endpoints >> (index * 16U)) & 0xFFFFU), scaled, alpha);\n}\n\nuint32 dxt1_block::pack_endpoints(uint32 lo, uint32 hi) {\n  CRND_ASSERT((lo <= 0xFFFFU) && (hi <= 0xFFFFU));\n  return lo | (hi << 16U);\n}\n\nvoid dxt3_block::set_alpha(uint32 x, uint32 y, uint32 value, bool scaled) {\n  CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));\n\n  if (scaled) {\n    CRND_ASSERT(value <= 0xFF);\n    value = (value * 15U + 128U) / 255U;\n  } else {\n    CRND_ASSERT(value <= 0xF);\n  }\n\n  uint32 ofs = (y << 1U) + (x >> 1U);\n  uint32 c = m_alpha[ofs];\n\n  c &= ~(0xF << ((x & 1U) << 2U));\n  c |= (value << ((x & 1U) << 2U));\n\n  m_alpha[ofs] = static_cast<uint8>(c);\n}\n\nuint32 dxt3_block::get_alpha(uint32 x, uint32 y, bool scaled) const {\n  CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));\n\n  uint32 value = m_alpha[(y << 1U) + (x >> 1U)];\n  if (x & 1)\n    value >>= 4;\n  value &= 0xF;\n\n  if (scaled)\n    value = (value << 4U) | value;\n\n  return value;\n}\n\nuint32 dxt5_block::get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h) {\n  pDst[0].a = static_cast<uint8>(l);\n  pDst[1].a = static_cast<uint8>(h);\n  pDst[2].a = static_cast<uint8>((l * 4 + h) / 5);\n  pDst[3].a = static_cast<uint8>((l * 3 + h * 2) / 5);\n  pDst[4].a = static_cast<uint8>((l * 2 + h * 3) / 5);\n  pDst[5].a = static_cast<uint8>((l + h * 4) / 5);\n  pDst[6].a = 0;\n  pDst[7].a = 255;\n  return 6;\n}\n\nuint32 dxt5_block::get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h) {\n  pDst[0].a = static_cast<uint8>(l);\n  pDst[1].a = static_cast<uint8>(h);\n  pDst[2].a = static_cast<uint8>((l * 6 + h) / 7);\n  pDst[3].a = static_cast<uint8>((l * 5 + h * 2) / 7);\n  pDst[4].a = static_cast<uint8>((l * 4 + h * 3) / 7);\n  pDst[5].a = static_cast<uint8>((l * 3 + h * 4) / 7);\n  pDst[6].a = static_cast<uint8>((l * 2 + h * 5) / 7);\n  pDst[7].a = static_cast<uint8>((l + h * 6) / 7);\n  return 8;\n}\n\nuint32 dxt5_block::get_block_values(color_quad_u8* pDst, uint32 l, uint32 h) {\n  if (l > h)\n    return get_block_values8(pDst, l, h);\n  else\n    return get_block_values6(pDst, l, h);\n}\n\nuint32 dxt5_block::get_block_values6(uint32* pDst, uint32 l, uint32 h) {\n  pDst[0] = l;\n  pDst[1] = h;\n  pDst[2] = (l * 4 + h) / 5;\n  pDst[3] = (l * 3 + h * 2) / 5;\n  pDst[4] = (l * 2 + h * 3) / 5;\n  pDst[5] = (l + h * 4) / 5;\n  pDst[6] = 0;\n  pDst[7] = 255;\n  return 6;\n}\n\nuint32 dxt5_block::get_block_values8(uint32* pDst, uint32 l, uint32 h) {\n  pDst[0] = l;\n  pDst[1] = h;\n  pDst[2] = (l * 6 + h) / 7;\n  pDst[3] = (l * 5 + h * 2) / 7;\n  pDst[4] = (l * 4 + h * 3) / 7;\n  pDst[5] = (l * 3 + h * 4) / 7;\n  pDst[6] = (l * 2 + h * 5) / 7;\n  pDst[7] = (l + h * 6) / 7;\n  return 8;\n}\n\nuint32 dxt5_block::unpack_endpoint(uint32 packed, uint32 index) {\n  CRND_ASSERT(index < 2);\n  return (packed >> (8 * index)) & 0xFF;\n}\n\nuint32 dxt5_block::pack_endpoints(uint32 lo, uint32 hi) {\n  CRND_ASSERT((lo <= 0xFF) && (hi <= 0xFF));\n  return lo | (hi << 8U);\n}\n\nuint32 dxt5_block::get_block_values(uint32* pDst, uint32 l, uint32 h) {\n  if (l > h)\n    return get_block_values8(pDst, l, h);\n  else\n    return get_block_values6(pDst, l, h);\n}\n\n}  // namespace unitycrnd\n\n// File: crnd_decode.cpp\n\nnamespace unitycrnd {\n\nclass crn_unpacker {\n public:\n  inline crn_unpacker()\n      : m_magic(cMagicValue),\n        m_pData(NULL),\n        m_data_size(0),\n        m_pHeader(NULL) {\n  }\n\n  inline ~crn_unpacker() {\n    m_magic = 0;\n  }\n\n  inline bool is_valid() const { return m_magic == cMagicValue; }\n\n  bool init(const void* pData, uint32 data_size) {\n    m_pHeader = crnd_get_header(pData, data_size);\n    if (!m_pHeader)\n      return false;\n\n    m_pData = static_cast<const uint8*>(pData);\n    m_data_size = data_size;\n\n    if (!init_tables())\n      return false;\n\n    if (!decode_palettes())\n      return false;\n\n    return true;\n  }\n\n  bool unpack_level(\n      void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n      uint32 level_index) {\n    uint32 cur_level_ofs = m_pHeader->m_level_ofs[level_index];\n\n    uint32 next_level_ofs = m_data_size;\n    if ((level_index + 1) < (m_pHeader->m_levels))\n      next_level_ofs = m_pHeader->m_level_ofs[level_index + 1];\n\n    CRND_ASSERT(next_level_ofs > cur_level_ofs);\n\n    return unpack_level(m_pData + cur_level_ofs, next_level_ofs - cur_level_ofs, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);\n  }\n\n  bool unpack_level(\n      const void* pSrc, uint32 src_size_in_bytes,\n      void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n      uint32 level_index) {\n\n#ifdef CRND_BUILD_DEBUG\n    for (uint32 f = 0; f < m_pHeader->m_faces; f++)\n      if (!pDst[f])\n        return false;\n#endif\n\n    const uint32 width = math::maximum(m_pHeader->m_width >> level_index, 1U);\n    const uint32 height = math::maximum(m_pHeader->m_height >> level_index, 1U);\n    const uint32 blocks_x = (width + 3U) >> 2U;\n    const uint32 blocks_y = (height + 3U) >> 2U;\n    const uint32 block_size = m_pHeader->m_format == cCRNFmtDXT1 || m_pHeader->m_format == cCRNFmtDXT5A || m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC1S ? 8 : 16;\n\n    uint32 minimal_row_pitch = block_size * blocks_x;\n    if (!row_pitch_in_bytes)\n      row_pitch_in_bytes = minimal_row_pitch;\n    else if ((row_pitch_in_bytes < minimal_row_pitch) || (row_pitch_in_bytes & 3))\n      return false;\n    if (dst_size_in_bytes < row_pitch_in_bytes * blocks_y)\n      return false;\n\n    if (!m_codec.start_decoding(static_cast<const unitycrnd::uint8*>(pSrc), src_size_in_bytes))\n      return false;\n\n    bool status = false;\n    switch (m_pHeader->m_format) {\n      case cCRNFmtDXT1:\n      case cCRNFmtETC1S:\n        status = unpack_dxt1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);\n        break;\n      case cCRNFmtDXT5:\n      case cCRNFmtDXT5_CCxY:\n      case cCRNFmtDXT5_xGBR:\n      case cCRNFmtDXT5_AGBR:\n      case cCRNFmtDXT5_xGxR:\n      case cCRNFmtETC2AS:\n        status = unpack_dxt5((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);\n        break;\n      case cCRNFmtDXT5A:\n        status = unpack_dxt5a((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);\n        break;\n      case cCRNFmtDXN_XY:\n      case cCRNFmtDXN_YX:\n        status = unpack_dxn((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);\n        break;\n      case cCRNFmtETC1:\n        status = unpack_etc1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);\n        break;\n      case cCRNFmtETC2:\n        status = unpack_etc1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);\n        break;\n      case cCRNFmtETC2A:\n        status = unpack_etc2a((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);\n        break;\n      default:\n        return false;\n    }\n    if (!status)\n      return false;\n\n    m_codec.stop_decoding();\n    return true;\n  }\n\n  inline const void* get_data() const { return m_pData; }\n  inline uint32 get_data_size() const { return m_data_size; }\n\n private:\n  enum { cMagicValue = 0x1EF9CABD };\n  uint32 m_magic;\n\n  const uint8* m_pData;\n  uint32 m_data_size;\n  const crn_header* m_pHeader;\n\n  symbol_codec m_codec;\n\n  static_huffman_data_model m_reference_encoding_dm;\n  static_huffman_data_model m_endpoint_delta_dm[2];\n  static_huffman_data_model m_selector_delta_dm[2];\n\n  unitycrnd::vector<uint32> m_color_endpoints;\n  unitycrnd::vector<uint32> m_color_selectors;\n\n  unitycrnd::vector<uint16> m_alpha_endpoints;\n  unitycrnd::vector<uint16> m_alpha_selectors;\n  \n  struct block_buffer_element {\n    uint16 endpoint_reference;\n    uint16 color_endpoint_index;\n    uint16 alpha0_endpoint_index;\n    uint16 alpha1_endpoint_index;\n  };\n  unitycrnd::vector<block_buffer_element> m_block_buffer;\n\n  bool init_tables() {\n    if (!m_codec.start_decoding(m_pData + m_pHeader->m_tables_ofs, m_pHeader->m_tables_size))\n      return false;\n\n    if (!m_codec.decode_receive_static_data_model(m_reference_encoding_dm))\n      return false;\n\n    if ((!m_pHeader->m_color_endpoints.m_num) && (!m_pHeader->m_alpha_endpoints.m_num))\n      return false;\n\n    if (m_pHeader->m_color_endpoints.m_num) {\n      if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[0]))\n        return false;\n      if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[0]))\n        return false;\n    }\n\n    if (m_pHeader->m_alpha_endpoints.m_num) {\n      if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[1]))\n        return false;\n      if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[1]))\n        return false;\n    }\n\n    m_codec.stop_decoding();\n\n    return true;\n  }\n\n  bool decode_palettes() {\n    if (m_pHeader->m_color_endpoints.m_num) {\n      if (!decode_color_endpoints())\n        return false;\n      if (!decode_color_selectors())\n        return false;\n    }\n\n    if (m_pHeader->m_alpha_endpoints.m_num) {\n      if (!decode_alpha_endpoints())\n        return false;\n      if (!(m_pHeader->m_format == cCRNFmtETC2AS ? decode_alpha_selectors_etcs() : m_pHeader->m_format == cCRNFmtETC2A ? decode_alpha_selectors_etc() : decode_alpha_selectors()))\n        return false;\n    }\n\n    return true;\n  }\n\n  bool decode_color_endpoints() {\n    const uint32 num_color_endpoints = m_pHeader->m_color_endpoints.m_num;\n    const bool has_etc_color_blocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A || m_pHeader->m_format == cCRNFmtETC1S || m_pHeader->m_format == cCRNFmtETC2AS;\n    const bool has_subblocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A;\n\n    if (!m_color_endpoints.resize(num_color_endpoints))\n      return false;\n\n    if (!m_codec.start_decoding(m_pData + m_pHeader->m_color_endpoints.m_ofs, m_pHeader->m_color_endpoints.m_size))\n      return false;\n\n    static_huffman_data_model dm[2];\n    for (uint32 i = 0; i < (has_etc_color_blocks ? 1 : 2); i++)\n      if (!m_codec.decode_receive_static_data_model(dm[i]))\n        return false;\n\n    uint32 a = 0, b = 0, c = 0;\n    uint32 d = 0, e = 0, f = 0;\n\n    uint32* CRND_RESTRICT pDst = &m_color_endpoints[0];\n\n    for (uint32 i = 0; i < num_color_endpoints; i++) {\n      if (has_etc_color_blocks) {\n        for (b = 0; b < 32; b += 8)\n          a += m_codec.decode(dm[0]) << b;\n        a &= 0x1F1F1F1F;\n        *pDst++ = has_subblocks ? a : (a & 0x07000000) << 5 | (a & 0x07000000) << 2 | 0x02000000 | (a & 0x001F1F1F) << 3;\n      } else {\n        a = (a + m_codec.decode(dm[0])) & 31;\n        b = (b + m_codec.decode(dm[1])) & 63;\n        c = (c + m_codec.decode(dm[0])) & 31;\n        d = (d + m_codec.decode(dm[0])) & 31;\n        e = (e + m_codec.decode(dm[1])) & 63;\n        f = (f + m_codec.decode(dm[0])) & 31;\n        *pDst++ = c | (b << 5U) | (a << 11U) | (f << 16U) | (e << 21U) | (d << 27U);\n      }\n    }\n\n    m_codec.stop_decoding();\n\n    return true;\n  }\n\n  bool decode_color_selectors() {\n    const bool has_etc_color_blocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A || m_pHeader->m_format == cCRNFmtETC1S || m_pHeader->m_format == cCRNFmtETC2AS;\n    const bool has_subblocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A;\n    m_codec.start_decoding(m_pData + m_pHeader->m_color_selectors.m_ofs, m_pHeader->m_color_selectors.m_size);\n    static_huffman_data_model dm;\n    m_codec.decode_receive_static_data_model(dm);\n    m_color_selectors.resize(m_pHeader->m_color_selectors.m_num << (has_subblocks ? 1 : 0));\n    for (uint32 s = 0, i = 0; i < m_pHeader->m_color_selectors.m_num; i++) {\n      for (uint32 j = 0; j < 32; j += 4)\n        s ^= m_codec.decode(dm) << j;\n      if (has_etc_color_blocks) {\n        for (uint32 selector = (~s & 0xAAAAAAAA) | (~(s ^ s >> 1) & 0x55555555), t = 8, h = 0; h < 4; h++, t -= 15) {\n          for (uint32 w = 0; w < 4; w++, t += 4) {\n            if (has_subblocks) {\n              uint32 s0 = selector >> (w << 3 | h << 1);\n              m_color_selectors[i << 1] |= ((s0 >> 1 & 1) | (s0 & 1) << 16) << (t & 15);\n            }\n            uint32 s1 = selector >> (h << 3 | w << 1);\n            m_color_selectors[has_subblocks ? i << 1 | 1 : i] |= ((s1 >> 1 & 1) | (s1 & 1) << 16) << (t & 15);\n          }\n        }\n      } else {\n        m_color_selectors[i] = ((s ^ s << 1) & 0xAAAAAAAA) | (s >> 1 & 0x55555555);\n      }\n    }\n    m_codec.stop_decoding();\n    return true;\n  }\n\n  bool decode_alpha_endpoints() {\n    const uint32 num_alpha_endpoints = m_pHeader->m_alpha_endpoints.m_num;\n\n    if (!m_codec.start_decoding(m_pData + m_pHeader->m_alpha_endpoints.m_ofs, m_pHeader->m_alpha_endpoints.m_size))\n      return false;\n\n    static_huffman_data_model dm;\n    if (!m_codec.decode_receive_static_data_model(dm))\n      return false;\n\n    if (!m_alpha_endpoints.resize(num_alpha_endpoints))\n      return false;\n\n    uint16* CRND_RESTRICT pDst = &m_alpha_endpoints[0];\n    uint32 a = 0, b = 0;\n\n    for (uint32 i = 0; i < num_alpha_endpoints; i++) {\n      a = (a + m_codec.decode(dm)) & 255;\n      b = (b + m_codec.decode(dm)) & 255;\n      *pDst++ = (uint16)(a | (b << 8));\n    }\n\n    m_codec.stop_decoding();\n\n    return true;\n  }\n\n  bool decode_alpha_selectors() {\n    m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size);\n    static_huffman_data_model dm;\n    m_codec.decode_receive_static_data_model(dm);\n    m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 3);\n    uint8 dxt5_from_linear[64];\n    for (uint32 i = 0; i < 64; i++)\n      dxt5_from_linear[i] = g_dxt5_from_linear[i & 7] | g_dxt5_from_linear[i >> 3] << 3;\n    for (uint32 s0_linear = 0, s1_linear = 0, i = 0; i < m_alpha_selectors.size();) {\n      uint32 s0 = 0, s1 = 0;\n      for (uint32 j = 0; j < 24; s0 |= dxt5_from_linear[s0_linear >> j & 0x3F] << j, j += 6)\n        s0_linear ^= m_codec.decode(dm) << j;\n      for (uint32 j = 0; j < 24; s1 |= dxt5_from_linear[s1_linear >> j & 0x3F] << j, j += 6)\n        s1_linear ^= m_codec.decode(dm) << j;\n      m_alpha_selectors[i++] = s0;\n      m_alpha_selectors[i++] = s0 >> 16 | s1 << 8;\n      m_alpha_selectors[i++] = s1 >> 8;\n    }\n    m_codec.stop_decoding();\n    return true;\n  }\n\n  bool decode_alpha_selectors_etc() {\n    m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size);\n    static_huffman_data_model dm;\n    m_codec.decode_receive_static_data_model(dm);\n    m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 6);\n    uint8 s_linear[8] = {};\n    uint8* data = (uint8*)m_alpha_selectors.begin();\n    for (uint i = 0; i < m_alpha_selectors.size(); i += 6, data += 12) {\n      for (uint s_group = 0, p = 0; p < 16; p++) {\n        s_group = p & 1 ? s_group >> 3 : s_linear[p >> 1] ^= m_codec.decode(dm);\n        uint8 s = s_group & 7;\n        if (s <= 3)\n          s = 3 - s;\n        uint8 d = 3 * (p + 1);\n        uint8 byte_offset = d >> 3;\n        uint8 bit_offset = d & 7;\n        data[byte_offset] |= s << (8 - bit_offset);\n        if (bit_offset < 3)\n          data[byte_offset - 1] |= s >> bit_offset;\n        d += 9 * ((p & 3) - (p >> 2));\n        byte_offset = d >> 3;\n        bit_offset = d & 7;\n        data[byte_offset + 6] |= s << (8 - bit_offset);\n        if (bit_offset < 3)\n          data[byte_offset + 5] |= s >> bit_offset;\n      }\n    }\n    m_codec.stop_decoding();\n    return true;\n  }\n\n  bool decode_alpha_selectors_etcs() {\n    m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size);\n    static_huffman_data_model dm;\n    m_codec.decode_receive_static_data_model(dm);\n    m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 3);\n    uint8 s_linear[8] = {};\n    uint8* data = (uint8*)m_alpha_selectors.begin();\n    for (uint i = 0; i < (m_alpha_selectors.size() << 1); i += 6) {\n      for (uint s_group = 0, p = 0; p < 16; p++) {\n        s_group = p & 1 ? s_group >> 3 : s_linear[p >> 1] ^= m_codec.decode(dm);\n        uint8 s = s_group & 7;\n        if (s <= 3)\n          s = 3 - s;\n        uint8 d = 3 * (p + 1) + 9 * ((p & 3) - (p >> 2));\n        uint8 byte_offset = d >> 3;\n        uint8 bit_offset = d & 7;\n        data[i + byte_offset] |= s << (8 - bit_offset);\n        if (bit_offset < 3)\n          data[i + byte_offset - 1] |= s >> bit_offset;\n      }\n    }\n    m_codec.stop_decoding();\n    return true;\n  }\n\n  static inline uint32 tiled_offset_2d_outer(uint32 y, uint32 AlignedWidth, uint32 LogBpp) {\n    uint32 Macro = ((y >> 5) * (AlignedWidth >> 5)) << (LogBpp + 7);\n    uint32 Micro = ((y & 6) << 2) << LogBpp;\n\n    return Macro +\n           ((Micro & ~15) << 1) +\n           (Micro & 15) +\n           ((y & 8) << (3 + LogBpp)) + ((y & 1) << 4);\n  }\n\n  static inline uint32 tiled_offset_2d_inner(uint32 x, uint32 y, uint32 LogBpp, uint32 BaseOffset) {\n    uint32 Macro = (x >> 5) << (LogBpp + 7);\n    uint32 Micro = (x & 7) << LogBpp;\n    uint32 Offset = BaseOffset + Macro + ((Micro & ~15) << 1) + (Micro & 15);\n\n    return ((Offset & ~511) << 3) + ((Offset & 448) << 2) + (Offset & 63) +\n           ((y & 16) << 7) +\n           (((((y & 8) >> 2) + (x >> 3)) & 3) << 6);\n  }\n\n  static inline void limit(uint& x, uint n) {\n    int v = x - n;\n    int msk = (v >> 31);\n    x = (x & msk) | (v & ~msk);\n  }\n\n  bool unpack_dxt1(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) {\n    const uint32 num_color_endpoints = m_color_endpoints.size();\n    const uint32 width = output_width + 1 & ~1;\n    const uint32 height = output_height + 1 & ~1;\n    const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 1);\n\n    if (m_block_buffer.size() < width)\n      m_block_buffer.resize(width);\n\n    uint32 color_endpoint_index = 0;\n    uint8 reference_group = 0;\n\n    for (uint32 f = 0; f < m_pHeader->m_faces; f++) {\n      uint32* pData = (uint32*)pDst[f];\n      for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {\n        bool visible = y < output_height;\n        for (uint32 x = 0; x < width; x++, pData += 2) {\n          visible = visible && x < output_width;\n          if (!(y & 1) && !(x & 1))\n            reference_group = m_codec.decode(m_reference_encoding_dm);\n          block_buffer_element &buffer = m_block_buffer[x];\n          uint8 endpoint_reference;\n          if (y & 1) {\n            endpoint_reference = buffer.endpoint_reference;\n          } else {\n            endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n            buffer.endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n          }\n          if (!endpoint_reference) {\n            color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);\n            if (color_endpoint_index >= num_color_endpoints)\n              color_endpoint_index -= num_color_endpoints;\n            buffer.color_endpoint_index = color_endpoint_index;\n          } else if (endpoint_reference == 1) {\n            buffer.color_endpoint_index = color_endpoint_index;\n          } else {\n            color_endpoint_index = buffer.color_endpoint_index;\n          }\n          uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]);\n          if (visible) {\n            pData[0] = m_color_endpoints[color_endpoint_index];\n            pData[1] = m_color_selectors[color_selector_index];\n          }\n        }\n      }\n    }\n    return true;\n  }\n\n  bool unpack_dxt5(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) {\n    const uint32 num_color_endpoints = m_color_endpoints.size();\n    const uint32 num_alpha_endpoints = m_alpha_endpoints.size();\n    const uint32 width = output_width + 1 & ~1;\n    const uint32 height = output_height + 1 & ~1;\n    const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 2);\n\n    if (m_block_buffer.size() < width)\n      m_block_buffer.resize(width);\n\n    uint32 color_endpoint_index = 0;\n    uint32 alpha0_endpoint_index = 0;\n    uint8 reference_group = 0;\n\n    for (uint32 f = 0; f < m_pHeader->m_faces; f++) {\n      uint32* pData = (uint32*)pDst[f];\n      for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {\n        bool visible = y < output_height;\n        for (uint32 x = 0; x < width; x++, pData += 4) {\n          visible = visible && x < output_width;\n          if (!(y & 1) && !(x & 1))\n            reference_group = m_codec.decode(m_reference_encoding_dm);\n          block_buffer_element &buffer = m_block_buffer[x];\n          uint8 endpoint_reference;\n          if (y & 1) {\n            endpoint_reference = buffer.endpoint_reference;\n          } else {\n            endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n            buffer.endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n          }\n          if (!endpoint_reference) {\n            color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);\n            if (color_endpoint_index >= num_color_endpoints)\n              color_endpoint_index -= num_color_endpoints;\n            buffer.color_endpoint_index = color_endpoint_index;\n            alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);\n            if (alpha0_endpoint_index >= num_alpha_endpoints)\n              alpha0_endpoint_index -= num_alpha_endpoints;\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n          } else if (endpoint_reference == 1) {\n            buffer.color_endpoint_index = color_endpoint_index;\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n          } else {\n            color_endpoint_index = buffer.color_endpoint_index;\n            alpha0_endpoint_index = buffer.alpha0_endpoint_index;\n          }\n          uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]);\n          uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);\n          if (visible) {\n            const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3];\n            pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16);\n            pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);\n            pData[2] = m_color_endpoints[color_endpoint_index];\n            pData[3] = m_color_selectors[color_selector_index];\n          }\n        }\n      }\n    }\n    return true;\n  }\n\n  bool unpack_dxn(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) {\n    const uint32 num_alpha_endpoints = m_alpha_endpoints.size();\n    const uint32 width = output_width + 1 & ~1;\n    const uint32 height = output_height + 1 & ~1;\n    const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 2);\n\n    if (m_block_buffer.size() < width)\n      m_block_buffer.resize(width);\n\n    uint32 alpha0_endpoint_index = 0;\n    uint32 alpha1_endpoint_index = 0;\n    uint8 reference_group = 0;\n\n    for (uint32 f = 0; f < m_pHeader->m_faces; f++) {\n      uint32* pData = (uint32*)pDst[f];\n      for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {\n        bool visible = y < output_height;\n        for (uint32 x = 0; x < width; x++, pData += 4) {\n          visible = visible && x < output_width;\n          if (!(y & 1) && !(x & 1))\n            reference_group = m_codec.decode(m_reference_encoding_dm);\n          block_buffer_element &buffer = m_block_buffer[x];\n          uint8 endpoint_reference;\n          if (y & 1) {\n            endpoint_reference = buffer.endpoint_reference;\n          } else {\n            endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n            buffer.endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n          }\n          if (!endpoint_reference) {\n            alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);\n            if (alpha0_endpoint_index >= num_alpha_endpoints)\n              alpha0_endpoint_index -= num_alpha_endpoints;\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n            alpha1_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);\n            if (alpha1_endpoint_index >= num_alpha_endpoints)\n              alpha1_endpoint_index -= num_alpha_endpoints;\n            buffer.alpha1_endpoint_index = alpha1_endpoint_index;\n          } else if (endpoint_reference == 1) {\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n            buffer.alpha1_endpoint_index = alpha1_endpoint_index;\n          } else {\n            alpha0_endpoint_index = buffer.alpha0_endpoint_index;\n            alpha1_endpoint_index = buffer.alpha1_endpoint_index;\n          }\n          uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);\n          uint32 alpha1_selector_index = m_codec.decode(m_selector_delta_dm[1]);\n          if (visible) {\n            const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3];\n            const uint16* pAlpha1_selectors = &m_alpha_selectors[alpha1_selector_index * 3];\n            pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16);\n            pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);\n            pData[2] = m_alpha_endpoints[alpha1_endpoint_index] | (pAlpha1_selectors[0] << 16);\n            pData[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16);\n          }\n        }\n      }\n    }\n    return true;\n  }\n\n  bool unpack_dxt5a(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) {\n    const uint32 num_alpha_endpoints = m_alpha_endpoints.size();\n    const uint32 width = output_width + 1 & ~1;\n    const uint32 height = output_height + 1 & ~1;\n    const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 1);\n\n    if (m_block_buffer.size() < width)\n      m_block_buffer.resize(width);\n\n    uint32 alpha0_endpoint_index = 0;\n    uint8 reference_group = 0;\n\n    for (uint32 f = 0; f < m_pHeader->m_faces; f++) {\n      uint32* pData = (uint32*)pDst[f];\n      for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {\n        bool visible = y < output_height;\n        for (uint32 x = 0; x < width; x++, pData += 2) {\n          visible = visible && x < output_width;\n          if (!(y & 1) && !(x & 1))\n            reference_group = m_codec.decode(m_reference_encoding_dm);\n          block_buffer_element &buffer = m_block_buffer[x];\n          uint8 endpoint_reference;\n          if (y & 1) {\n            endpoint_reference = buffer.endpoint_reference;\n          } else {\n            endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n            buffer.endpoint_reference = reference_group & 3;\n            reference_group >>= 2;\n          }\n          if (!endpoint_reference) {\n            alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);\n            if (alpha0_endpoint_index >= num_alpha_endpoints)\n              alpha0_endpoint_index -= num_alpha_endpoints;\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n          } else if (endpoint_reference == 1) {\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n          } else {\n            alpha0_endpoint_index = buffer.alpha0_endpoint_index;\n          }\n          uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);\n          if (visible) {\n            const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3];\n            pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16);\n            pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);\n          }\n        }\n      }\n    }\n    return true;\n  }\n\n  bool unpack_etc1(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) {\n    const uint32 num_color_endpoints = m_color_endpoints.size();\n    const uint32 width = output_width + 1 & ~1;\n    const uint32 height = output_height + 1 & ~1;\n    const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 1);\n\n    if (m_block_buffer.size() < width << 1)\n      m_block_buffer.resize(width << 1);\n\n    uint32 color_endpoint_index = 0, diagonal_color_endpoint_index = 0;\n    uint8 reference_group = 0;\n\n    for (uint32 f = 0; f < m_pHeader->m_faces; f++) {\n      uint32* pData = (uint32*)pDst[f];\n      for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {\n        bool visible = y < output_height;\n        for (uint32 x = 0; x < width; x++, pData += 2) {\n          visible = visible && x < output_width;\n          block_buffer_element &buffer = m_block_buffer[x << 1];\n          uint8 endpoint_reference, block_endpoint[4], e0[4], e1[4];\n          if (y & 1) {\n            endpoint_reference = buffer.endpoint_reference;\n          } else {\n            reference_group = m_codec.decode(m_reference_encoding_dm);\n            endpoint_reference = (reference_group & 3) | (reference_group >> 2 & 12);\n            buffer.endpoint_reference = (reference_group >> 2 & 3) | (reference_group >> 4 & 12);\n          }\n          if (!(endpoint_reference & 3)) {\n            color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);\n            if (color_endpoint_index >= num_color_endpoints)\n              color_endpoint_index -= num_color_endpoints;\n            buffer.color_endpoint_index = color_endpoint_index;\n          } else if ((endpoint_reference & 3) == 1) {\n            buffer.color_endpoint_index = color_endpoint_index;\n          } else if ((endpoint_reference & 3) == 3) {\n            buffer.color_endpoint_index = color_endpoint_index = diagonal_color_endpoint_index;\n          } else {\n            color_endpoint_index = buffer.color_endpoint_index;\n          }\n          endpoint_reference >>= 2;\n          *(uint32*)&e0 = m_color_endpoints[color_endpoint_index];\n          uint32 selector_index = m_codec.decode(m_selector_delta_dm[0]);\n          if (endpoint_reference) {\n            color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);\n            if (color_endpoint_index >= num_color_endpoints)\n              color_endpoint_index -= num_color_endpoints;\n          }\n          diagonal_color_endpoint_index = m_block_buffer[x << 1 | 1].color_endpoint_index;\n          m_block_buffer[x << 1 | 1].color_endpoint_index = color_endpoint_index;\n          *(uint32*)&e1 = m_color_endpoints[color_endpoint_index];\n          if (visible) {\n            uint32 flip = endpoint_reference >> 1 ^ 1, diff = 1;\n            for (uint c = 0; diff && c < 3; c++)\n              diff = e0[c] + 3 >= e1[c] && e1[c] + 4 >= e0[c] ? diff : 0;\n            for (uint c = 0; c < 3; c++)\n              block_endpoint[c] = diff ? e0[c] << 3 | ((e1[c] - e0[c]) & 7) : (e0[c] << 3 & 0xF0) | e1[c] >> 1;\n            block_endpoint[3] = e0[3] << 5 | e1[3] << 2 | diff << 1 | flip;\n            pData[0] = *(uint32*)&block_endpoint;\n            pData[1] = m_color_selectors[selector_index << 1 | flip];\n          }\n        }\n      }\n    }\n    return true;\n  }\n\n  bool unpack_etc2a(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) {\n    const uint32 num_color_endpoints = m_color_endpoints.size();\n    const uint32 num_alpha_endpoints = m_alpha_endpoints.size();\n    const uint32 width = output_width + 1 & ~1;\n    const uint32 height = output_height + 1 & ~1;\n    const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 2);\n\n    if (m_block_buffer.size() < width << 1)\n      m_block_buffer.resize(width << 1);\n\n    uint32 color_endpoint_index = 0, diagonal_color_endpoint_index = 0, alpha0_endpoint_index = 0, diagonal_alpha0_endpoint_index = 0;\n    uint8 reference_group = 0;\n\n    for (uint32 f = 0; f < m_pHeader->m_faces; f++) {\n      uint32* pData = (uint32*)pDst[f];\n      for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {\n        bool visible = y < output_height;\n        for (uint32 x = 0; x < width; x++, pData += 4) {\n          visible = visible && x < output_width;\n          block_buffer_element &buffer = m_block_buffer[x << 1];\n          uint8 endpoint_reference, block_endpoint[4], e0[4], e1[4];\n          if (y & 1) {\n            endpoint_reference = buffer.endpoint_reference;\n          } else {\n            reference_group = m_codec.decode(m_reference_encoding_dm);\n            endpoint_reference = (reference_group & 3) | (reference_group >> 2 & 12);\n            buffer.endpoint_reference = (reference_group >> 2 & 3) | (reference_group >> 4 & 12);\n          }\n          if (!(endpoint_reference & 3)) {\n            color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);\n            if (color_endpoint_index >= num_color_endpoints)\n              color_endpoint_index -= num_color_endpoints;\n            alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);\n            if (alpha0_endpoint_index >= num_alpha_endpoints)\n              alpha0_endpoint_index -= num_alpha_endpoints;\n            buffer.color_endpoint_index = color_endpoint_index;\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n          } else if ((endpoint_reference & 3) == 1) {\n            buffer.color_endpoint_index = color_endpoint_index;\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index;\n          } else if ((endpoint_reference & 3) == 3) {\n            buffer.color_endpoint_index = color_endpoint_index = diagonal_color_endpoint_index;\n            buffer.alpha0_endpoint_index = alpha0_endpoint_index = diagonal_alpha0_endpoint_index;\n          } else {\n            color_endpoint_index = buffer.color_endpoint_index;\n            alpha0_endpoint_index = buffer.alpha0_endpoint_index;\n          }\n          endpoint_reference >>= 2;\n          *(uint32*)&e0 = m_color_endpoints[color_endpoint_index];\n          uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]);\n          uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);\n          if (endpoint_reference) {\n            color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);\n            if (color_endpoint_index >= num_color_endpoints)\n              color_endpoint_index -= num_color_endpoints;\n          }\n          *(uint32*)&e1 = m_color_endpoints[color_endpoint_index];\n          diagonal_color_endpoint_index = m_block_buffer[x << 1 | 1].color_endpoint_index;\n          diagonal_alpha0_endpoint_index = m_block_buffer[x << 1 | 1].alpha0_endpoint_index;\n          m_block_buffer[x << 1 | 1].color_endpoint_index = color_endpoint_index;\n          m_block_buffer[x << 1 | 1].alpha0_endpoint_index = alpha0_endpoint_index;\n          if (visible) {\n            uint32 flip = endpoint_reference >> 1 ^ 1, diff = 1;\n            for (uint c = 0; diff && c < 3; c++)\n              diff = e0[c] + 3 >= e1[c] && e1[c] + 4 >= e0[c] ? diff : 0;\n            for (uint c = 0; c < 3; c++)\n              block_endpoint[c] = diff ? e0[c] << 3 | ((e1[c] - e0[c]) & 7) : (e0[c] << 3 & 0xF0) | e1[c] >> 1;\n            block_endpoint[3] = e0[3] << 5 | e1[3] << 2 | diff << 1 | flip;\n            const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 6 + (flip ? 3 : 0)];\n            pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | pAlpha0_selectors[0] << 16;\n            pData[1] = pAlpha0_selectors[1] | pAlpha0_selectors[2] << 16;\n            pData[2] = *(uint32*)&block_endpoint;\n            pData[3] = m_color_selectors[color_selector_index << 1 | flip];\n          }\n        }\n      }\n    }\n    return true;\n  }\n\n};\n\ncrnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size) {\n  if ((!pData) || (data_size < cCRNHeaderMinSize))\n    return NULL;\n\n  crn_unpacker* p = crnd_new<crn_unpacker>();\n  if (!p)\n    return NULL;\n\n  if (!p->init(pData, data_size)) {\n    crnd_delete(p);\n    return NULL;\n  }\n\n  return p;\n}\n\nbool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size) {\n  if (!pContext)\n    return false;\n\n  crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n  if (!pUnpacker->is_valid())\n    return false;\n\n  if (ppData)\n    *ppData = pUnpacker->get_data();\n\n  if (pData_size)\n    *pData_size = pUnpacker->get_data_size();\n\n  return true;\n}\n\nbool crnd_unpack_level(\n    crnd_unpack_context pContext,\n    void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n    uint32 level_index) {\n  if ((!pContext) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels))\n    return false;\n\n  crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n  if (!pUnpacker->is_valid())\n    return false;\n\n  return pUnpacker->unpack_level(pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);\n}\n\nbool crnd_unpack_level_segmented(\n    crnd_unpack_context pContext,\n    const void* pSrc, uint32 src_size_in_bytes,\n    void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n    uint32 level_index) {\n  if ((!pContext) || (!pSrc) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels))\n    return false;\n\n  crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n  if (!pUnpacker->is_valid())\n    return false;\n\n  return pUnpacker->unpack_level(pSrc, src_size_in_bytes, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);\n}\n\nbool crnd_unpack_end(crnd_unpack_context pContext) {\n  if (!pContext)\n    return false;\n\n  crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);\n\n  if (!pUnpacker->is_valid())\n    return false;\n\n  crnd_delete(pUnpacker);\n\n  return true;\n}\n\n}  // namespace unitycrnd\n\n#endif  // CRND_INCLUDE_CRND_H\n\n//------------------------------------------------------------------------------\n//\n// crn_decomp.h uses the ZLIB license:\n// http://opensource.org/licenses/Zlib\n//\n// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC\n//\n// This software is provided 'as-is', without any express or implied\n// warranty.  In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n//\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n//\n// 3. This notice may not be removed or altered from any source distribution.\n//\n//------------------------------------------------------------------------------\n"
  },
  {
    "path": "Texture2DDecoderNative/unitycrunch/crn_defs.h",
    "content": "#ifndef CRND_INCLUDE_CRN_DEFS_H\n#define CRND_INCLUDE_CRN_DEFS_H\n\n// Include crnlib.h (only to bring in some basic CRN-related types).\n#include \"crnlib.h\"\n\n#define CRND_LIB_VERSION 104\n#define CRND_VERSION_STRING \"01.04\"\n\n#ifdef _DEBUG\n#define CRND_BUILD_DEBUG\n#else\n#define CRND_BUILD_RELEASE\n#endif\n\n// CRN decompression API\nnamespace unitycrnd {\ntypedef unsigned char uint8;\ntypedef signed char int8;\ntypedef unsigned short uint16;\ntypedef signed short int16;\ntypedef unsigned int uint32;\ntypedef uint32 uint32;\ntypedef unsigned int uint;\ntypedef signed int int32;\n#ifdef __GNUC__\ntypedef unsigned long long uint64;\ntypedef long long int64;\n#else\ntypedef unsigned __int64 uint64;\ntypedef signed __int64 int64;\n#endif\n\n// The crnd library assumes all allocation blocks have at least CRND_MIN_ALLOC_ALIGNMENT alignment.\nconst uint32 CRND_MIN_ALLOC_ALIGNMENT = sizeof(uint32) * 2U;\n\n// realloc callback:\n// Used to allocate, resize, or free memory blocks.\n// If p is NULL, the realloc function attempts to allocate a block of at least size bytes. Returns NULL on out of memory.\n// *pActual_size must be set to the actual size of the allocated block, which must be greater than or equal to the requested size.\n// If p is not NULL, and size is 0, the realloc function frees the specified block, and always returns NULL. *pActual_size should be set to 0.\n// If p is not NULL, and size is non-zero, the realloc function attempts to resize the specified block:\n//    If movable is false, the realloc function attempts to shrink or expand the block in-place. NULL is returned if the block cannot be resized in place, or if the\n//    underlying heap implementation doesn't support in-place resizing. Otherwise, the pointer to the original block is returned.\n//    If movable is true, it is permissible to move the block's contents if it cannot be resized in place. NULL is returned if the block cannot be resized in place, and there\n//    is not enough memory to relocate the block.\n//    In all cases, *pActual_size must be set to the actual size of the allocated block, whether it was successfully resized or not.\ntypedef void* (*crnd_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data);\n\n// msize callback: Returns the size of the memory block in bytes, or 0 if the pointer or block is invalid.\ntypedef size_t (*crnd_msize_func)(void* p, void* pUser_data);\n\n// crnd_set_memory_callbacks() - Use to override the crnd library's memory allocation functions.\n// If any input parameters are NULL, the memory callback functions are reset to the default functions.\n// The default functions call malloc(), free(),  _msize(), _expand(), etc.\nvoid crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data);\n\nstruct crn_file_info {\n  inline crn_file_info()\n      : m_struct_size(sizeof(crn_file_info)) {}\n\n  uint32 m_struct_size;\n  uint32 m_actual_data_size;\n  uint32 m_header_size;\n  uint32 m_total_palette_size;\n  uint32 m_tables_size;\n  uint32 m_levels;\n  uint32 m_level_compressed_size[cCRNMaxLevels];\n  uint32 m_color_endpoint_palette_entries;\n  uint32 m_color_selector_palette_entries;\n  uint32 m_alpha_endpoint_palette_entries;\n  uint32 m_alpha_selector_palette_entries;\n};\n\nstruct crn_texture_info {\n  inline crn_texture_info()\n      : m_struct_size(sizeof(crn_texture_info)) {}\n\n  uint32 m_struct_size;\n  uint32 m_width;\n  uint32 m_height;\n  uint32 m_levels;\n  uint32 m_faces;\n  uint32 m_bytes_per_block;\n  uint32 m_userdata0;\n  uint32 m_userdata1;\n  crn_format m_format;\n};\n\nstruct crn_level_info {\n  inline crn_level_info()\n      : m_struct_size(sizeof(crn_level_info)) {}\n\n  uint32 m_struct_size;\n  uint32 m_width;\n  uint32 m_height;\n  uint32 m_faces;\n  uint32 m_blocks_x;\n  uint32 m_blocks_y;\n  uint32 m_bytes_per_block;\n  crn_format m_format;\n};\n\n// Returns the FOURCC format code corresponding to the specified CRN format.\nuint32 crnd_crn_format_to_fourcc(crn_format fmt);\n\n// Returns the fundamental GPU format given a potentially swizzled DXT5 crn_format.\ncrn_format crnd_get_fundamental_dxt_format(crn_format fmt);\n\n// Returns the size of the crn_format in bits/texel (either 4 or 8).\nuint32 crnd_get_crn_format_bits_per_texel(crn_format fmt);\n\n// Returns the number of bytes per DXTn block (8 or 16).\nuint32 crnd_get_bytes_per_dxt_block(crn_format fmt);\n\n// Validates the entire file by checking the header and data CRC's.\n// This is not something you want to be doing much!\n// The crn_file_info.m_struct_size field must be set before calling this function.\nbool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info);\n\n// Retrieves texture information from the CRN file.\n// The crn_texture_info.m_struct_size field must be set before calling this function.\nbool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pTexture_info);\n\n// Retrieves mipmap level specific information from the CRN file.\n// The crn_level_info.m_struct_size field must be set before calling this function.\nbool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info);\n\n// Transcode/unpack context handle.\ntypedef void* crnd_unpack_context;\n\n// crnd_unpack_begin() - Decompresses the texture's decoder tables and endpoint/selector palettes.\n// Once you call this function, you may call crnd_unpack_level() to unpack one or more mip levels.\n// Don't call this once per mip level (unless you absolutely must)!\n// This function allocates enough memory to hold: Huffman decompression tables, and the endpoint/selector palettes (color and/or alpha).\n// Worst case allocation is approx. 200k, assuming all palettes contain 8192 entries.\n// pData must point to a buffer holding all of the compressed .CRN file data.\n// This buffer must be stable until crnd_unpack_end() is called.\n// Returns NULL if out of memory, or if any of the input parameters are invalid.\ncrnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size);\n\n// Returns a pointer to the compressed .CRN data associated with a crnd_unpack_context.\n// Returns false if any of the input parameters are invalid.\nbool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size);\n\n// crnd_unpack_level() - Transcodes the specified mipmap level to a destination buffer in cached or write combined memory.\n// pContext - Context created by a call to crnd_unpack_begin().\n// ppDst - A pointer to an array of 1 or 6 destination buffer pointers. Cubemaps require an array of 6 pointers, 2D textures require an array of 1 pointer.\n// dst_size_in_bytes - Optional size of each destination buffer. Only used for debugging - OK to set to UINT32_MAX.\n// row_pitch_in_bytes - The pitch in bytes from one row of DXT blocks to the next. Must be a multiple of 4.\n// level_index - mipmap level index, where 0 is the largest/first level.\n// Returns false if any of the input parameters, or the compressed stream, are invalid.\n// This function does not allocate any memory.\nbool crnd_unpack_level(\n    crnd_unpack_context pContext,\n    void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n    uint32 level_index);\n\n// crnd_unpack_level_segmented() - Unpacks the specified mipmap level from a \"segmented\" CRN file.\n// See the crnd_create_segmented_file() API below.\n// Segmented files allow the user to control where the compressed mipmap data is stored.\nbool crnd_unpack_level_segmented(\n    crnd_unpack_context pContext,\n    const void* pSrc, uint32 src_size_in_bytes,\n    void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,\n    uint32 level_index);\n\n// crnd_unpack_end() - Frees the decompress tables and unpacked palettes associated with the specified unpack context.\n// Returns false if the context is NULL, or if it points to an invalid context.\n// This function frees all memory associated with the context.\nbool crnd_unpack_end(crnd_unpack_context pContext);\n\n// The following API's allow the user to create \"segmented\" CRN files. A segmented file contains multiple pieces:\n// - Base data: Header + compression tables\n// - Level data: Individual mipmap levels\n// This allows mipmap levels from multiple CRN files to be tightly packed together into single files.\n\n// Returns a pointer to the level's compressed data, and optionally returns the level's compressed data size if pSize is not NULL.\nconst void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize);\n\n// Returns the compressed size of the texture's header and compression tables (but no levels).\nuint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size);\n\n// Creates a \"segmented\" CRN texture from a normal CRN texture. The new texture will be created at pBase_data, and will be crnd_get_base_data_size() bytes long.\n// base_data_size must be >= crnd_get_base_data_size().\n// The base data will contain the CRN header and compression tables, but no mipmap data.\nbool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size);\n\n}  // namespace unitycrnd\n\n// Low-level CRN file header cracking.\nnamespace unitycrnd {\ntemplate <unsigned int N>\nstruct crn_packed_uint {\n  inline crn_packed_uint() {}\n\n  inline crn_packed_uint(unsigned int val) { *this = val; }\n\n  inline crn_packed_uint(const crn_packed_uint& other) { *this = other; }\n\n  inline crn_packed_uint& operator=(const crn_packed_uint& rhs) {\n    if (this != &rhs)\n      memcpy(m_buf, rhs.m_buf, sizeof(m_buf));\n    return *this;\n  }\n\n  inline crn_packed_uint& operator=(unsigned int val) {\n    //CRND_ASSERT((N == 4U) || (val < (1U << (N * 8U))));\n\n    val <<= (8U * (4U - N));\n\n    for (unsigned int i = 0; i < N; i++) {\n      m_buf[i] = static_cast<unsigned char>(val >> 24U);\n      val <<= 8U;\n    }\n\n    return *this;\n  }\n\n  inline operator unsigned int() const {\n    switch (N) {\n      case 1:\n        return m_buf[0];\n      case 2:\n        return (m_buf[0] << 8U) | m_buf[1];\n      case 3:\n        return (m_buf[0] << 16U) | (m_buf[1] << 8U) | (m_buf[2]);\n      default:\n        return (m_buf[0] << 24U) | (m_buf[1] << 16U) | (m_buf[2] << 8U) | (m_buf[3]);\n    }\n  }\n\n  unsigned char m_buf[N];\n};\n\n#pragma pack(push)\n#pragma pack(1)\nstruct crn_palette {\n  crn_packed_uint<3> m_ofs;\n  crn_packed_uint<3> m_size;\n  crn_packed_uint<2> m_num;\n};\n\nenum crn_header_flags {\n  // If set, the compressed mipmap level data is not located after the file's base data - it will be separately managed by the user instead.\n  cCRNHeaderFlagSegmented = 1\n};\n\nstruct crn_header {\n  enum { cCRNSigValue = ('H' << 8) | 'x' };\n\n  crn_packed_uint<2> m_sig;\n  crn_packed_uint<2> m_header_size;\n  crn_packed_uint<2> m_header_crc16;\n\n  crn_packed_uint<4> m_data_size;\n  crn_packed_uint<2> m_data_crc16;\n\n  crn_packed_uint<2> m_width;\n  crn_packed_uint<2> m_height;\n\n  crn_packed_uint<1> m_levels;\n  crn_packed_uint<1> m_faces;\n\n  crn_packed_uint<1> m_format;\n  crn_packed_uint<2> m_flags;\n\n  crn_packed_uint<4> m_reserved;\n  crn_packed_uint<4> m_userdata0;\n  crn_packed_uint<4> m_userdata1;\n\n  crn_palette m_color_endpoints;\n  crn_palette m_color_selectors;\n\n  crn_palette m_alpha_endpoints;\n  crn_palette m_alpha_selectors;\n\n  crn_packed_uint<2> m_tables_size;\n  crn_packed_uint<3> m_tables_ofs;\n\n  // m_level_ofs[] is actually an array of offsets: m_level_ofs[m_levels]\n  crn_packed_uint<4> m_level_ofs[1];\n};\n\nconst unsigned int cCRNHeaderMinSize = 62U;\n\n#pragma pack(pop)\n\n}  // namespace unitycrnd\n\n#endif  // CRND_INCLUDE_CRN_DEFS_H\n"
  },
  {
    "path": "Texture2DDecoderNative/unitycrunch/crnlib.h",
    "content": "// File: crnlib.h - Advanced DXTn texture compression library.\n// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC\n// See copyright notice and license at the end of this file.\n//\n// This header file contains the public crnlib declarations for DXTn,\n// clustered DXTn, and CRN compression/decompression.\n//\n// Note: This library does NOT need to be linked into your game executable if\n// all you want to do is transcode .CRN files to raw DXTn bits at run-time.\n// The crn_decomp.h header file library contains all the code necessary for\n// decompression.\n//\n// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing\n#ifndef CRNLIB_H\n#define CRNLIB_H\n\n#ifdef _MSC_VER\n#pragma warning(disable : 4127)  //  conditional expression is constant\n#endif\n\n#define CRNLIB_VERSION 104\n\n#define CRNLIB_SUPPORT_ATI_COMPRESS 0\n#define CRNLIB_SUPPORT_SQUISH 0\n\ntypedef unsigned char crn_uint8;\ntypedef unsigned short crn_uint16;\ntypedef unsigned int crn_uint32;\ntypedef signed char crn_int8;\ntypedef signed short crn_int16;\ntypedef signed int crn_int32;\ntypedef unsigned int crn_bool;\n\n// crnlib can compress to these file types.\nenum crn_file_type {\n  // .CRN\n  cCRNFileTypeCRN = 0,\n\n  // .DDS using regular DXT or clustered DXT\n  cCRNFileTypeDDS,\n\n  cCRNFileTypeForceDWORD = 0xFFFFFFFF\n};\n\n// Supported compressed pixel formats.\n// Basically all the standard DX9 formats, with some swizzled DXT5 formats\n// (most of them supported by ATI's Compressonator), along with some ATI/X360 GPU specific formats.\nenum crn_format {\n  cCRNFmtInvalid = -1,\n\n  cCRNFmtDXT1 = 0,\n\n  cCRNFmtFirstValid = cCRNFmtDXT1,\n\n  // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS.\n  cCRNFmtDXT3,\n\n  cCRNFmtDXT5,\n\n  // Various DXT5 derivatives\n  cCRNFmtDXT5_CCxY,  // Luma-chroma\n  cCRNFmtDXT5_xGxR,  // Swizzled 2-component\n  cCRNFmtDXT5_xGBR,  // Swizzled 3-component\n  cCRNFmtDXT5_AGBR,  // Swizzled 4-component\n\n  // ATI 3DC and X360 DXN\n  cCRNFmtDXN_XY,\n  cCRNFmtDXN_YX,\n\n  // DXT5 alpha blocks only\n  cCRNFmtDXT5A,\n\n  cCRNFmtETC1,\n  cCRNFmtETC2,\n  cCRNFmtETC2A,\n  cCRNFmtETC1S,\n  cCRNFmtETC2AS,\n\n  cCRNFmtTotal,\n\n  cCRNFmtForceDWORD = 0xFFFFFFFF\n};\n\n// Various library/file format limits.\nenum crn_limits {\n  // Max. mipmap level resolution on any axis.\n  cCRNMaxLevelResolution = 4096,\n\n  cCRNMinPaletteSize = 8,\n  cCRNMaxPaletteSize = 8192,\n\n  cCRNMaxFaces = 6,\n  cCRNMaxLevels = 16,\n\n  cCRNMaxHelperThreads = 15,\n\n  cCRNMinQualityLevel = 0,\n  cCRNMaxQualityLevel = 255\n};\n\n// CRN/DDS compression flags.\n// See the m_flags member in the crn_comp_params struct, below.\nenum crn_comp_flags {\n  // Enables perceptual colorspace distance metrics if set.\n  // Important: Be sure to disable this when compressing non-sRGB colorspace images, like normal maps!\n  // Default: Set\n  cCRNCompFlagPerceptual = 1,\n\n  // Enables (up to) 8x8 macroblock usage if set. If disabled, only 4x4 blocks are allowed.\n  // Compression ratio will be lower when disabled, but may cut down on blocky artifacts because the process used to determine\n  // where large macroblocks can be used without artifacts isn't perfect.\n  // Default: Set.\n  cCRNCompFlagHierarchical = 2,\n\n  // cCRNCompFlagQuick disables several output file optimizations - intended for things like quicker previews.\n  // Default: Not set.\n  cCRNCompFlagQuick = 4,\n\n  // DXT1: OK to use DXT1 alpha blocks for better quality or DXT1A transparency.\n  // DXT5: OK to use both DXT5 block types.\n  // Currently only used when writing to .DDS files, as .CRN uses only a subset of the possible DXTn block types.\n  // Default: Set.\n  cCRNCompFlagUseBothBlockTypes = 8,\n\n  // OK to use DXT1A transparent indices to encode black (assumes pixel shader ignores fetched alpha).\n  // Currently only used when writing to .DDS files, .CRN never uses alpha blocks.\n  // Default: Not set.\n  cCRNCompFlagUseTransparentIndicesForBlack = 16,\n\n  // Disables endpoint caching, for more deterministic output.\n  // Currently only used when writing to .DDS files.\n  // Default: Not set.\n  cCRNCompFlagDisableEndpointCaching = 32,\n\n  // If enabled, use the cCRNColorEndpointPaletteSize, etc. params to control the CRN palette sizes. Only useful when writing to .CRN files.\n  // Default: Not set.\n  cCRNCompFlagManualPaletteSizes = 64,\n\n  // If enabled, DXT1A alpha blocks are used to encode single bit transparency.\n  // Default: Not set.\n  cCRNCompFlagDXT1AForTransparency = 128,\n\n  // If enabled, the DXT1 compressor's color distance metric assumes the pixel shader will be converting the fetched RGB results to luma (Y part of YCbCr).\n  // This increases quality when compressing grayscale images, because the compressor can spread the luma error amoung all three channels (i.e. it can generate blocks\n  // with some chroma present if doing so will ultimately lead to lower luma error).\n  // Only enable on grayscale source images.\n  // Default: Not set.\n  cCRNCompFlagGrayscaleSampling = 256,\n\n  // If enabled, debug information will be output during compression.\n  // Default: Not set.\n  cCRNCompFlagDebugging = 0x80000000,\n\n  cCRNCompFlagForceDWORD = 0xFFFFFFFF\n};\n\n// Controls DXTn quality vs. speed control - only used when compressing to .DDS.\nenum crn_dxt_quality {\n  cCRNDXTQualitySuperFast,\n  cCRNDXTQualityFast,\n  cCRNDXTQualityNormal,\n  cCRNDXTQualityBetter,\n  cCRNDXTQualityUber,\n\n  cCRNDXTQualityTotal,\n\n  cCRNDXTQualityForceDWORD = 0xFFFFFFFF\n};\n\n// Which DXTn compressor to use when compressing to plain (non-clustered) .DDS.\nenum crn_dxt_compressor_type {\n  cCRNDXTCompressorCRN,   // Use crnlib's ETC1 or DXTc block compressor (default, highest quality, comparable or better than ati_compress or squish, and crnlib's ETC1 is a lot fasterw with similiar quality to Erricson's)\n  cCRNDXTCompressorCRNF,  // Use crnlib's \"fast\" DXTc block compressor\n  cCRNDXTCompressorRYG,   // Use RYG's DXTc block compressor (low quality, but very fast)\n\n#if CRNLIB_SUPPORT_ATI_COMPRESS\n  cCRNDXTCompressorATI,\n#endif\n\n#if CRNLIB_SUPPORT_SQUISH\n  cCRNDXTCompressorSquish,\n#endif\n\n  cCRNTotalDXTCompressors,\n\n  cCRNDXTCompressorForceDWORD = 0xFFFFFFFF\n};\n\n// Progress callback function.\n// Processing will stop prematurely (and fail) if the callback returns false.\n// phase_index, total_phases - high level progress\n// subphase_index, total_subphases - progress within current phase\ntypedef crn_bool (*crn_progress_callback_func)(crn_uint32 phase_index, crn_uint32 total_phases, crn_uint32 subphase_index, crn_uint32 total_subphases, void* pUser_data_ptr);\n\n// CRN/DDS compression parameters struct.\nstruct crn_comp_params {\n  inline crn_comp_params() { clear(); }\n\n  // Clear struct to default parameters.\n  inline void clear() {\n    m_size_of_obj = sizeof(*this);\n    m_file_type = cCRNFileTypeCRN;\n    m_faces = 1;\n    m_width = 0;\n    m_height = 0;\n    m_levels = 1;\n    m_format = cCRNFmtDXT1;\n    m_flags = cCRNCompFlagPerceptual | cCRNCompFlagHierarchical | cCRNCompFlagUseBothBlockTypes;\n\n    for (crn_uint32 f = 0; f < cCRNMaxFaces; f++)\n      for (crn_uint32 l = 0; l < cCRNMaxLevels; l++)\n        m_pImages[f][l] = NULL;\n\n    m_target_bitrate = 0.0f;\n    m_quality_level = cCRNMaxQualityLevel;\n    m_dxt1a_alpha_threshold = 128;\n    m_dxt_quality = cCRNDXTQualityUber;\n    m_dxt_compressor_type = cCRNDXTCompressorCRN;\n    m_alpha_component = 3;\n\n    m_crn_adaptive_tile_color_psnr_derating = 2.0f;\n    m_crn_adaptive_tile_alpha_psnr_derating = 2.0f;\n    m_crn_color_endpoint_palette_size = 0;\n    m_crn_color_selector_palette_size = 0;\n    m_crn_alpha_endpoint_palette_size = 0;\n    m_crn_alpha_selector_palette_size = 0;\n\n    m_num_helper_threads = 0;\n    m_userdata0 = 0;\n    m_userdata1 = 0;\n    m_pProgress_func = NULL;\n    m_pProgress_func_data = NULL;\n  }\n\n  inline bool operator==(const crn_comp_params& rhs) const {\n#define CRNLIB_COMP(x)  \\\n  do {                  \\\n    if ((x) != (rhs.x)) \\\n      return false;     \\\n  } while (0)\n    CRNLIB_COMP(m_size_of_obj);\n    CRNLIB_COMP(m_file_type);\n    CRNLIB_COMP(m_faces);\n    CRNLIB_COMP(m_width);\n    CRNLIB_COMP(m_height);\n    CRNLIB_COMP(m_levels);\n    CRNLIB_COMP(m_format);\n    CRNLIB_COMP(m_flags);\n    CRNLIB_COMP(m_target_bitrate);\n    CRNLIB_COMP(m_quality_level);\n    CRNLIB_COMP(m_dxt1a_alpha_threshold);\n    CRNLIB_COMP(m_dxt_quality);\n    CRNLIB_COMP(m_dxt_compressor_type);\n    CRNLIB_COMP(m_alpha_component);\n    CRNLIB_COMP(m_crn_adaptive_tile_color_psnr_derating);\n    CRNLIB_COMP(m_crn_adaptive_tile_alpha_psnr_derating);\n    CRNLIB_COMP(m_crn_color_endpoint_palette_size);\n    CRNLIB_COMP(m_crn_color_selector_palette_size);\n    CRNLIB_COMP(m_crn_alpha_endpoint_palette_size);\n    CRNLIB_COMP(m_crn_alpha_selector_palette_size);\n    CRNLIB_COMP(m_num_helper_threads);\n    CRNLIB_COMP(m_userdata0);\n    CRNLIB_COMP(m_userdata1);\n    CRNLIB_COMP(m_pProgress_func);\n    CRNLIB_COMP(m_pProgress_func_data);\n\n    for (crn_uint32 f = 0; f < cCRNMaxFaces; f++)\n      for (crn_uint32 l = 0; l < cCRNMaxLevels; l++)\n        CRNLIB_COMP(m_pImages[f][l]);\n\n#undef CRNLIB_COMP\n    return true;\n  }\n\n  // Returns true if the input parameters are reasonable.\n  inline bool check() const {\n    if ((m_file_type > cCRNFileTypeDDS) ||\n        (((int)m_quality_level < (int)cCRNMinQualityLevel) || ((int)m_quality_level > (int)cCRNMaxQualityLevel)) ||\n        (m_dxt1a_alpha_threshold > 255) ||\n        ((m_faces != 1) && (m_faces != 6)) ||\n        ((m_width < 1) || (m_width > cCRNMaxLevelResolution)) ||\n        ((m_height < 1) || (m_height > cCRNMaxLevelResolution)) ||\n        ((m_levels < 1) || (m_levels > cCRNMaxLevels)) ||\n        ((m_format < cCRNFmtDXT1) || (m_format >= cCRNFmtTotal)) ||\n        ((m_crn_color_endpoint_palette_size) && ((m_crn_color_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_color_endpoint_palette_size > cCRNMaxPaletteSize))) ||\n        ((m_crn_color_selector_palette_size) && ((m_crn_color_selector_palette_size < cCRNMinPaletteSize) || (m_crn_color_selector_palette_size > cCRNMaxPaletteSize))) ||\n        ((m_crn_alpha_endpoint_palette_size) && ((m_crn_alpha_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_endpoint_palette_size > cCRNMaxPaletteSize))) ||\n        ((m_crn_alpha_selector_palette_size) && ((m_crn_alpha_selector_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_selector_palette_size > cCRNMaxPaletteSize))) ||\n        (m_alpha_component > 3) ||\n        (m_num_helper_threads > cCRNMaxHelperThreads) ||\n        (m_dxt_quality > cCRNDXTQualityUber) ||\n        (m_dxt_compressor_type >= cCRNTotalDXTCompressors)) {\n      return false;\n    }\n    return true;\n  }\n\n  // Helper to set/get flags from m_flags member.\n  inline bool get_flag(crn_comp_flags flag) const { return (m_flags & flag) != 0; }\n  inline void set_flag(crn_comp_flags flag, bool val) {\n    m_flags &= ~flag;\n    if (val)\n      m_flags |= flag;\n  }\n\n  crn_uint32 m_size_of_obj;\n\n  crn_file_type m_file_type;  // Output file type: cCRNFileTypeCRN or cCRNFileTypeDDS.\n\n  crn_uint32 m_faces;   // 1 (2D map) or 6 (cubemap)\n  crn_uint32 m_width;   // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK\n  crn_uint32 m_height;  // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK\n  crn_uint32 m_levels;  // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK\n\n  crn_format m_format;  // Output pixel format.\n\n  crn_uint32 m_flags;  // see crn_comp_flags enum\n\n  // Array of pointers to 32bpp input images.\n  const crn_uint32* m_pImages[cCRNMaxFaces][cCRNMaxLevels];\n\n  // Target bitrate - if non-zero, the compressor will use an interpolative search to find the\n  // highest quality level that is <= the target bitrate. If it fails to find a bitrate high enough, it'll\n  // try disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and redo the search. This process can be pretty slow.\n  float m_target_bitrate;\n\n  // Desired quality level.\n  // Currently, CRN and DDS quality levels are not compatible with eachother from an image quality standpoint.\n  crn_uint32 m_quality_level;  // [cCRNMinQualityLevel, cCRNMaxQualityLevel]\n\n  // DXTn compression parameters.\n  crn_uint32 m_dxt1a_alpha_threshold;\n  crn_dxt_quality m_dxt_quality;\n  crn_dxt_compressor_type m_dxt_compressor_type;\n\n  // Alpha channel's component. Defaults to 3.\n  crn_uint32 m_alpha_component;\n\n  // Various low-level CRN specific parameters.\n  float m_crn_adaptive_tile_color_psnr_derating;\n  float m_crn_adaptive_tile_alpha_psnr_derating;\n\n  crn_uint32 m_crn_color_endpoint_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n  crn_uint32 m_crn_color_selector_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n\n  crn_uint32 m_crn_alpha_endpoint_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n  crn_uint32 m_crn_alpha_selector_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]\n\n  // Number of helper threads to create during compression. 0=no threading.\n  crn_uint32 m_num_helper_threads;\n\n  // CRN userdata0 and userdata1 members, which are written directly to the header of the output file.\n  crn_uint32 m_userdata0;\n  crn_uint32 m_userdata1;\n\n  // User provided progress callback.\n  crn_progress_callback_func m_pProgress_func;\n  void* m_pProgress_func_data;\n};\n\n// Mipmap generator's mode.\nenum crn_mip_mode {\n  cCRNMipModeUseSourceOrGenerateMips,  // Use source texture's mipmaps if it has any, otherwise generate new mipmaps\n  cCRNMipModeUseSourceMips,            // Use source texture's mipmaps if it has any, otherwise the output has no mipmaps\n  cCRNMipModeGenerateMips,             // Always generate new mipmaps\n  cCRNMipModeNoMips,                   // Output texture has no mipmaps\n\n  cCRNMipModeTotal,\n\n  cCRNModeForceDWORD = 0xFFFFFFFF\n};\n\nconst char* crn_get_mip_mode_desc(crn_mip_mode m);\nconst char* crn_get_mip_mode_name(crn_mip_mode m);\n\n// Mipmap generator's filter kernel.\nenum crn_mip_filter {\n  cCRNMipFilterBox,\n  cCRNMipFilterTent,\n  cCRNMipFilterLanczos4,\n  cCRNMipFilterMitchell,\n  cCRNMipFilterKaiser,  // Kaiser=default mipmap filter\n\n  cCRNMipFilterTotal,\n\n  cCRNMipFilterForceDWORD = 0xFFFFFFFF\n};\n\nconst char* crn_get_mip_filter_name(crn_mip_filter f);\n\n// Mipmap generator's scale mode.\nenum crn_scale_mode {\n  cCRNSMDisabled,\n  cCRNSMAbsolute,\n  cCRNSMRelative,\n  cCRNSMLowerPow2,\n  cCRNSMNearestPow2,\n  cCRNSMNextPow2,\n\n  cCRNSMTotal,\n\n  cCRNSMForceDWORD = 0xFFFFFFFF\n};\n\nconst char* crn_get_scale_mode_desc(crn_scale_mode sm);\n\n// Mipmap generator parameters.\nstruct crn_mipmap_params {\n  inline crn_mipmap_params() { clear(); }\n\n  inline void clear() {\n    m_size_of_obj = sizeof(*this);\n    m_mode = cCRNMipModeUseSourceOrGenerateMips;\n    m_filter = cCRNMipFilterKaiser;\n    m_gamma_filtering = true;\n    m_gamma = 2.2f;\n    // Default \"blurriness\" factor of .9 actually sharpens the output a little.\n    m_blurriness = .9f;\n    m_renormalize = false;\n    m_tiled = false;\n    m_max_levels = cCRNMaxLevels;\n    m_min_mip_size = 1;\n\n    m_scale_mode = cCRNSMDisabled;\n    m_scale_x = 1.0f;\n    m_scale_y = 1.0f;\n\n    m_window_left = 0;\n    m_window_top = 0;\n    m_window_right = 0;\n    m_window_bottom = 0;\n\n    m_clamp_scale = false;\n    m_clamp_width = 0;\n    m_clamp_height = 0;\n  }\n\n  inline bool check() const { return true; }\n\n  inline bool operator==(const crn_mipmap_params& rhs) const {\n#define CRNLIB_COMP(x)  \\\n  do {                  \\\n    if ((x) != (rhs.x)) \\\n      return false;     \\\n  } while (0)\n    CRNLIB_COMP(m_size_of_obj);\n    CRNLIB_COMP(m_mode);\n    CRNLIB_COMP(m_filter);\n    CRNLIB_COMP(m_gamma_filtering);\n    CRNLIB_COMP(m_gamma);\n    CRNLIB_COMP(m_blurriness);\n    CRNLIB_COMP(m_renormalize);\n    CRNLIB_COMP(m_tiled);\n    CRNLIB_COMP(m_max_levels);\n    CRNLIB_COMP(m_min_mip_size);\n    CRNLIB_COMP(m_scale_mode);\n    CRNLIB_COMP(m_scale_x);\n    CRNLIB_COMP(m_scale_y);\n    CRNLIB_COMP(m_window_left);\n    CRNLIB_COMP(m_window_top);\n    CRNLIB_COMP(m_window_right);\n    CRNLIB_COMP(m_window_bottom);\n    CRNLIB_COMP(m_clamp_scale);\n    CRNLIB_COMP(m_clamp_width);\n    CRNLIB_COMP(m_clamp_height);\n    return true;\n#undef CRNLIB_COMP\n  }\n  crn_uint32 m_size_of_obj;\n\n  crn_mip_mode m_mode;\n  crn_mip_filter m_filter;\n\n  crn_bool m_gamma_filtering;\n  float m_gamma;\n\n  float m_blurriness;\n\n  crn_uint32 m_max_levels;\n  crn_uint32 m_min_mip_size;\n\n  crn_bool m_renormalize;\n  crn_bool m_tiled;\n\n  crn_scale_mode m_scale_mode;\n  float m_scale_x;\n  float m_scale_y;\n\n  crn_uint32 m_window_left;\n  crn_uint32 m_window_top;\n  crn_uint32 m_window_right;\n  crn_uint32 m_window_bottom;\n\n  crn_bool m_clamp_scale;\n  crn_uint32 m_clamp_width;\n  crn_uint32 m_clamp_height;\n};\n\n// -------- High-level helper function definitions for CDN/DDS compression.\n\n#ifndef CRNLIB_MIN_ALLOC_ALIGNMENT\n#define CRNLIB_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2\n#endif\n\n// Function to set an optional user provided memory allocation/reallocation/msize routines.\n// By default, crnlib just uses malloc(), free(), etc. for all allocations.\ntypedef void* (*crn_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data);\ntypedef size_t (*crn_msize_func)(void* p, void* pUser_data);\nvoid crn_set_memory_callbacks(crn_realloc_func pRealloc, crn_msize_func pMSize, void* pUser_data);\n\n// Frees memory blocks allocated by crn_compress(), crn_decompress_crn_to_dds(), or crn_decompress_dds_to_images().\nvoid crn_free_block(void* pBlock);\n\n// Compresses a 32-bit/pixel texture to either: a regular DX9 DDS file, a \"clustered\" (or reduced entropy) DX9 DDS file, or a CRN file in memory.\n// Input parameters:\n//  comp_params is the compression parameters struct, defined above.\n//  compressed_size will be set to the size of the returned memory block containing the output file.\n//  The returned block must be freed by calling crn_free_block().\n//  *pActual_quality_level will be set to the actual quality level used to compress the image. May be NULL.\n//  *pActual_bitrate will be set to the output file's effective bitrate, possibly taking into account LZMA compression. May be NULL.\n// Return value:\n//  The compressed file data, or NULL on failure.\n//  compressed_size will be set to the size of the returned memory buffer.\n// Notes:\n//  A \"regular\" DDS file is compressed using normal DXTn compression at the specified DXT quality level.\n//  A \"clustered\" DDS file is compressed using clustered DXTn compression to either the target bitrate or the specified integer quality factor.\n//  The output file is a standard DX9 format DDS file, except the compressor assumes you will be later losslessly compressing the DDS output file using the LZMA algorithm.\n//  A texture is defined as an array of 1 or 6 \"faces\" (6 faces=cubemap), where each \"face\" consists of between [1,cCRNMaxLevels] mipmap levels.\n//  Mipmap levels are simple 32-bit 2D images with a pitch of width*sizeof(uint32), arranged in the usual raster order (top scanline first).\n//  The image pixels may be grayscale (YYYX bytes in memory), grayscale/alpha (YYYA in memory), 24-bit (RGBX in memory), or 32-bit (RGBA) colors (where \"X\"=don't care).\n//  RGB color data is generally assumed to be in the sRGB colorspace. If not, be sure to clear the \"cCRNCompFlagPerceptual\" in the crn_comp_params struct!\nvoid* crn_compress(const crn_comp_params& comp_params, crn_uint32& compressed_size, crn_uint32* pActual_quality_level = NULL, float* pActual_bitrate = NULL);\n\n// Like the above function, except this function can also do things like generate mipmaps, and resize or crop the input texture before compression.\n// The actual operations performed are controlled by the crn_mipmap_params struct members.\n// Be sure to set the \"m_gamma_filtering\" member of crn_mipmap_params to false if the input texture is not sRGB.\nvoid* crn_compress(const crn_comp_params& comp_params, const crn_mipmap_params& mip_params, crn_uint32& compressed_size, crn_uint32* pActual_quality_level = NULL, float* pActual_bitrate = NULL);\n\n// Transcodes an entire CRN file to DDS using the crn_decomp.h header file library to do most of the heavy lifting.\n// The output DDS file's format is guaranteed to be one of the DXTn formats in the crn_format enum.\n// This is a fast operation, because the CRN format is explicitly designed to be efficiently transcodable to DXTn.\n// For more control over decompression, see the lower-level helper functions in crn_decomp.h, which do not depend at all on crnlib.\nvoid* crn_decompress_crn_to_dds(const void* pCRN_file_data, crn_uint32& file_size);\n\n// Decompresses an entire DDS file in any supported format to uncompressed 32-bit/pixel image(s).\n// See the crnlib::pixel_format enum in inc/dds_defs.h for a list of the supported DDS formats.\n// You are responsible for freeing each image block, either by calling crn_free_all_images() or manually calling crn_free_block() on each image pointer.\nstruct crn_texture_desc {\n  crn_uint32 m_faces;\n  crn_uint32 m_width;\n  crn_uint32 m_height;\n  crn_uint32 m_levels;\n  crn_uint32 m_fmt_fourcc;  // Same as crnlib::pixel_format\n};\nbool crn_decompress_dds_to_images(const void* pDDS_file_data, crn_uint32 dds_file_size, crn_uint32** ppImages, crn_texture_desc& tex_desc);\n\n// Frees all images allocated by crn_decompress_dds_to_images().\nvoid crn_free_all_images(crn_uint32** ppImages, const crn_texture_desc& desc);\n\n// -------- crn_format related helpers functions.\n\n// Returns the FOURCC format equivalent to the specified crn_format.\ncrn_uint32 crn_get_format_fourcc(crn_format fmt);\n\n// Returns the crn_format's bits per texel.\ncrn_uint32 crn_get_format_bits_per_texel(crn_format fmt);\n\n// Returns the crn_format's number of bytes per block.\ncrn_uint32 crn_get_bytes_per_dxt_block(crn_format fmt);\n\n// Returns the non-swizzled, basic DXTn version of the specified crn_format.\n// This is the format you would supply D3D or OpenGL.\ncrn_format crn_get_fundamental_dxt_format(crn_format fmt);\n\n// -------- String helpers.\n\n// Converts a crn_file_type to a string.\nconst char* crn_get_file_type_ext(crn_file_type file_type);\n\n// Converts a crn_format to a string.\nconst char* crn_get_format_string(crn_format fmt);\n\n// Converts a crn_dxt_quality to a string.\nconst char* crn_get_dxt_quality_string(crn_dxt_quality q);\n\n// -------- Low-level DXTn 4x4 block compressor API\n\n// crnlib's DXTn endpoint optimizer actually supports any number of source pixels (i.e. from 1 to thousands, not just 16),\n// but for simplicity this API only supports 4x4 texel blocks.\ntypedef void* crn_block_compressor_context_t;\n\n// Create a DXTn block compressor.\n// This function only supports the basic/nonswizzled \"fundamental\" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX.\n// Avoid calling this multiple times if you intend on compressing many blocks, because it allocates some memory.\ncrn_block_compressor_context_t crn_create_block_compressor(const crn_comp_params& params);\n\n// Compresses a block of 16 pixels to the destination DXTn block.\n// pDst_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others).\n// pPixels should be an array of 16 crn_uint32's. Each crn_uint32 must be r,g,b,a (r is always first) in memory.\nvoid crn_compress_block(crn_block_compressor_context_t pContext, const crn_uint32* pPixels, void* pDst_block);\n\n// Frees a DXTn block compressor.\nvoid crn_free_block_compressor(crn_block_compressor_context_t pContext);\n\n// Unpacks a compressed block to pDst_pixels.\n// pSrc_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others).\n// pDst_pixel should be an array of 16 crn_uint32's. Each uint32 will be r,g,b,a (r is always first) in memory.\n// crn_fmt should be one of the \"fundamental\" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX.\n// The various swizzled DXT5 formats (such as cCRNFmtDXT5_xGBR, etc.) will be unpacked as if they where plain DXT5.\n// Returns false if the crn_fmt is invalid.\nbool crn_decompress_block(const void* pSrc_block, crn_uint32* pDst_pixels, crn_format crn_fmt);\n\n#endif  // CRNLIB_H\n\n//------------------------------------------------------------------------------\n//\n// crnlib uses the ZLIB license:\n// http://opensource.org/licenses/Zlib\n//\n// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC\n//\n// This software is provided 'as-is', without any express or implied\n// warranty.  In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n//\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n//\n// 3. This notice may not be removed or altered from any source distribution.\n//\n//------------------------------------------------------------------------------\n"
  },
  {
    "path": "Texture2DDecoderNative/unitycrunch.cpp",
    "content": "#include \"unitycrunch.h\"\n#include <stdint.h>\n#include <algorithm>\n#include \"unitycrunch/crn_decomp.h\"\n\nbool unity_crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size) {\n\tunitycrnd::crn_texture_info tex_info;\n\tif (!unitycrnd::crnd_get_texture_info(data, data_size, &tex_info))\n\t{\n\t\treturn false;\n\t}\n\n\tunitycrnd::crnd_unpack_context pContext = unitycrnd::crnd_unpack_begin(data, data_size);\n\tif (!pContext)\n\t{\n\t\treturn false;\n\t}\n\n\tconst crn_uint32 width = std::max(1U, tex_info.m_width >> level_index);\n\tconst crn_uint32 height = std::max(1U, tex_info.m_height >> level_index);\n\tconst crn_uint32 blocks_x = std::max(1U, (width + 3) >> 2);\n\tconst crn_uint32 blocks_y = std::max(1U, (height + 3) >> 2);\n\tconst crn_uint32 row_pitch = blocks_x * unitycrnd::crnd_get_bytes_per_dxt_block(tex_info.m_format);\n\tconst crn_uint32 total_face_size = row_pitch * blocks_y;\n\t*ret = new uint8_t[total_face_size];\n\t*ret_size = total_face_size;\n\tif (!unitycrnd::crnd_unpack_level(pContext, ret, total_face_size, row_pitch, level_index))\n\t{\n\t\tunitycrnd::crnd_unpack_end(pContext);\n\t\treturn false;\n\t}\n\tunitycrnd::crnd_unpack_end(pContext);\n\treturn true;\n}"
  },
  {
    "path": "Texture2DDecoderNative/unitycrunch.h",
    "content": "#pragma once\n\n#include <stdint.h>\n\nbool unity_crunch_unpack_level(const uint8_t* data, uint32_t data_size, uint32_t level_index, void** ret, uint32_t* ret_size);"
  },
  {
    "path": "Texture2DDecoderWrapper/T2DDll.cs",
    "content": "﻿namespace Texture2DDecoder\n{\n    internal static class T2DDll\n    {\n\n        internal const string DllName = \"Texture2DDecoderNative\";\n\n    }\n}\n"
  },
  {
    "path": "Texture2DDecoderWrapper/Texture2DDecoderWrapper.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <Version>0.16.0.0</Version>\n    <AssemblyVersion>0.16.0.0</AssemblyVersion>\n    <FileVersion>0.16.0.0</FileVersion>\n    <Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>\n    <DebugType>embedded</DebugType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\AssetStudio.PInvoke\\AssetStudio.PInvoke.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Texture2DDecoderWrapper/TextureDecoder.PInvoke.cs",
    "content": "﻿using System.Runtime.InteropServices;\n\nnamespace Texture2DDecoder\n{\n    unsafe partial class TextureDecoder\n    {\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeDXT1(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeDXT5(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodePVRTC(void* data, int width, int height, void* image, [MarshalAs(UnmanagedType.Bool)] bool is2bpp);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeETC1(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeETC2(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeETC2A1(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeETC2A8(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeEACR(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeEACRSigned(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeEACRG(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeEACRGSigned(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeBC4(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeBC5(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeBC6(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeBC7(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeATCRGB4(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeATCRGBA8(void* data, int width, int height, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        private static extern bool DecodeASTC(void* data, int width, int height, int blockWidth, int blockHeight, void* image);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void DisposeBuffer(ref void* ppBuffer);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void UnpackCrunch(void* data, uint dataSize, out void* result, out uint resultSize);\n\n        [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]\n        private static extern void UnpackUnityCrunch(void* data, uint dataSize, out void* result, out uint resultSize);\n\n    }\n}\n"
  },
  {
    "path": "Texture2DDecoderWrapper/TextureDecoder.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\nusing AssetStudio.PInvoke;\n\nnamespace Texture2DDecoder\n{\n    public static unsafe partial class TextureDecoder\n    {\n\n        static TextureDecoder()\n        {\n            DllLoader.PreloadDll(T2DDll.DllName);\n        }\n\n        public static bool DecodeDXT1(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeDXT1(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeDXT5(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeDXT5(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodePVRTC(byte[] data, int width, int height, byte[] image, bool is2bpp)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodePVRTC(pData, width, height, pImage, is2bpp);\n                }\n            }\n        }\n\n        public static bool DecodeETC1(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeETC1(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeETC2(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeETC2(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeETC2A1(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeETC2A1(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeETC2A8(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeETC2A8(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeEACR(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeEACR(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeEACRSigned(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeEACRSigned(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeEACRG(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeEACRG(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeEACRGSigned(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeEACRGSigned(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeBC4(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeBC4(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeBC5(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeBC5(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeBC6(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeBC6(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeBC7(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeBC7(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeATCRGB4(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeATCRGB4(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeATCRGBA8(byte[] data, int width, int height, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeATCRGBA8(pData, width, height, pImage);\n                }\n            }\n        }\n\n        public static bool DecodeASTC(byte[] data, int width, int height, int blockWidth, int blockHeight, byte[] image)\n        {\n            fixed (byte* pData = data)\n            {\n                fixed (byte* pImage = image)\n                {\n                    return DecodeASTC(pData, width, height, blockWidth, blockHeight, pImage);\n                }\n            }\n        }\n\n        public static byte[] UnpackCrunch(byte[] data)\n        {\n            void* pBuffer;\n            uint bufferSize;\n\n            fixed (byte* pData = data)\n            {\n                UnpackCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize);\n            }\n\n            if (pBuffer == null)\n            {\n                return null;\n            }\n\n            var result = new byte[bufferSize];\n\n            Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize);\n\n            DisposeBuffer(ref pBuffer);\n\n            return result;\n        }\n\n        public static byte[] UnpackUnityCrunch(byte[] data)\n        {\n            void* pBuffer;\n            uint bufferSize;\n\n            fixed (byte* pData = data)\n            {\n                UnpackUnityCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize);\n            }\n\n            if (pBuffer == null)\n            {\n                return null;\n            }\n\n            var result = new byte[bufferSize];\n\n            Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize);\n\n            DisposeBuffer(ref pBuffer);\n\n            return result;\n        }\n\n    }\n}\n"
  }
]