Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ea998b81f | ||
|
|
b93866d196 | ||
|
|
c0a5a7a5dd | ||
|
|
6d68f2bde5 | ||
|
|
a89fd049f1 | ||
|
|
e7c5976f7c | ||
|
|
798a63e33c | ||
|
|
e13b4489c3 | ||
|
|
c6484ba77e | ||
|
|
a98fd52831 | ||
|
|
9d3cae8b28 | ||
|
|
f5aef9486f | ||
|
|
c2ae9e63e0 | ||
|
|
b04cdbf12b | ||
|
|
1f897cf431 | ||
|
|
d380c38710 | ||
|
|
3cd6126ed9 | ||
|
|
22b2d472bc | ||
|
|
2c58fae804 | ||
|
|
1e9b8037ab | ||
|
|
0dbd5b52f0 | ||
|
|
21a8d7ef49 | ||
|
|
17bd7a210a | ||
|
|
40b191f039 | ||
|
|
3442b39784 | ||
|
|
f15ee038b4 | ||
|
|
ec8b41155a | ||
|
|
d54bfbdfe7 | ||
|
|
a1f491af25 | ||
|
|
f2b041741b | ||
|
|
97169ff6dd | ||
|
|
11019a8473 | ||
|
|
767e4d0bf6 | ||
|
|
250856598b | ||
|
|
61751eeb1b | ||
|
|
99651a5d77 | ||
|
|
b31614641d | ||
|
|
310c165824 | ||
|
|
a233af5b8f | ||
|
|
2d0278db87 | ||
|
|
18af0a8856 | ||
|
|
d7d56b4ad8 | ||
|
|
3034dbc392 | ||
|
|
0b508509af | ||
|
|
14ad9431b9 | ||
|
|
c9a98d7163 | ||
|
|
afae830ece | ||
|
|
ec8c3e71d6 | ||
|
|
a7c5330042 | ||
|
|
10f02af70b | ||
|
|
2fd2b71148 | ||
|
|
d1bec6a672 | ||
|
|
9336613755 | ||
|
|
9f482b7cf9 | ||
|
|
0c8fcb07b1 | ||
|
|
eb302be569 | ||
|
|
cb3cf2a5ea | ||
|
|
9e5a06c107 | ||
|
|
b49d5bdeb4 | ||
|
|
0c23548817 | ||
|
|
cdaeb36e06 | ||
|
|
114073f359 | ||
|
|
959a1a65b9 | ||
|
|
3e59a78376 | ||
|
|
2bd4729fe7 | ||
|
|
84054428a8 | ||
|
|
9ad063bd0a | ||
|
|
9d1fd2f945 | ||
|
|
35edb9d391 | ||
|
|
d523862fac | ||
|
|
21ff88c890 | ||
|
|
e034ac5c1e | ||
|
|
adf39dde27 | ||
|
|
9b1e3435d6 | ||
|
|
66a2dbe730 | ||
|
|
28a3b6cb23 | ||
|
|
2adda81b28 | ||
|
|
380afbf295 | ||
|
|
d39e24246e | ||
|
|
a3e430d98d | ||
|
|
e0dcd6ac10 | ||
|
|
02f8d46620 | ||
|
|
dc6b9748a3 | ||
|
|
54c2bdc728 | ||
|
|
18275557df | ||
|
|
453f6b6e36 | ||
|
|
7236136cf1 | ||
|
|
ac6bd5236e | ||
|
|
b2acf9a2a7 | ||
|
|
7a8ac79ec4 | ||
|
|
70c9d0edb3 | ||
|
|
18e934dd7e | ||
|
|
3457d4d22c | ||
|
|
f65514b320 | ||
|
|
0a0b172a09 | ||
|
|
3e2d0935b8 | ||
|
|
71c633b506 | ||
|
|
79af119cf4 | ||
|
|
9385b4da76 | ||
|
|
75985c8bf0 | ||
|
|
9c8601a665 | ||
|
|
8218662548 | ||
|
|
52ba354dc5 | ||
|
|
87d6a26232 | ||
|
|
546fe52ff0 | ||
|
|
674c634c2c | ||
|
|
a3c92ddb8f | ||
|
|
4bcc16245c | ||
|
|
bd5eb3be5d | ||
|
|
ffda15a1a5 | ||
|
|
5354506315 | ||
|
|
ed569bfaf8 | ||
|
|
592bfb64e7 | ||
|
|
17b986f5df | ||
|
|
de464dfe10 | ||
|
|
906149a58a | ||
|
|
e3a0ab4e4a | ||
|
|
500f7788d4 | ||
|
|
af80b270cf | ||
|
|
8031d1a03f | ||
|
|
bc2469e11a | ||
|
|
9e4be3e082 | ||
|
|
7410511c40 | ||
|
|
8906c856e8 | ||
|
|
dec672f9e2 | ||
|
|
0b111d5f79 | ||
|
|
4bcbdbc57d | ||
|
|
d5d937247e | ||
|
|
4ab513002f | ||
|
|
140a732046 | ||
|
|
e5104d5cc7 | ||
|
|
f87390cc2b | ||
|
|
a062905734 | ||
|
|
62206f8977 | ||
|
|
8891414f60 | ||
|
|
90dce1c17d | ||
|
|
a9f1bd320e | ||
|
|
c8393e165f | ||
|
|
9d7c3b9f64 | ||
|
|
aa653cd508 | ||
|
|
3d60c5a7f6 | ||
|
|
4ef160de34 | ||
|
|
8f7def379d | ||
|
|
351228e45c | ||
|
|
ee6c050330 | ||
|
|
b4ce12a9e8 | ||
|
|
8664531c47 | ||
|
|
40f6dbcc06 | ||
|
|
1f21a67610 |
61
AssetStudio.sln
Normal file
61
AssetStudio.sln
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2024
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "AssetStudioFBX\AssetStudioFBX.vcxproj", "{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioTools", "AssetStudioTools\AssetStudioTools.csproj", "{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{AF56B63C-1764-41B7-9E60-8D485422AC3B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.Build.0 = Debug|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.Build.0 = Debug|x86
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.ActiveCfg = Release|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.Build.0 = Release|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.ActiveCfg = Release|x86
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.Build.0 = Release|x86
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.Build.0 = Debug|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.ActiveCfg = Release|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.Build.0 = Release|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.Build.0 = Release|Win32
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.Build.0 = Debug|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.Build.0 = Debug|x86
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.ActiveCfg = Release|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.Build.0 = Release|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.ActiveCfg = Release|x86
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.Build.0 = Release|x86
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F5C476A6-2B3B-416F-8BD5-6FE454FF3972}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class CRC
|
||||
public class CRC
|
||||
{
|
||||
public static readonly uint[] Table;
|
||||
|
||||
148
AssetStudio/AssetStudio.csproj
Normal file
148
AssetStudio/AssetStudio.csproj
Normal file
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{AF56B63C-1764-41B7-9E60-8D485422AC3B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AssetStudio</RootNamespace>
|
||||
<AssemblyName>AssetStudio</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="SharpDX.Mathematics">
|
||||
<HintPath>Libraries\SharpDX.Mathematics.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Half">
|
||||
<HintPath>Libraries\System.Half.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="7zip\Common\CommandLineParser.cs" />
|
||||
<Compile Include="7zip\Common\CRC.cs" />
|
||||
<Compile Include="7zip\Common\InBuffer.cs" />
|
||||
<Compile Include="7zip\Common\OutBuffer.cs" />
|
||||
<Compile Include="7zip\Compress\LZMA\LzmaBase.cs" />
|
||||
<Compile Include="7zip\Compress\LZMA\LzmaDecoder.cs" />
|
||||
<Compile Include="7zip\Compress\LZMA\LzmaEncoder.cs" />
|
||||
<Compile Include="7zip\Compress\LZ\IMatchFinder.cs" />
|
||||
<Compile Include="7zip\Compress\LZ\LzBinTree.cs" />
|
||||
<Compile Include="7zip\Compress\LZ\LzInWindow.cs" />
|
||||
<Compile Include="7zip\Compress\LZ\LzOutWindow.cs" />
|
||||
<Compile Include="7zip\Compress\RangeCoder\RangeCoder.cs" />
|
||||
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs" />
|
||||
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs" />
|
||||
<Compile Include="7zip\ICoder.cs" />
|
||||
<Compile Include="Utility\IImported.cs" />
|
||||
<Compile Include="SerializedFile.cs" />
|
||||
<Compile Include="AssetsManager.cs" />
|
||||
<Compile Include="Extensions\BinaryReaderExtensions.cs" />
|
||||
<Compile Include="Extensions\BinaryWriterExtensions.cs" />
|
||||
<Compile Include="Brotli\BitReader.cs" />
|
||||
<Compile Include="Brotli\BrotliInputStream.cs" />
|
||||
<Compile Include="Brotli\BrotliRuntimeException.cs" />
|
||||
<Compile Include="Brotli\Context.cs" />
|
||||
<Compile Include="Brotli\Decode.cs" />
|
||||
<Compile Include="Brotli\Dictionary.cs" />
|
||||
<Compile Include="Brotli\Huffman.cs" />
|
||||
<Compile Include="Brotli\HuffmanTreeGroup.cs" />
|
||||
<Compile Include="Brotli\IntReader.cs" />
|
||||
<Compile Include="Brotli\Prefix.cs" />
|
||||
<Compile Include="Brotli\RunningState.cs" />
|
||||
<Compile Include="Brotli\State.cs" />
|
||||
<Compile Include="Brotli\Transform.cs" />
|
||||
<Compile Include="Brotli\Utils.cs" />
|
||||
<Compile Include="Brotli\WordTransformType.cs" />
|
||||
<Compile Include="BuildTarget.cs" />
|
||||
<Compile Include="BuildType.cs" />
|
||||
<Compile Include="BundleFile.cs" />
|
||||
<Compile Include="Classes\Animation.cs" />
|
||||
<Compile Include="Classes\AnimationClip.cs" />
|
||||
<Compile Include="Classes\Animator.cs" />
|
||||
<Compile Include="Classes\AnimatorController.cs" />
|
||||
<Compile Include="Classes\AnimatorOverrideController.cs" />
|
||||
<Compile Include="Classes\AssetBundle.cs" />
|
||||
<Compile Include="Classes\AudioClip.cs" />
|
||||
<Compile Include="Classes\Avatar.cs" />
|
||||
<Compile Include="Classes\Behaviour.cs" />
|
||||
<Compile Include="Classes\BuildSettings.cs" />
|
||||
<Compile Include="Classes\Component.cs" />
|
||||
<Compile Include="Classes\EditorExtension.cs" />
|
||||
<Compile Include="Classes\Font.cs" />
|
||||
<Compile Include="Classes\GameObject.cs" />
|
||||
<Compile Include="Classes\Material.cs" />
|
||||
<Compile Include="Classes\Mesh.cs" />
|
||||
<Compile Include="Classes\MeshFilter.cs" />
|
||||
<Compile Include="Classes\MeshRenderer.cs" />
|
||||
<Compile Include="Classes\MonoBehaviour.cs" />
|
||||
<Compile Include="Classes\MonoScript.cs" />
|
||||
<Compile Include="Classes\MovieTexture.cs" />
|
||||
<Compile Include="Classes\NamedObject.cs" />
|
||||
<Compile Include="Classes\Object.cs" />
|
||||
<Compile Include="Classes\PlayerSettings.cs" />
|
||||
<Compile Include="Classes\RectTransform.cs" />
|
||||
<Compile Include="Classes\Renderer.cs" />
|
||||
<Compile Include="Classes\Shader.cs" />
|
||||
<Compile Include="Classes\SkinnedMeshRenderer.cs" />
|
||||
<Compile Include="Classes\Sprite.cs" />
|
||||
<Compile Include="Classes\SpriteAtlas.cs" />
|
||||
<Compile Include="Classes\TextAsset.cs" />
|
||||
<Compile Include="Classes\Texture.cs" />
|
||||
<Compile Include="Classes\Texture2D.cs" />
|
||||
<Compile Include="Classes\Transform.cs" />
|
||||
<Compile Include="Classes\VideoClip.cs" />
|
||||
<Compile Include="ClassIDType.cs" />
|
||||
<Compile Include="CommonString.cs" />
|
||||
<Compile Include="EndianBinaryReader.cs" />
|
||||
<Compile Include="FileIdentifier.cs" />
|
||||
<Compile Include="Utility\ILogger.cs" />
|
||||
<Compile Include="ImportHelper.cs" />
|
||||
<Compile Include="Utility\IProgress.cs" />
|
||||
<Compile Include="LocalSerializedObjectIdentifier.cs" />
|
||||
<Compile Include="Utility\Logger.cs" />
|
||||
<Compile Include="Lz4DecoderStream.cs" />
|
||||
<Compile Include="ObjectInfo.cs" />
|
||||
<Compile Include="ObjectReader.cs" />
|
||||
<Compile Include="Classes\PPtr.cs" />
|
||||
<Compile Include="Utility\Progress.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ResourcesHelper.cs" />
|
||||
<Compile Include="SerializedFileHeader.cs" />
|
||||
<Compile Include="SerializedType.cs" />
|
||||
<Compile Include="SevenZipHelper.cs" />
|
||||
<Compile Include="Extensions\StreamExtensions.cs" />
|
||||
<Compile Include="TypeTreeHelper.cs" />
|
||||
<Compile Include="TypeTreeNode.cs" />
|
||||
<Compile Include="WebFile.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
192
AssetStudio/AssetsManager.cs
Normal file
192
AssetStudio/AssetsManager.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using static AssetStudio.ImportHelper;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class AssetsManager
|
||||
{
|
||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>();
|
||||
internal Dictionary<string, EndianBinaryReader> resourceFileReaders = new Dictionary<string, EndianBinaryReader>();
|
||||
|
||||
private List<string> importFiles = new List<string>();
|
||||
private HashSet<string> importFilesHash = new HashSet<string>();
|
||||
private HashSet<string> assetsfileListHash = new HashSet<string>();
|
||||
|
||||
public void LoadFiles(string[] files)
|
||||
{
|
||||
var path = Path.GetDirectoryName(files[0]);
|
||||
MergeSplitAssets(path);
|
||||
var toReadFile = ProcessingSplitFiles(files.ToList());
|
||||
Load(toReadFile);
|
||||
}
|
||||
|
||||
public void LoadFolder(string path)
|
||||
{
|
||||
MergeSplitAssets(path, true);
|
||||
var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).ToList();
|
||||
var toReadFile = ProcessingSplitFiles(files);
|
||||
Load(toReadFile);
|
||||
}
|
||||
|
||||
private void Load(string[] files)
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
importFiles.Add(file);
|
||||
importFilesHash.Add(Path.GetFileName(file).ToUpper());
|
||||
}
|
||||
Progress.Reset();
|
||||
//use a for loop because list size can change
|
||||
for (var i = 0; i < importFiles.Count; i++)
|
||||
{
|
||||
LoadFile(importFiles[i]);
|
||||
Progress.Report(i + 1, importFiles.Count);
|
||||
}
|
||||
importFiles.Clear();
|
||||
importFilesHash.Clear();
|
||||
assetsfileListHash.Clear();
|
||||
}
|
||||
|
||||
private void LoadFile(string fullName)
|
||||
{
|
||||
switch (CheckFileType(fullName, out var reader))
|
||||
{
|
||||
case FileType.AssetsFile:
|
||||
LoadAssetsFile(fullName, reader);
|
||||
break;
|
||||
case FileType.BundleFile:
|
||||
LoadBundleFile(fullName, reader);
|
||||
break;
|
||||
case FileType.WebFile:
|
||||
LoadWebFile(fullName, reader);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
|
||||
{
|
||||
var fileName = Path.GetFileName(fullName);
|
||||
if (!assetsfileListHash.Contains(fileName.ToUpper()))
|
||||
{
|
||||
Logger.Info($"Loading {fileName}");
|
||||
var assetsFile = new SerializedFile(this, fullName, reader);
|
||||
if (assetsFile.valid)
|
||||
{
|
||||
assetsFileList.Add(assetsFile);
|
||||
assetsfileListHash.Add(assetsFile.upperFileName);
|
||||
|
||||
foreach (var sharedFile in assetsFile.m_Externals)
|
||||
{
|
||||
var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName;
|
||||
var sharedFileName = sharedFile.fileName;
|
||||
|
||||
if (!importFilesHash.Contains(sharedFileName.ToUpper()))
|
||||
{
|
||||
if (!File.Exists(sharedFilePath))
|
||||
{
|
||||
var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories);
|
||||
if (findFiles.Length > 0)
|
||||
{
|
||||
sharedFilePath = findFiles[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(sharedFilePath))
|
||||
{
|
||||
importFiles.Add(sharedFilePath);
|
||||
importFilesHash.Add(sharedFileName.ToUpper());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, string originalPath, string unityVersion = null)
|
||||
{
|
||||
var fileName = Path.GetFileName(fullName);
|
||||
if (!assetsfileListHash.Contains(fileName.ToUpper()))
|
||||
{
|
||||
Logger.Info($"Loading {fileName}");
|
||||
var assetsFile = new SerializedFile(this, fullName, reader);
|
||||
if (assetsFile.valid)
|
||||
{
|
||||
assetsFile.originalPath = originalPath;
|
||||
if (assetsFile.header.m_Version < 7)
|
||||
{
|
||||
assetsFile.SetVersion(unityVersion);
|
||||
}
|
||||
assetsFileList.Add(assetsFile);
|
||||
assetsfileListHash.Add(assetsFile.upperFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceFileReaders.Add(assetsFile.upperFileName, assetsFile.reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
|
||||
{
|
||||
var fileName = Path.GetFileName(fullName);
|
||||
Logger.Info("Decompressing " + fileName);
|
||||
var bundleFile = new BundleFile(reader, fullName);
|
||||
reader.Dispose();
|
||||
foreach (var file in bundleFile.fileList)
|
||||
{
|
||||
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
||||
LoadAssetsFromMemory(dummyPath, new EndianBinaryReader(file.stream), parentPath ?? fullName, bundleFile.versionEngine);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadWebFile(string fullName, EndianBinaryReader reader)
|
||||
{
|
||||
var fileName = Path.GetFileName(fullName);
|
||||
Logger.Info("Loading " + fileName);
|
||||
var webFile = new WebFile(reader);
|
||||
reader.Dispose();
|
||||
foreach (var file in webFile.fileList)
|
||||
{
|
||||
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
||||
switch (CheckFileType(file.stream, out reader))
|
||||
{
|
||||
case FileType.AssetsFile:
|
||||
LoadAssetsFromMemory(dummyPath, reader, fullName);
|
||||
break;
|
||||
case FileType.BundleFile:
|
||||
LoadBundleFile(dummyPath, reader, fullName);
|
||||
break;
|
||||
case FileType.WebFile:
|
||||
LoadWebFile(dummyPath, reader);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var assetsFile in assetsFileList)
|
||||
{
|
||||
assetsFile.reader.Close();
|
||||
}
|
||||
assetsFileList.Clear();
|
||||
foreach (var resourceFileReader in resourceFileReaders)
|
||||
{
|
||||
resourceFileReader.Value.Close();
|
||||
}
|
||||
resourceFileReaders.Clear();
|
||||
assetsFileIndexCache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
271
AssetStudio/Brotli/BitReader.cs
Normal file
271
AssetStudio/Brotli/BitReader.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Bit reading helpers.</summary>
|
||||
internal sealed class BitReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Input byte buffer, consist of a ring-buffer and a "slack" region where bytes from the start of
|
||||
/// the ring-buffer are copied.
|
||||
/// </summary>
|
||||
private const int Capacity = 1024;
|
||||
|
||||
private const int Slack = 16;
|
||||
|
||||
private const int IntBufferSize = Capacity + Slack;
|
||||
|
||||
private const int ByteReadSize = Capacity << 2;
|
||||
|
||||
private const int ByteBufferSize = IntBufferSize << 2;
|
||||
|
||||
private readonly byte[] byteBuffer = new byte[ByteBufferSize];
|
||||
|
||||
private readonly int[] intBuffer = new int[IntBufferSize];
|
||||
|
||||
private readonly Org.Brotli.Dec.IntReader intReader = new Org.Brotli.Dec.IntReader();
|
||||
|
||||
private System.IO.Stream input;
|
||||
|
||||
/// <summary>Input stream is finished.</summary>
|
||||
private bool endOfStreamReached;
|
||||
|
||||
/// <summary>Pre-fetched bits.</summary>
|
||||
internal long accumulator;
|
||||
|
||||
/// <summary>Current bit-reading position in accumulator.</summary>
|
||||
internal int bitOffset;
|
||||
|
||||
/// <summary>Offset of next item in intBuffer.</summary>
|
||||
private int intOffset;
|
||||
|
||||
private int tailBytes = 0;
|
||||
|
||||
/* Number of bytes in unfinished "int" item. */
|
||||
/// <summary>Fills up the input buffer.</summary>
|
||||
/// <remarks>
|
||||
/// Fills up the input buffer.
|
||||
/// <p> No-op if there are at least 36 bytes present after current position.
|
||||
/// <p> After encountering the end of the input stream, 64 additional zero bytes are copied to the
|
||||
/// buffer.
|
||||
/// </remarks>
|
||||
internal static void ReadMoreInput(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
// TODO: Split to check and read; move read outside of decoding loop.
|
||||
if (br.intOffset <= Capacity - 9)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (br.endOfStreamReached)
|
||||
{
|
||||
if (IntAvailable(br) >= -2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("No more input");
|
||||
}
|
||||
int readOffset = br.intOffset << 2;
|
||||
int bytesRead = ByteReadSize - readOffset;
|
||||
System.Array.Copy(br.byteBuffer, readOffset, br.byteBuffer, 0, bytesRead);
|
||||
br.intOffset = 0;
|
||||
try
|
||||
{
|
||||
while (bytesRead < ByteReadSize)
|
||||
{
|
||||
int len = br.input.Read(br.byteBuffer, bytesRead, ByteReadSize - bytesRead);
|
||||
// EOF is -1 in Java, but 0 in C#.
|
||||
if (len <= 0)
|
||||
{
|
||||
br.endOfStreamReached = true;
|
||||
br.tailBytes = bytesRead;
|
||||
bytesRead += 3;
|
||||
break;
|
||||
}
|
||||
bytesRead += len;
|
||||
}
|
||||
}
|
||||
catch (System.IO.IOException e)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Failed to read input", e);
|
||||
}
|
||||
Org.Brotli.Dec.IntReader.Convert(br.intReader, bytesRead >> 2);
|
||||
}
|
||||
|
||||
internal static void CheckHealth(Org.Brotli.Dec.BitReader br, bool endOfStream)
|
||||
{
|
||||
if (!br.endOfStreamReached)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int byteOffset = (br.intOffset << 2) + ((br.bitOffset + 7) >> 3) - 8;
|
||||
if (byteOffset > br.tailBytes)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Read after end");
|
||||
}
|
||||
if (endOfStream && (byteOffset != br.tailBytes))
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Unused bytes after end");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Advances the Read buffer by 5 bytes to make room for reading next 24 bits.</summary>
|
||||
internal static void FillBitWindow(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
if (br.bitOffset >= 32)
|
||||
{
|
||||
br.accumulator = ((long)br.intBuffer[br.intOffset++] << 32) | ((long)(((ulong)br.accumulator) >> 32));
|
||||
br.bitOffset -= 32;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reads the specified number of bits from Read Buffer.</summary>
|
||||
internal static int ReadBits(Org.Brotli.Dec.BitReader br, int n)
|
||||
{
|
||||
FillBitWindow(br);
|
||||
int val = (int)((long)(((ulong)br.accumulator) >> br.bitOffset)) & ((1 << n) - 1);
|
||||
br.bitOffset += n;
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>Initialize bit reader.</summary>
|
||||
/// <remarks>
|
||||
/// Initialize bit reader.
|
||||
/// <p> Initialisation turns bit reader to a ready state. Also a number of bytes is prefetched to
|
||||
/// accumulator. Because of that this method may block until enough data could be read from input.
|
||||
/// </remarks>
|
||||
/// <param name="br">BitReader POJO</param>
|
||||
/// <param name="input">data source</param>
|
||||
internal static void Init(Org.Brotli.Dec.BitReader br, System.IO.Stream input)
|
||||
{
|
||||
if (br.input != null)
|
||||
{
|
||||
throw new System.InvalidOperationException("Bit reader already has associated input stream");
|
||||
}
|
||||
Org.Brotli.Dec.IntReader.Init(br.intReader, br.byteBuffer, br.intBuffer);
|
||||
br.input = input;
|
||||
br.accumulator = 0;
|
||||
br.bitOffset = 64;
|
||||
br.intOffset = Capacity;
|
||||
br.endOfStreamReached = false;
|
||||
Prepare(br);
|
||||
}
|
||||
|
||||
private static void Prepare(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
ReadMoreInput(br);
|
||||
CheckHealth(br, false);
|
||||
FillBitWindow(br);
|
||||
FillBitWindow(br);
|
||||
}
|
||||
|
||||
internal static void Reload(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
if (br.bitOffset == 64)
|
||||
{
|
||||
Prepare(br);
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"/>
|
||||
internal static void Close(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
System.IO.Stream @is = br.input;
|
||||
br.input = null;
|
||||
if (@is != null)
|
||||
{
|
||||
@is.Close();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void JumpToByteBoundary(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
int padding = (64 - br.bitOffset) & 7;
|
||||
if (padding != 0)
|
||||
{
|
||||
int paddingBits = Org.Brotli.Dec.BitReader.ReadBits(br, padding);
|
||||
if (paddingBits != 0)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Corrupted padding bits");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static int IntAvailable(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
int limit = Capacity;
|
||||
if (br.endOfStreamReached)
|
||||
{
|
||||
limit = (br.tailBytes + 3) >> 2;
|
||||
}
|
||||
return limit - br.intOffset;
|
||||
}
|
||||
|
||||
internal static void CopyBytes(Org.Brotli.Dec.BitReader br, byte[] data, int offset, int length)
|
||||
{
|
||||
if ((br.bitOffset & 7) != 0)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Unaligned copyBytes");
|
||||
}
|
||||
// Drain accumulator.
|
||||
while ((br.bitOffset != 64) && (length != 0))
|
||||
{
|
||||
data[offset++] = unchecked((byte)((long)(((ulong)br.accumulator) >> br.bitOffset)));
|
||||
br.bitOffset += 8;
|
||||
length--;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Get data from shadow buffer with "sizeof(int)" granularity.
|
||||
int copyInts = System.Math.Min(IntAvailable(br), length >> 2);
|
||||
if (copyInts > 0)
|
||||
{
|
||||
int readOffset = br.intOffset << 2;
|
||||
System.Array.Copy(br.byteBuffer, readOffset, data, offset, copyInts << 2);
|
||||
offset += copyInts << 2;
|
||||
length -= copyInts << 2;
|
||||
br.intOffset += copyInts;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Read tail bytes.
|
||||
if (IntAvailable(br) > 0)
|
||||
{
|
||||
// length = 1..3
|
||||
FillBitWindow(br);
|
||||
while (length != 0)
|
||||
{
|
||||
data[offset++] = unchecked((byte)((long)(((ulong)br.accumulator) >> br.bitOffset)));
|
||||
br.bitOffset += 8;
|
||||
length--;
|
||||
}
|
||||
CheckHealth(br, false);
|
||||
return;
|
||||
}
|
||||
// Now it is possible to copy bytes directly.
|
||||
try
|
||||
{
|
||||
while (length > 0)
|
||||
{
|
||||
int len = br.input.Read(data, offset, length);
|
||||
if (len == -1)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Unexpected end of input");
|
||||
}
|
||||
offset += len;
|
||||
length -= len;
|
||||
}
|
||||
}
|
||||
catch (System.IO.IOException e)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Failed to read input", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
223
AssetStudio/Brotli/BrotliInputStream.cs
Normal file
223
AssetStudio/Brotli/BrotliInputStream.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="System.IO.Stream"/>
|
||||
/// decorator that decompresses brotli data.
|
||||
/// <p> Not thread-safe.
|
||||
/// </summary>
|
||||
public class BrotliInputStream : System.IO.Stream
|
||||
{
|
||||
public const int DefaultInternalBufferSize = 16384;
|
||||
|
||||
/// <summary>Internal buffer used for efficient byte-by-byte reading.</summary>
|
||||
private byte[] buffer;
|
||||
|
||||
/// <summary>Number of decoded but still unused bytes in internal buffer.</summary>
|
||||
private int remainingBufferBytes;
|
||||
|
||||
/// <summary>Next unused byte offset.</summary>
|
||||
private int bufferOffset;
|
||||
|
||||
/// <summary>Decoder state.</summary>
|
||||
private readonly Org.Brotli.Dec.State state = new Org.Brotli.Dec.State();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a
|
||||
/// <see cref="System.IO.Stream"/>
|
||||
/// wrapper that decompresses brotli data.
|
||||
/// <p> For byte-by-byte reading (
|
||||
/// <see cref="ReadByte()"/>
|
||||
/// ) internal buffer with
|
||||
/// <see cref="DefaultInternalBufferSize"/>
|
||||
/// size is allocated and used.
|
||||
/// <p> Will block the thread until first kilobyte of data of source is available.
|
||||
/// </summary>
|
||||
/// <param name="source">underlying data source</param>
|
||||
/// <exception cref="System.IO.IOException">in case of corrupted data or source stream problems</exception>
|
||||
public BrotliInputStream(System.IO.Stream source)
|
||||
: this(source, DefaultInternalBufferSize, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a
|
||||
/// <see cref="System.IO.Stream"/>
|
||||
/// wrapper that decompresses brotli data.
|
||||
/// <p> For byte-by-byte reading (
|
||||
/// <see cref="ReadByte()"/>
|
||||
/// ) internal buffer of specified size is
|
||||
/// allocated and used.
|
||||
/// <p> Will block the thread until first kilobyte of data of source is available.
|
||||
/// </summary>
|
||||
/// <param name="source">compressed data source</param>
|
||||
/// <param name="byteReadBufferSize">
|
||||
/// size of internal buffer used in case of
|
||||
/// byte-by-byte reading
|
||||
/// </param>
|
||||
/// <exception cref="System.IO.IOException">in case of corrupted data or source stream problems</exception>
|
||||
public BrotliInputStream(System.IO.Stream source, int byteReadBufferSize)
|
||||
: this(source, byteReadBufferSize, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a
|
||||
/// <see cref="System.IO.Stream"/>
|
||||
/// wrapper that decompresses brotli data.
|
||||
/// <p> For byte-by-byte reading (
|
||||
/// <see cref="ReadByte()"/>
|
||||
/// ) internal buffer of specified size is
|
||||
/// allocated and used.
|
||||
/// <p> Will block the thread until first kilobyte of data of source is available.
|
||||
/// </summary>
|
||||
/// <param name="source">compressed data source</param>
|
||||
/// <param name="byteReadBufferSize">
|
||||
/// size of internal buffer used in case of
|
||||
/// byte-by-byte reading
|
||||
/// </param>
|
||||
/// <param name="customDictionary">
|
||||
/// custom dictionary data;
|
||||
/// <see langword="null"/>
|
||||
/// if not used
|
||||
/// </param>
|
||||
/// <exception cref="System.IO.IOException">in case of corrupted data or source stream problems</exception>
|
||||
public BrotliInputStream(System.IO.Stream source, int byteReadBufferSize, byte[] customDictionary)
|
||||
{
|
||||
if (byteReadBufferSize <= 0)
|
||||
{
|
||||
throw new System.ArgumentException("Bad buffer size:" + byteReadBufferSize);
|
||||
}
|
||||
else if (source == null)
|
||||
{
|
||||
throw new System.ArgumentException("source is null");
|
||||
}
|
||||
this.buffer = new byte[byteReadBufferSize];
|
||||
this.remainingBufferBytes = 0;
|
||||
this.bufferOffset = 0;
|
||||
try
|
||||
{
|
||||
Org.Brotli.Dec.State.SetInput(state, source);
|
||||
}
|
||||
catch (Org.Brotli.Dec.BrotliRuntimeException ex)
|
||||
{
|
||||
throw new System.IO.IOException("Brotli decoder initialization failed", ex);
|
||||
}
|
||||
if (customDictionary != null)
|
||||
{
|
||||
Org.Brotli.Dec.Decode.SetCustomDictionary(state, customDictionary);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritDoc/></summary>
|
||||
/// <exception cref="System.IO.IOException"/>
|
||||
public override void Close()
|
||||
{
|
||||
Org.Brotli.Dec.State.Close(state);
|
||||
}
|
||||
|
||||
/// <summary><inheritDoc/></summary>
|
||||
/// <exception cref="System.IO.IOException"/>
|
||||
public override int ReadByte()
|
||||
{
|
||||
if (bufferOffset >= remainingBufferBytes)
|
||||
{
|
||||
remainingBufferBytes = Read(buffer, 0, buffer.Length);
|
||||
bufferOffset = 0;
|
||||
if (remainingBufferBytes == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return buffer[bufferOffset++] & unchecked((int)(0xFF));
|
||||
}
|
||||
|
||||
/// <summary><inheritDoc/></summary>
|
||||
/// <exception cref="System.IO.IOException"/>
|
||||
public override int Read(byte[] destBuffer, int destOffset, int destLen)
|
||||
{
|
||||
if (destOffset < 0)
|
||||
{
|
||||
throw new System.ArgumentException("Bad offset: " + destOffset);
|
||||
}
|
||||
else if (destLen < 0)
|
||||
{
|
||||
throw new System.ArgumentException("Bad length: " + destLen);
|
||||
}
|
||||
else if (destOffset + destLen > destBuffer.Length)
|
||||
{
|
||||
throw new System.ArgumentException("Buffer overflow: " + (destOffset + destLen) + " > " + destBuffer.Length);
|
||||
}
|
||||
else if (destLen == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int copyLen = System.Math.Max(remainingBufferBytes - bufferOffset, 0);
|
||||
if (copyLen != 0)
|
||||
{
|
||||
copyLen = System.Math.Min(copyLen, destLen);
|
||||
System.Array.Copy(buffer, bufferOffset, destBuffer, destOffset, copyLen);
|
||||
bufferOffset += copyLen;
|
||||
destOffset += copyLen;
|
||||
destLen -= copyLen;
|
||||
if (destLen == 0)
|
||||
{
|
||||
return copyLen;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
state.output = destBuffer;
|
||||
state.outputOffset = destOffset;
|
||||
state.outputLength = destLen;
|
||||
state.outputUsed = 0;
|
||||
Org.Brotli.Dec.Decode.Decompress(state);
|
||||
if (state.outputUsed == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return state.outputUsed + copyLen;
|
||||
}
|
||||
catch (Org.Brotli.Dec.BrotliRuntimeException ex)
|
||||
{
|
||||
throw new System.IO.IOException("Brotli stream decoding failed", ex);
|
||||
}
|
||||
}
|
||||
// <{[INJECTED CODE]}>
|
||||
public override bool CanRead {
|
||||
get {return true;}
|
||||
}
|
||||
|
||||
public override bool CanSeek {
|
||||
get {return false;}
|
||||
}
|
||||
public override long Length {
|
||||
get {throw new System.NotSupportedException();}
|
||||
}
|
||||
public override long Position {
|
||||
get {throw new System.NotSupportedException();}
|
||||
set {throw new System.NotSupportedException();}
|
||||
}
|
||||
public override long Seek(long offset, System.IO.SeekOrigin origin) {
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
public override void SetLength(long value){
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public override bool CanWrite{get{return false;}}
|
||||
public override System.IAsyncResult BeginWrite(byte[] buffer, int offset,
|
||||
int count, System.AsyncCallback callback, object state) {
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
public override void Write(byte[] buffer, int offset, int count) {
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Flush() {}
|
||||
}
|
||||
}
|
||||
22
AssetStudio/Brotli/BrotliRuntimeException.cs
Normal file
22
AssetStudio/Brotli/BrotliRuntimeException.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Unchecked exception used internally.</summary>
|
||||
[System.Serializable]
|
||||
internal class BrotliRuntimeException : System.Exception
|
||||
{
|
||||
internal BrotliRuntimeException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
internal BrotliRuntimeException(string message, System.Exception cause)
|
||||
: base(message, cause)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
57
AssetStudio/Brotli/Context.cs
Normal file
57
AssetStudio/Brotli/Context.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Common context lookup table for all context modes.</summary>
|
||||
internal sealed class Context
|
||||
{
|
||||
internal 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
|
||||
, 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
|
||||
, 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,
|
||||
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, 2, 3, 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, 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,
|
||||
1, 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,
|
||||
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, 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,
|
||||
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, 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,
|
||||
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, 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,
|
||||
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, 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,
|
||||
6, 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,
|
||||
16, 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,
|
||||
24, 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,
|
||||
32, 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,
|
||||
40, 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
|
||||
, 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,
|
||||
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, 34, 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, 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, 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,
|
||||
10, 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,
|
||||
25, 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,
|
||||
40, 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,
|
||||
55, 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,
|
||||
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, 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, 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 };
|
||||
|
||||
internal static readonly int[] LookupOffsets = new int[] { 1024, 1536, 1280, 1536, 0, 256, 768, 512 };
|
||||
// CONTEXT_UTF8, last byte.
|
||||
// ASCII range.
|
||||
// UTF8 continuation byte range.
|
||||
// UTF8 lead byte range.
|
||||
// CONTEXT_UTF8 second last byte.
|
||||
// ASCII range.
|
||||
// UTF8 continuation byte range.
|
||||
// UTF8 lead byte range.
|
||||
// CONTEXT_SIGNED, second last byte.
|
||||
// CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits.
|
||||
// CONTEXT_LSB6, last byte.
|
||||
// CONTEXT_MSB6, last byte.
|
||||
// CONTEXT_{M,L}SB6, second last byte,
|
||||
// CONTEXT_LSB6
|
||||
// CONTEXT_MSB6
|
||||
// CONTEXT_UTF8
|
||||
// CONTEXT_SIGNED
|
||||
}
|
||||
}
|
||||
992
AssetStudio/Brotli/Decode.cs
Normal file
992
AssetStudio/Brotli/Decode.cs
Normal file
@@ -0,0 +1,992 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>API for Brotli decompression.</summary>
|
||||
internal sealed class Decode
|
||||
{
|
||||
private const int DefaultCodeLength = 8;
|
||||
|
||||
private const int CodeLengthRepeatCode = 16;
|
||||
|
||||
private const int NumLiteralCodes = 256;
|
||||
|
||||
private const int NumInsertAndCopyCodes = 704;
|
||||
|
||||
private const int NumBlockLengthCodes = 26;
|
||||
|
||||
private const int LiteralContextBits = 6;
|
||||
|
||||
private const int DistanceContextBits = 2;
|
||||
|
||||
private const int HuffmanTableBits = 8;
|
||||
|
||||
private const int HuffmanTableMask = unchecked((int)(0xFF));
|
||||
|
||||
private const int CodeLengthCodes = 18;
|
||||
|
||||
private static readonly int[] CodeLengthCodeOrder = new int[] { 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
|
||||
private const int NumDistanceShortCodes = 16;
|
||||
|
||||
private static readonly int[] DistanceShortCodeIndexOffset = new int[] { 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
|
||||
|
||||
private static readonly int[] DistanceShortCodeValueOffset = new int[] { 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3 };
|
||||
|
||||
/// <summary>Static Huffman code for the code length code lengths.</summary>
|
||||
private 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
|
||||
)), 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
|
||||
)(0x040005)) };
|
||||
|
||||
/// <summary>Decodes a number in the range [0..255], by reading 1 - 11 bits.</summary>
|
||||
private static int DecodeVarLenUnsignedByte(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
if (Org.Brotli.Dec.BitReader.ReadBits(br, 1) != 0)
|
||||
{
|
||||
int n = Org.Brotli.Dec.BitReader.ReadBits(br, 3);
|
||||
if (n == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Org.Brotli.Dec.BitReader.ReadBits(br, n) + (1 << n);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void DecodeMetaBlockLength(Org.Brotli.Dec.BitReader br, Org.Brotli.Dec.State state)
|
||||
{
|
||||
state.inputEnd = Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1;
|
||||
state.metaBlockLength = 0;
|
||||
state.isUncompressed = false;
|
||||
state.isMetadata = false;
|
||||
if (state.inputEnd && Org.Brotli.Dec.BitReader.ReadBits(br, 1) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int sizeNibbles = Org.Brotli.Dec.BitReader.ReadBits(br, 2) + 4;
|
||||
if (sizeNibbles == 7)
|
||||
{
|
||||
state.isMetadata = true;
|
||||
if (Org.Brotli.Dec.BitReader.ReadBits(br, 1) != 0)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Corrupted reserved bit");
|
||||
}
|
||||
int sizeBytes = Org.Brotli.Dec.BitReader.ReadBits(br, 2);
|
||||
if (sizeBytes == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < sizeBytes; i++)
|
||||
{
|
||||
int bits = Org.Brotli.Dec.BitReader.ReadBits(br, 8);
|
||||
if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Exuberant nibble");
|
||||
}
|
||||
state.metaBlockLength |= bits << (i * 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < sizeNibbles; i++)
|
||||
{
|
||||
int bits = Org.Brotli.Dec.BitReader.ReadBits(br, 4);
|
||||
if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Exuberant nibble");
|
||||
}
|
||||
state.metaBlockLength |= bits << (i * 4);
|
||||
}
|
||||
}
|
||||
state.metaBlockLength++;
|
||||
if (!state.inputEnd)
|
||||
{
|
||||
state.isUncompressed = Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Decodes the next Huffman code from bit-stream.</summary>
|
||||
private static int ReadSymbol(int[] table, int offset, Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
int val = (int)((long)(((ulong)br.accumulator) >> br.bitOffset));
|
||||
offset += val & HuffmanTableMask;
|
||||
int bits = table[offset] >> 16;
|
||||
int sym = table[offset] & unchecked((int)(0xFFFF));
|
||||
if (bits <= HuffmanTableBits)
|
||||
{
|
||||
br.bitOffset += bits;
|
||||
return sym;
|
||||
}
|
||||
offset += sym;
|
||||
int mask = (1 << bits) - 1;
|
||||
offset += (int)(((uint)(val & mask)) >> HuffmanTableBits);
|
||||
br.bitOffset += ((table[offset] >> 16) + HuffmanTableBits);
|
||||
return table[offset] & unchecked((int)(0xFFFF));
|
||||
}
|
||||
|
||||
private static int ReadBlockLength(int[] table, int offset, Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
int code = ReadSymbol(table, offset, br);
|
||||
int n = Org.Brotli.Dec.Prefix.BlockLengthNBits[code];
|
||||
return Org.Brotli.Dec.Prefix.BlockLengthOffset[code] + Org.Brotli.Dec.BitReader.ReadBits(br, n);
|
||||
}
|
||||
|
||||
private static int TranslateShortCodes(int code, int[] ringBuffer, int index)
|
||||
{
|
||||
if (code < NumDistanceShortCodes)
|
||||
{
|
||||
index += DistanceShortCodeIndexOffset[code];
|
||||
index &= 3;
|
||||
return ringBuffer[index] + DistanceShortCodeValueOffset[code];
|
||||
}
|
||||
return code - NumDistanceShortCodes + 1;
|
||||
}
|
||||
|
||||
private static void MoveToFront(int[] v, int index)
|
||||
{
|
||||
int value = v[index];
|
||||
for (; index > 0; index--)
|
||||
{
|
||||
v[index] = v[index - 1];
|
||||
}
|
||||
v[0] = value;
|
||||
}
|
||||
|
||||
private static void InverseMoveToFrontTransform(byte[] v, int vLen)
|
||||
{
|
||||
int[] mtf = new int[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
mtf[i] = i;
|
||||
}
|
||||
for (int i = 0; i < vLen; i++)
|
||||
{
|
||||
int index = v[i] & unchecked((int)(0xFF));
|
||||
v[i] = unchecked((byte)mtf[index]);
|
||||
if (index != 0)
|
||||
{
|
||||
MoveToFront(mtf, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReadHuffmanCodeLengths(int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths, Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
int symbol = 0;
|
||||
int prevCodeLen = DefaultCodeLength;
|
||||
int repeat = 0;
|
||||
int repeatCodeLen = 0;
|
||||
int space = 32768;
|
||||
int[] table = new int[32];
|
||||
Org.Brotli.Dec.Huffman.BuildHuffmanTable(table, 0, 5, codeLengthCodeLengths, CodeLengthCodes);
|
||||
while (symbol < numSymbols && space > 0)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
int p = (int)(((long)(((ulong)br.accumulator) >> br.bitOffset))) & 31;
|
||||
br.bitOffset += table[p] >> 16;
|
||||
int codeLen = table[p] & unchecked((int)(0xFFFF));
|
||||
if (codeLen < CodeLengthRepeatCode)
|
||||
{
|
||||
repeat = 0;
|
||||
codeLengths[symbol++] = codeLen;
|
||||
if (codeLen != 0)
|
||||
{
|
||||
prevCodeLen = codeLen;
|
||||
space -= 32768 >> codeLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int extraBits = codeLen - 14;
|
||||
int newLen = 0;
|
||||
if (codeLen == CodeLengthRepeatCode)
|
||||
{
|
||||
newLen = prevCodeLen;
|
||||
}
|
||||
if (repeatCodeLen != newLen)
|
||||
{
|
||||
repeat = 0;
|
||||
repeatCodeLen = newLen;
|
||||
}
|
||||
int oldRepeat = repeat;
|
||||
if (repeat > 0)
|
||||
{
|
||||
repeat -= 2;
|
||||
repeat <<= extraBits;
|
||||
}
|
||||
repeat += Org.Brotli.Dec.BitReader.ReadBits(br, extraBits) + 3;
|
||||
int repeatDelta = repeat - oldRepeat;
|
||||
if (symbol + repeatDelta > numSymbols)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("symbol + repeatDelta > numSymbols");
|
||||
}
|
||||
// COV_NF_LINE
|
||||
for (int i = 0; i < repeatDelta; i++)
|
||||
{
|
||||
codeLengths[symbol++] = repeatCodeLen;
|
||||
}
|
||||
if (repeatCodeLen != 0)
|
||||
{
|
||||
space -= repeatDelta << (15 - repeatCodeLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (space != 0)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Unused space");
|
||||
}
|
||||
// COV_NF_LINE
|
||||
// TODO: Pass max_symbol to Huffman table builder instead?
|
||||
Org.Brotli.Dec.Utils.FillWithZeroes(codeLengths, symbol, numSymbols - symbol);
|
||||
}
|
||||
|
||||
// TODO: Use specialized versions for smaller tables.
|
||||
internal static void ReadHuffmanCode(int alphabetSize, int[] table, int offset, Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
bool ok = true;
|
||||
int simpleCodeOrSkip;
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
// TODO: Avoid allocation.
|
||||
int[] codeLengths = new int[alphabetSize];
|
||||
simpleCodeOrSkip = Org.Brotli.Dec.BitReader.ReadBits(br, 2);
|
||||
if (simpleCodeOrSkip == 1)
|
||||
{
|
||||
// Read symbols, codes & code lengths directly.
|
||||
int maxBitsCounter = alphabetSize - 1;
|
||||
int maxBits = 0;
|
||||
int[] symbols = new int[4];
|
||||
int numSymbols = Org.Brotli.Dec.BitReader.ReadBits(br, 2) + 1;
|
||||
while (maxBitsCounter != 0)
|
||||
{
|
||||
maxBitsCounter >>= 1;
|
||||
maxBits++;
|
||||
}
|
||||
// TODO: uncomment when codeLengths is reused.
|
||||
// Utils.fillWithZeroes(codeLengths, 0, alphabetSize);
|
||||
for (int i = 0; i < numSymbols; i++)
|
||||
{
|
||||
symbols[i] = Org.Brotli.Dec.BitReader.ReadBits(br, maxBits) % alphabetSize;
|
||||
codeLengths[symbols[i]] = 2;
|
||||
}
|
||||
codeLengths[symbols[0]] = 1;
|
||||
switch (numSymbols)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
ok = symbols[0] != symbols[1];
|
||||
codeLengths[symbols[1]] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
ok = symbols[0] != symbols[1] && symbols[0] != symbols[2] && symbols[1] != symbols[2];
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
default:
|
||||
{
|
||||
ok = symbols[0] != symbols[1] && symbols[0] != symbols[2] && symbols[0] != symbols[3] && symbols[1] != symbols[2] && symbols[1] != symbols[3] && symbols[2] != symbols[3];
|
||||
if (Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1)
|
||||
{
|
||||
codeLengths[symbols[2]] = 3;
|
||||
codeLengths[symbols[3]] = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
codeLengths[symbols[0]] = 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decode Huffman-coded code lengths.
|
||||
int[] codeLengthCodeLengths = new int[CodeLengthCodes];
|
||||
int space = 32;
|
||||
int numCodes = 0;
|
||||
for (int i = simpleCodeOrSkip; i < CodeLengthCodes && space > 0; i++)
|
||||
{
|
||||
int codeLenIdx = CodeLengthCodeOrder[i];
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
int p = (int)((long)(((ulong)br.accumulator) >> br.bitOffset)) & 15;
|
||||
// TODO: Demultiplex FIXED_TABLE.
|
||||
br.bitOffset += FixedTable[p] >> 16;
|
||||
int v = FixedTable[p] & unchecked((int)(0xFFFF));
|
||||
codeLengthCodeLengths[codeLenIdx] = v;
|
||||
if (v != 0)
|
||||
{
|
||||
space -= (32 >> v);
|
||||
numCodes++;
|
||||
}
|
||||
}
|
||||
ok = (numCodes == 1 || space == 0);
|
||||
ReadHuffmanCodeLengths(codeLengthCodeLengths, alphabetSize, codeLengths, br);
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Can't readHuffmanCode");
|
||||
}
|
||||
// COV_NF_LINE
|
||||
Org.Brotli.Dec.Huffman.BuildHuffmanTable(table, offset, HuffmanTableBits, codeLengths, alphabetSize);
|
||||
}
|
||||
|
||||
private static int DecodeContextMap(int contextMapSize, byte[] contextMap, Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
int numTrees = DecodeVarLenUnsignedByte(br) + 1;
|
||||
if (numTrees == 1)
|
||||
{
|
||||
Org.Brotli.Dec.Utils.FillWithZeroes(contextMap, 0, contextMapSize);
|
||||
return numTrees;
|
||||
}
|
||||
bool useRleForZeros = Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1;
|
||||
int maxRunLengthPrefix = 0;
|
||||
if (useRleForZeros)
|
||||
{
|
||||
maxRunLengthPrefix = Org.Brotli.Dec.BitReader.ReadBits(br, 4) + 1;
|
||||
}
|
||||
int[] table = new int[Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];
|
||||
ReadHuffmanCode(numTrees + maxRunLengthPrefix, table, 0, br);
|
||||
for (int i = 0; i < contextMapSize; )
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
int code = ReadSymbol(table, 0, br);
|
||||
if (code == 0)
|
||||
{
|
||||
contextMap[i] = 0;
|
||||
i++;
|
||||
}
|
||||
else if (code <= maxRunLengthPrefix)
|
||||
{
|
||||
int reps = (1 << code) + Org.Brotli.Dec.BitReader.ReadBits(br, code);
|
||||
while (reps != 0)
|
||||
{
|
||||
if (i >= contextMapSize)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Corrupted context map");
|
||||
}
|
||||
// COV_NF_LINE
|
||||
contextMap[i] = 0;
|
||||
i++;
|
||||
reps--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
contextMap[i] = unchecked((byte)(code - maxRunLengthPrefix));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 1)
|
||||
{
|
||||
InverseMoveToFrontTransform(contextMap, contextMapSize);
|
||||
}
|
||||
return numTrees;
|
||||
}
|
||||
|
||||
private static void DecodeBlockTypeAndLength(Org.Brotli.Dec.State state, int treeType)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader br = state.br;
|
||||
int[] ringBuffers = state.blockTypeRb;
|
||||
int offset = treeType * 2;
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
int blockType = ReadSymbol(state.blockTypeTrees, treeType * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);
|
||||
state.blockLength[treeType] = ReadBlockLength(state.blockLenTrees, treeType * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);
|
||||
if (blockType == 1)
|
||||
{
|
||||
blockType = ringBuffers[offset + 1] + 1;
|
||||
}
|
||||
else if (blockType == 0)
|
||||
{
|
||||
blockType = ringBuffers[offset];
|
||||
}
|
||||
else
|
||||
{
|
||||
blockType -= 2;
|
||||
}
|
||||
if (blockType >= state.numBlockTypes[treeType])
|
||||
{
|
||||
blockType -= state.numBlockTypes[treeType];
|
||||
}
|
||||
ringBuffers[offset] = ringBuffers[offset + 1];
|
||||
ringBuffers[offset + 1] = blockType;
|
||||
}
|
||||
|
||||
private static void DecodeLiteralBlockSwitch(Org.Brotli.Dec.State state)
|
||||
{
|
||||
DecodeBlockTypeAndLength(state, 0);
|
||||
int literalBlockType = state.blockTypeRb[1];
|
||||
state.contextMapSlice = literalBlockType << LiteralContextBits;
|
||||
state.literalTreeIndex = state.contextMap[state.contextMapSlice] & unchecked((int)(0xFF));
|
||||
state.literalTree = state.hGroup0.trees[state.literalTreeIndex];
|
||||
int contextMode = state.contextModes[literalBlockType];
|
||||
state.contextLookupOffset1 = Org.Brotli.Dec.Context.LookupOffsets[contextMode];
|
||||
state.contextLookupOffset2 = Org.Brotli.Dec.Context.LookupOffsets[contextMode + 1];
|
||||
}
|
||||
|
||||
private static void DecodeCommandBlockSwitch(Org.Brotli.Dec.State state)
|
||||
{
|
||||
DecodeBlockTypeAndLength(state, 1);
|
||||
state.treeCommandOffset = state.hGroup1.trees[state.blockTypeRb[3]];
|
||||
}
|
||||
|
||||
private static void DecodeDistanceBlockSwitch(Org.Brotli.Dec.State state)
|
||||
{
|
||||
DecodeBlockTypeAndLength(state, 2);
|
||||
state.distContextMapSlice = state.blockTypeRb[5] << DistanceContextBits;
|
||||
}
|
||||
|
||||
private static void MaybeReallocateRingBuffer(Org.Brotli.Dec.State state)
|
||||
{
|
||||
int newSize = state.maxRingBufferSize;
|
||||
if ((long)newSize > state.expectedTotalSize)
|
||||
{
|
||||
/* TODO: Handle 2GB+ cases more gracefully. */
|
||||
int minimalNewSize = (int)state.expectedTotalSize + state.customDictionary.Length;
|
||||
while ((newSize >> 1) > minimalNewSize)
|
||||
{
|
||||
newSize >>= 1;
|
||||
}
|
||||
if (!state.inputEnd && newSize < 16384 && state.maxRingBufferSize >= 16384)
|
||||
{
|
||||
newSize = 16384;
|
||||
}
|
||||
}
|
||||
if (newSize <= state.ringBufferSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int ringBufferSizeWithSlack = newSize + Org.Brotli.Dec.Dictionary.MaxTransformedWordLength;
|
||||
byte[] newBuffer = new byte[ringBufferSizeWithSlack];
|
||||
if (state.ringBuffer != null)
|
||||
{
|
||||
System.Array.Copy(state.ringBuffer, 0, newBuffer, 0, state.ringBufferSize);
|
||||
}
|
||||
else if (state.customDictionary.Length != 0)
|
||||
{
|
||||
/* Prepend custom dictionary, if any. */
|
||||
int length = state.customDictionary.Length;
|
||||
int offset = 0;
|
||||
if (length > state.maxBackwardDistance)
|
||||
{
|
||||
offset = length - state.maxBackwardDistance;
|
||||
length = state.maxBackwardDistance;
|
||||
}
|
||||
System.Array.Copy(state.customDictionary, offset, newBuffer, 0, length);
|
||||
state.pos = length;
|
||||
state.bytesToIgnore = length;
|
||||
}
|
||||
state.ringBuffer = newBuffer;
|
||||
state.ringBufferSize = newSize;
|
||||
}
|
||||
|
||||
/// <summary>Reads next metablock header.</summary>
|
||||
/// <param name="state">decoding state</param>
|
||||
private static void ReadMetablockInfo(Org.Brotli.Dec.State state)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader br = state.br;
|
||||
if (state.inputEnd)
|
||||
{
|
||||
state.nextRunningState = Org.Brotli.Dec.RunningState.Finished;
|
||||
state.bytesToWrite = state.pos;
|
||||
state.bytesWritten = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Write;
|
||||
return;
|
||||
}
|
||||
// TODO: Reset? Do we need this?
|
||||
state.hGroup0.codes = null;
|
||||
state.hGroup0.trees = null;
|
||||
state.hGroup1.codes = null;
|
||||
state.hGroup1.trees = null;
|
||||
state.hGroup2.codes = null;
|
||||
state.hGroup2.trees = null;
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
DecodeMetaBlockLength(br, state);
|
||||
if (state.metaBlockLength == 0 && !state.isMetadata)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (state.isUncompressed || state.isMetadata)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.JumpToByteBoundary(br);
|
||||
state.runningState = state.isMetadata ? Org.Brotli.Dec.RunningState.ReadMetadata : Org.Brotli.Dec.RunningState.CopyUncompressed;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.runningState = Org.Brotli.Dec.RunningState.CompressedBlockStart;
|
||||
}
|
||||
if (state.isMetadata)
|
||||
{
|
||||
return;
|
||||
}
|
||||
state.expectedTotalSize += state.metaBlockLength;
|
||||
if (state.ringBufferSize < state.maxRingBufferSize)
|
||||
{
|
||||
MaybeReallocateRingBuffer(state);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReadMetablockHuffmanCodesAndContextMaps(Org.Brotli.Dec.State state)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader br = state.br;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
state.numBlockTypes[i] = DecodeVarLenUnsignedByte(br) + 1;
|
||||
state.blockLength[i] = 1 << 28;
|
||||
if (state.numBlockTypes[i] > 1)
|
||||
{
|
||||
ReadHuffmanCode(state.numBlockTypes[i] + 2, state.blockTypeTrees, i * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);
|
||||
ReadHuffmanCode(NumBlockLengthCodes, state.blockLenTrees, i * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);
|
||||
state.blockLength[i] = ReadBlockLength(state.blockLenTrees, i * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize, br);
|
||||
}
|
||||
}
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
state.distancePostfixBits = Org.Brotli.Dec.BitReader.ReadBits(br, 2);
|
||||
state.numDirectDistanceCodes = NumDistanceShortCodes + (Org.Brotli.Dec.BitReader.ReadBits(br, 4) << state.distancePostfixBits);
|
||||
state.distancePostfixMask = (1 << state.distancePostfixBits) - 1;
|
||||
int numDistanceCodes = state.numDirectDistanceCodes + (48 << state.distancePostfixBits);
|
||||
// TODO: Reuse?
|
||||
state.contextModes = new byte[state.numBlockTypes[0]];
|
||||
for (int i = 0; i < state.numBlockTypes[0]; )
|
||||
{
|
||||
/* Ensure that less than 256 bits read between readMoreInput. */
|
||||
int limit = System.Math.Min(i + 96, state.numBlockTypes[0]);
|
||||
for (; i < limit; ++i)
|
||||
{
|
||||
state.contextModes[i] = unchecked((byte)(Org.Brotli.Dec.BitReader.ReadBits(br, 2) << 1));
|
||||
}
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
}
|
||||
// TODO: Reuse?
|
||||
state.contextMap = new byte[state.numBlockTypes[0] << LiteralContextBits];
|
||||
int numLiteralTrees = DecodeContextMap(state.numBlockTypes[0] << LiteralContextBits, state.contextMap, br);
|
||||
state.trivialLiteralContext = true;
|
||||
for (int j = 0; j < state.numBlockTypes[0] << LiteralContextBits; j++)
|
||||
{
|
||||
if (state.contextMap[j] != j >> LiteralContextBits)
|
||||
{
|
||||
state.trivialLiteralContext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO: Reuse?
|
||||
state.distContextMap = new byte[state.numBlockTypes[2] << DistanceContextBits];
|
||||
int numDistTrees = DecodeContextMap(state.numBlockTypes[2] << DistanceContextBits, state.distContextMap, br);
|
||||
Org.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup0, NumLiteralCodes, numLiteralTrees);
|
||||
Org.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup1, NumInsertAndCopyCodes, state.numBlockTypes[1]);
|
||||
Org.Brotli.Dec.HuffmanTreeGroup.Init(state.hGroup2, numDistanceCodes, numDistTrees);
|
||||
Org.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup0, br);
|
||||
Org.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup1, br);
|
||||
Org.Brotli.Dec.HuffmanTreeGroup.Decode(state.hGroup2, br);
|
||||
state.contextMapSlice = 0;
|
||||
state.distContextMapSlice = 0;
|
||||
state.contextLookupOffset1 = Org.Brotli.Dec.Context.LookupOffsets[state.contextModes[0]];
|
||||
state.contextLookupOffset2 = Org.Brotli.Dec.Context.LookupOffsets[state.contextModes[0] + 1];
|
||||
state.literalTreeIndex = 0;
|
||||
state.literalTree = state.hGroup0.trees[0];
|
||||
state.treeCommandOffset = state.hGroup1.trees[0];
|
||||
// TODO: == 0?
|
||||
state.blockTypeRb[0] = state.blockTypeRb[2] = state.blockTypeRb[4] = 1;
|
||||
state.blockTypeRb[1] = state.blockTypeRb[3] = state.blockTypeRb[5] = 0;
|
||||
}
|
||||
|
||||
private static void CopyUncompressedData(Org.Brotli.Dec.State state)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader br = state.br;
|
||||
byte[] ringBuffer = state.ringBuffer;
|
||||
// Could happen if block ends at ring buffer end.
|
||||
if (state.metaBlockLength <= 0)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.Reload(br);
|
||||
state.runningState = Org.Brotli.Dec.RunningState.BlockStart;
|
||||
return;
|
||||
}
|
||||
int chunkLength = System.Math.Min(state.ringBufferSize - state.pos, state.metaBlockLength);
|
||||
Org.Brotli.Dec.BitReader.CopyBytes(br, ringBuffer, state.pos, chunkLength);
|
||||
state.metaBlockLength -= chunkLength;
|
||||
state.pos += chunkLength;
|
||||
if (state.pos == state.ringBufferSize)
|
||||
{
|
||||
state.nextRunningState = Org.Brotli.Dec.RunningState.CopyUncompressed;
|
||||
state.bytesToWrite = state.ringBufferSize;
|
||||
state.bytesWritten = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Write;
|
||||
return;
|
||||
}
|
||||
Org.Brotli.Dec.BitReader.Reload(br);
|
||||
state.runningState = Org.Brotli.Dec.RunningState.BlockStart;
|
||||
}
|
||||
|
||||
private static bool WriteRingBuffer(Org.Brotli.Dec.State state)
|
||||
{
|
||||
/* Ignore custom dictionary bytes. */
|
||||
if (state.bytesToIgnore != 0)
|
||||
{
|
||||
state.bytesWritten += state.bytesToIgnore;
|
||||
state.bytesToIgnore = 0;
|
||||
}
|
||||
int toWrite = System.Math.Min(state.outputLength - state.outputUsed, state.bytesToWrite - state.bytesWritten);
|
||||
if (toWrite != 0)
|
||||
{
|
||||
System.Array.Copy(state.ringBuffer, state.bytesWritten, state.output, state.outputOffset + state.outputUsed, toWrite);
|
||||
state.outputUsed += toWrite;
|
||||
state.bytesWritten += toWrite;
|
||||
}
|
||||
return state.outputUsed < state.outputLength;
|
||||
}
|
||||
|
||||
internal static void SetCustomDictionary(Org.Brotli.Dec.State state, byte[] data)
|
||||
{
|
||||
state.customDictionary = (data == null) ? new byte[0] : data;
|
||||
}
|
||||
|
||||
/// <summary>Actual decompress implementation.</summary>
|
||||
internal static void Decompress(Org.Brotli.Dec.State state)
|
||||
{
|
||||
if (state.runningState == Org.Brotli.Dec.RunningState.Uninitialized)
|
||||
{
|
||||
throw new System.InvalidOperationException("Can't decompress until initialized");
|
||||
}
|
||||
if (state.runningState == Org.Brotli.Dec.RunningState.Closed)
|
||||
{
|
||||
throw new System.InvalidOperationException("Can't decompress after close");
|
||||
}
|
||||
Org.Brotli.Dec.BitReader br = state.br;
|
||||
int ringBufferMask = state.ringBufferSize - 1;
|
||||
byte[] ringBuffer = state.ringBuffer;
|
||||
while (state.runningState != Org.Brotli.Dec.RunningState.Finished)
|
||||
{
|
||||
switch (state.runningState)
|
||||
{
|
||||
case Org.Brotli.Dec.RunningState.BlockStart:
|
||||
{
|
||||
// TODO: extract cases to methods for the better readability.
|
||||
if (state.metaBlockLength < 0)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Invalid metablock length");
|
||||
}
|
||||
ReadMetablockInfo(state);
|
||||
/* Ring-buffer would be reallocated here. */
|
||||
ringBufferMask = state.ringBufferSize - 1;
|
||||
ringBuffer = state.ringBuffer;
|
||||
continue;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.CompressedBlockStart:
|
||||
{
|
||||
ReadMetablockHuffmanCodesAndContextMaps(state);
|
||||
state.runningState = Org.Brotli.Dec.RunningState.MainLoop;
|
||||
goto case Org.Brotli.Dec.RunningState.MainLoop;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.MainLoop:
|
||||
{
|
||||
// Fall through
|
||||
if (state.metaBlockLength <= 0)
|
||||
{
|
||||
state.runningState = Org.Brotli.Dec.RunningState.BlockStart;
|
||||
continue;
|
||||
}
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
if (state.blockLength[1] == 0)
|
||||
{
|
||||
DecodeCommandBlockSwitch(state);
|
||||
}
|
||||
state.blockLength[1]--;
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
int cmdCode = ReadSymbol(state.hGroup1.codes, state.treeCommandOffset, br);
|
||||
int rangeIdx = (int)(((uint)cmdCode) >> 6);
|
||||
state.distanceCode = 0;
|
||||
if (rangeIdx >= 2)
|
||||
{
|
||||
rangeIdx -= 2;
|
||||
state.distanceCode = -1;
|
||||
}
|
||||
int insertCode = Org.Brotli.Dec.Prefix.InsertRangeLut[rangeIdx] + (((int)(((uint)cmdCode) >> 3)) & 7);
|
||||
int copyCode = Org.Brotli.Dec.Prefix.CopyRangeLut[rangeIdx] + (cmdCode & 7);
|
||||
state.insertLength = Org.Brotli.Dec.Prefix.InsertLengthOffset[insertCode] + Org.Brotli.Dec.BitReader.ReadBits(br, Org.Brotli.Dec.Prefix.InsertLengthNBits[insertCode]);
|
||||
state.copyLength = Org.Brotli.Dec.Prefix.CopyLengthOffset[copyCode] + Org.Brotli.Dec.BitReader.ReadBits(br, Org.Brotli.Dec.Prefix.CopyLengthNBits[copyCode]);
|
||||
state.j = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.InsertLoop;
|
||||
goto case Org.Brotli.Dec.RunningState.InsertLoop;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.InsertLoop:
|
||||
{
|
||||
// Fall through
|
||||
if (state.trivialLiteralContext)
|
||||
{
|
||||
while (state.j < state.insertLength)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
if (state.blockLength[0] == 0)
|
||||
{
|
||||
DecodeLiteralBlockSwitch(state);
|
||||
}
|
||||
state.blockLength[0]--;
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
ringBuffer[state.pos] = unchecked((byte)ReadSymbol(state.hGroup0.codes, state.literalTree, br));
|
||||
state.j++;
|
||||
if (state.pos++ == ringBufferMask)
|
||||
{
|
||||
state.nextRunningState = Org.Brotli.Dec.RunningState.InsertLoop;
|
||||
state.bytesToWrite = state.ringBufferSize;
|
||||
state.bytesWritten = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Write;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int prevByte1 = ringBuffer[(state.pos - 1) & ringBufferMask] & unchecked((int)(0xFF));
|
||||
int prevByte2 = ringBuffer[(state.pos - 2) & ringBufferMask] & unchecked((int)(0xFF));
|
||||
while (state.j < state.insertLength)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
if (state.blockLength[0] == 0)
|
||||
{
|
||||
DecodeLiteralBlockSwitch(state);
|
||||
}
|
||||
int literalTreeIndex = state.contextMap[state.contextMapSlice + (Org.Brotli.Dec.Context.Lookup[state.contextLookupOffset1 + prevByte1] | Org.Brotli.Dec.Context.Lookup[state.contextLookupOffset2 + prevByte2])] & unchecked((int)(0xFF));
|
||||
state.blockLength[0]--;
|
||||
prevByte2 = prevByte1;
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
prevByte1 = ReadSymbol(state.hGroup0.codes, state.hGroup0.trees[literalTreeIndex], br);
|
||||
ringBuffer[state.pos] = unchecked((byte)prevByte1);
|
||||
state.j++;
|
||||
if (state.pos++ == ringBufferMask)
|
||||
{
|
||||
state.nextRunningState = Org.Brotli.Dec.RunningState.InsertLoop;
|
||||
state.bytesToWrite = state.ringBufferSize;
|
||||
state.bytesWritten = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Write;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.runningState != Org.Brotli.Dec.RunningState.InsertLoop)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
state.metaBlockLength -= state.insertLength;
|
||||
if (state.metaBlockLength <= 0)
|
||||
{
|
||||
state.runningState = Org.Brotli.Dec.RunningState.MainLoop;
|
||||
continue;
|
||||
}
|
||||
if (state.distanceCode < 0)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
if (state.blockLength[2] == 0)
|
||||
{
|
||||
DecodeDistanceBlockSwitch(state);
|
||||
}
|
||||
state.blockLength[2]--;
|
||||
Org.Brotli.Dec.BitReader.FillBitWindow(br);
|
||||
state.distanceCode = ReadSymbol(state.hGroup2.codes, state.hGroup2.trees[state.distContextMap[state.distContextMapSlice + (state.copyLength > 4 ? 3 : state.copyLength - 2)] & unchecked((int)(0xFF))], br);
|
||||
if (state.distanceCode >= state.numDirectDistanceCodes)
|
||||
{
|
||||
state.distanceCode -= state.numDirectDistanceCodes;
|
||||
int postfix = state.distanceCode & state.distancePostfixMask;
|
||||
state.distanceCode = (int)(((uint)state.distanceCode) >> state.distancePostfixBits);
|
||||
int n = ((int)(((uint)state.distanceCode) >> 1)) + 1;
|
||||
int offset = ((2 + (state.distanceCode & 1)) << n) - 4;
|
||||
state.distanceCode = state.numDirectDistanceCodes + postfix + ((offset + Org.Brotli.Dec.BitReader.ReadBits(br, n)) << state.distancePostfixBits);
|
||||
}
|
||||
}
|
||||
// Convert the distance code to the actual distance by possibly looking up past distances
|
||||
// from the ringBuffer.
|
||||
state.distance = TranslateShortCodes(state.distanceCode, state.distRb, state.distRbIdx);
|
||||
if (state.distance < 0)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Negative distance");
|
||||
}
|
||||
// COV_NF_LINE
|
||||
if (state.maxDistance != state.maxBackwardDistance && state.pos < state.maxBackwardDistance)
|
||||
{
|
||||
state.maxDistance = state.pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.maxDistance = state.maxBackwardDistance;
|
||||
}
|
||||
state.copyDst = state.pos;
|
||||
if (state.distance > state.maxDistance)
|
||||
{
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Transform;
|
||||
continue;
|
||||
}
|
||||
if (state.distanceCode > 0)
|
||||
{
|
||||
state.distRb[state.distRbIdx & 3] = state.distance;
|
||||
state.distRbIdx++;
|
||||
}
|
||||
if (state.copyLength > state.metaBlockLength)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Invalid backward reference");
|
||||
}
|
||||
// COV_NF_LINE
|
||||
state.j = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.CopyLoop;
|
||||
goto case Org.Brotli.Dec.RunningState.CopyLoop;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.CopyLoop:
|
||||
{
|
||||
// fall through
|
||||
int src = (state.pos - state.distance) & ringBufferMask;
|
||||
int dst = state.pos;
|
||||
int copyLength = state.copyLength - state.j;
|
||||
if ((src + copyLength < ringBufferMask) && (dst + copyLength < ringBufferMask))
|
||||
{
|
||||
for (int k = 0; k < copyLength; ++k)
|
||||
{
|
||||
ringBuffer[dst++] = ringBuffer[src++];
|
||||
}
|
||||
state.j += copyLength;
|
||||
state.metaBlockLength -= copyLength;
|
||||
state.pos += copyLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; state.j < state.copyLength; )
|
||||
{
|
||||
ringBuffer[state.pos] = ringBuffer[(state.pos - state.distance) & ringBufferMask];
|
||||
state.metaBlockLength--;
|
||||
state.j++;
|
||||
if (state.pos++ == ringBufferMask)
|
||||
{
|
||||
state.nextRunningState = Org.Brotli.Dec.RunningState.CopyLoop;
|
||||
state.bytesToWrite = state.ringBufferSize;
|
||||
state.bytesWritten = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Write;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.runningState == Org.Brotli.Dec.RunningState.CopyLoop)
|
||||
{
|
||||
state.runningState = Org.Brotli.Dec.RunningState.MainLoop;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.Transform:
|
||||
{
|
||||
if (state.copyLength >= Org.Brotli.Dec.Dictionary.MinWordLength && state.copyLength <= Org.Brotli.Dec.Dictionary.MaxWordLength)
|
||||
{
|
||||
int offset = Org.Brotli.Dec.Dictionary.OffsetsByLength[state.copyLength];
|
||||
int wordId = state.distance - state.maxDistance - 1;
|
||||
int shift = Org.Brotli.Dec.Dictionary.SizeBitsByLength[state.copyLength];
|
||||
int mask = (1 << shift) - 1;
|
||||
int wordIdx = wordId & mask;
|
||||
int transformIdx = (int)(((uint)wordId) >> shift);
|
||||
offset += wordIdx * state.copyLength;
|
||||
if (transformIdx < Org.Brotli.Dec.Transform.Transforms.Length)
|
||||
{
|
||||
int len = Org.Brotli.Dec.Transform.TransformDictionaryWord(ringBuffer, state.copyDst, Org.Brotli.Dec.Dictionary.GetData(), offset, state.copyLength, Org.Brotli.Dec.Transform.Transforms[transformIdx]);
|
||||
state.copyDst += len;
|
||||
state.pos += len;
|
||||
state.metaBlockLength -= len;
|
||||
if (state.copyDst >= state.ringBufferSize)
|
||||
{
|
||||
state.nextRunningState = Org.Brotli.Dec.RunningState.CopyWrapBuffer;
|
||||
state.bytesToWrite = state.ringBufferSize;
|
||||
state.bytesWritten = 0;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Write;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Invalid backward reference");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// COV_NF_LINE
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Invalid backward reference");
|
||||
}
|
||||
// COV_NF_LINE
|
||||
state.runningState = Org.Brotli.Dec.RunningState.MainLoop;
|
||||
continue;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.CopyWrapBuffer:
|
||||
{
|
||||
System.Array.Copy(ringBuffer, state.ringBufferSize, ringBuffer, 0, state.copyDst - state.ringBufferSize);
|
||||
state.runningState = Org.Brotli.Dec.RunningState.MainLoop;
|
||||
continue;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.ReadMetadata:
|
||||
{
|
||||
while (state.metaBlockLength > 0)
|
||||
{
|
||||
Org.Brotli.Dec.BitReader.ReadMoreInput(br);
|
||||
// Optimize
|
||||
Org.Brotli.Dec.BitReader.ReadBits(br, 8);
|
||||
state.metaBlockLength--;
|
||||
}
|
||||
state.runningState = Org.Brotli.Dec.RunningState.BlockStart;
|
||||
continue;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.CopyUncompressed:
|
||||
{
|
||||
CopyUncompressedData(state);
|
||||
continue;
|
||||
}
|
||||
|
||||
case Org.Brotli.Dec.RunningState.Write:
|
||||
{
|
||||
if (!WriteRingBuffer(state))
|
||||
{
|
||||
// Output buffer is full.
|
||||
return;
|
||||
}
|
||||
if (state.pos >= state.maxBackwardDistance)
|
||||
{
|
||||
state.maxDistance = state.maxBackwardDistance;
|
||||
}
|
||||
state.pos &= ringBufferMask;
|
||||
state.runningState = state.nextRunningState;
|
||||
continue;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Unexpected state " + state.runningState);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.runningState == Org.Brotli.Dec.RunningState.Finished)
|
||||
{
|
||||
if (state.metaBlockLength < 0)
|
||||
{
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Invalid metablock length");
|
||||
}
|
||||
Org.Brotli.Dec.BitReader.JumpToByteBoundary(br);
|
||||
Org.Brotli.Dec.BitReader.CheckHealth(state.br, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
97
AssetStudio/Brotli/Dictionary.cs
Normal file
97
AssetStudio/Brotli/Dictionary.cs
Normal file
File diff suppressed because one or more lines are too long
149
AssetStudio/Brotli/Huffman.cs
Normal file
149
AssetStudio/Brotli/Huffman.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Utilities for building Huffman decoding tables.</summary>
|
||||
internal sealed class Huffman
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum possible Huffman table size for an alphabet size of 704, max code length 15 and root
|
||||
/// table bits 8.
|
||||
/// </summary>
|
||||
internal const int HuffmanMaxTableSize = 1080;
|
||||
|
||||
private const int MaxLength = 15;
|
||||
|
||||
/// <summary>Returns reverse(reverse(key, len) + 1, len).</summary>
|
||||
/// <remarks>
|
||||
/// Returns reverse(reverse(key, len) + 1, len).
|
||||
/// <p> reverse(key, len) is the bit-wise reversal of the len least significant bits of key.
|
||||
/// </remarks>
|
||||
private static int GetNextKey(int key, int len)
|
||||
{
|
||||
int step = 1 << (len - 1);
|
||||
while ((key & step) != 0)
|
||||
{
|
||||
step >>= 1;
|
||||
}
|
||||
return (key & (step - 1)) + step;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores
|
||||
/// <paramref name="item"/>
|
||||
/// in
|
||||
/// <c>table[0], table[step], table[2 * step] .., table[end]</c>
|
||||
/// .
|
||||
/// <p> Assumes that end is an integer multiple of step.
|
||||
/// </summary>
|
||||
private static void ReplicateValue(int[] table, int offset, int step, int end, int item)
|
||||
{
|
||||
do
|
||||
{
|
||||
end -= step;
|
||||
table[offset + end] = item;
|
||||
}
|
||||
while (end > 0);
|
||||
}
|
||||
|
||||
/// <param name="count">histogram of bit lengths for the remaining symbols,</param>
|
||||
/// <param name="len">code length of the next processed symbol.</param>
|
||||
/// <returns>table width of the next 2nd level table.</returns>
|
||||
private static int NextTableBitSize(int[] count, int len, int rootBits)
|
||||
{
|
||||
int left = 1 << (len - rootBits);
|
||||
while (len < MaxLength)
|
||||
{
|
||||
left -= count[len];
|
||||
if (left <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
len++;
|
||||
left <<= 1;
|
||||
}
|
||||
return len - rootBits;
|
||||
}
|
||||
|
||||
/// <summary>Builds Huffman lookup table assuming code lengths are in symbol order.</summary>
|
||||
internal static void BuildHuffmanTable(int[] rootTable, int tableOffset, int rootBits, int[] codeLengths, int codeLengthsSize)
|
||||
{
|
||||
int key;
|
||||
// Reversed prefix code.
|
||||
int[] sorted = new int[codeLengthsSize];
|
||||
// Symbols sorted by code length.
|
||||
// TODO: fill with zeroes?
|
||||
int[] count = new int[MaxLength + 1];
|
||||
// Number of codes of each length.
|
||||
int[] offset = new int[MaxLength + 1];
|
||||
// Offsets in sorted table for each length.
|
||||
int symbol;
|
||||
// Build histogram of code lengths.
|
||||
for (symbol = 0; symbol < codeLengthsSize; symbol++)
|
||||
{
|
||||
count[codeLengths[symbol]]++;
|
||||
}
|
||||
// Generate offsets into sorted symbol table by code length.
|
||||
offset[1] = 0;
|
||||
for (int len = 1; len < MaxLength; len++)
|
||||
{
|
||||
offset[len + 1] = offset[len] + count[len];
|
||||
}
|
||||
// Sort symbols by length, by symbol order within each length.
|
||||
for (symbol = 0; symbol < codeLengthsSize; symbol++)
|
||||
{
|
||||
if (codeLengths[symbol] != 0)
|
||||
{
|
||||
sorted[offset[codeLengths[symbol]]++] = symbol;
|
||||
}
|
||||
}
|
||||
int tableBits = rootBits;
|
||||
int tableSize = 1 << tableBits;
|
||||
int totalSize = tableSize;
|
||||
// Special case code with only one value.
|
||||
if (offset[MaxLength] == 1)
|
||||
{
|
||||
for (key = 0; key < totalSize; key++)
|
||||
{
|
||||
rootTable[tableOffset + key] = sorted[0];
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Fill in root table.
|
||||
key = 0;
|
||||
symbol = 0;
|
||||
for (int len = 1, step = 2; len <= rootBits; len++, step <<= 1)
|
||||
{
|
||||
for (; count[len] > 0; count[len]--)
|
||||
{
|
||||
ReplicateValue(rootTable, tableOffset + key, step, tableSize, len << 16 | sorted[symbol++]);
|
||||
key = GetNextKey(key, len);
|
||||
}
|
||||
}
|
||||
// Fill in 2nd level tables and add pointers to root table.
|
||||
int mask = totalSize - 1;
|
||||
int low = -1;
|
||||
int currentOffset = tableOffset;
|
||||
for (int len = rootBits + 1, step = 2; len <= MaxLength; len++, step <<= 1)
|
||||
{
|
||||
for (; count[len] > 0; count[len]--)
|
||||
{
|
||||
if ((key & mask) != low)
|
||||
{
|
||||
currentOffset += tableSize;
|
||||
tableBits = NextTableBitSize(count, len, rootBits);
|
||||
tableSize = 1 << tableBits;
|
||||
totalSize += tableSize;
|
||||
low = key & mask;
|
||||
rootTable[tableOffset + low] = (tableBits + rootBits) << 16 | (currentOffset - tableOffset - low);
|
||||
}
|
||||
ReplicateValue(rootTable, currentOffset + (key >> rootBits), step, tableSize, (len - rootBits) << 16 | sorted[symbol++]);
|
||||
key = GetNextKey(key, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
AssetStudio/Brotli/HuffmanTreeGroup.cs
Normal file
50
AssetStudio/Brotli/HuffmanTreeGroup.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Contains a collection of huffman trees with the same alphabet size.</summary>
|
||||
internal sealed class HuffmanTreeGroup
|
||||
{
|
||||
/// <summary>The maximal alphabet size in this group.</summary>
|
||||
private int alphabetSize;
|
||||
|
||||
/// <summary>Storage for Huffman lookup tables.</summary>
|
||||
internal int[] codes;
|
||||
|
||||
/// <summary>
|
||||
/// Offsets of distinct lookup tables in
|
||||
/// <see cref="codes"/>
|
||||
/// storage.
|
||||
/// </summary>
|
||||
internal int[] trees;
|
||||
|
||||
/// <summary>Initializes the Huffman tree group.</summary>
|
||||
/// <param name="group">POJO to be initialised</param>
|
||||
/// <param name="alphabetSize">the maximal alphabet size in this group</param>
|
||||
/// <param name="n">number of Huffman codes</param>
|
||||
internal static void Init(Org.Brotli.Dec.HuffmanTreeGroup group, int alphabetSize, int n)
|
||||
{
|
||||
group.alphabetSize = alphabetSize;
|
||||
group.codes = new int[n * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];
|
||||
group.trees = new int[n];
|
||||
}
|
||||
|
||||
/// <summary>Decodes Huffman trees from input stream and constructs lookup tables.</summary>
|
||||
/// <param name="group">target POJO</param>
|
||||
/// <param name="br">data source</param>
|
||||
internal static void Decode(Org.Brotli.Dec.HuffmanTreeGroup group, Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
int next = 0;
|
||||
int n = group.trees.Length;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
group.trees[i] = next;
|
||||
Org.Brotli.Dec.Decode.ReadHuffmanCode(group.alphabetSize, group.codes, next, br);
|
||||
next += Org.Brotli.Dec.Huffman.HuffmanMaxTableSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
AssetStudio/Brotli/IntReader.cs
Normal file
36
AssetStudio/Brotli/IntReader.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Byte-to-int conversion magic.</summary>
|
||||
internal sealed class IntReader
|
||||
{
|
||||
private byte[] byteBuffer;
|
||||
|
||||
private int[] intBuffer;
|
||||
|
||||
internal static void Init(Org.Brotli.Dec.IntReader ir, byte[] byteBuffer, int[] intBuffer)
|
||||
{
|
||||
ir.byteBuffer = byteBuffer;
|
||||
ir.intBuffer = intBuffer;
|
||||
}
|
||||
|
||||
/// <summary>Translates bytes to ints.</summary>
|
||||
/// <remarks>
|
||||
/// Translates bytes to ints.
|
||||
/// NB: intLen == 4 * byteSize!
|
||||
/// NB: intLen should be less or equal to intBuffer length.
|
||||
/// </remarks>
|
||||
internal static void Convert(Org.Brotli.Dec.IntReader ir, int intLen)
|
||||
{
|
||||
for (int i = 0; i < intLen; ++i)
|
||||
{
|
||||
ir.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
|
||||
)(0xFF))) << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
AssetStudio/Brotli/Prefix.cs
Normal file
33
AssetStudio/Brotli/Prefix.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Lookup tables to map prefix codes to value ranges.</summary>
|
||||
/// <remarks>
|
||||
/// Lookup tables to map prefix codes to value ranges.
|
||||
/// <p> This is used during decoding of the block lengths, literal insertion lengths and copy
|
||||
/// lengths.
|
||||
/// <p> Range represents values: [offset, offset + 2 ^ n_bits)
|
||||
/// </remarks>
|
||||
internal sealed class Prefix
|
||||
{
|
||||
internal 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 };
|
||||
|
||||
internal 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 };
|
||||
|
||||
internal 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 };
|
||||
|
||||
internal 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 };
|
||||
|
||||
internal 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 };
|
||||
|
||||
internal 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 };
|
||||
|
||||
internal static readonly int[] InsertRangeLut = new int[] { 0, 0, 8, 8, 0, 16, 8, 16, 16 };
|
||||
|
||||
internal static readonly int[] CopyRangeLut = new int[] { 0, 8, 0, 8, 16, 0, 16, 8, 16 };
|
||||
}
|
||||
}
|
||||
37
AssetStudio/Brotli/RunningState.cs
Normal file
37
AssetStudio/Brotli/RunningState.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Enumeration of decoding state-machine.</summary>
|
||||
internal sealed class RunningState
|
||||
{
|
||||
internal const int Uninitialized = 0;
|
||||
|
||||
internal const int BlockStart = 1;
|
||||
|
||||
internal const int CompressedBlockStart = 2;
|
||||
|
||||
internal const int MainLoop = 3;
|
||||
|
||||
internal const int ReadMetadata = 4;
|
||||
|
||||
internal const int CopyUncompressed = 5;
|
||||
|
||||
internal const int InsertLoop = 6;
|
||||
|
||||
internal const int CopyLoop = 7;
|
||||
|
||||
internal const int CopyWrapBuffer = 8;
|
||||
|
||||
internal const int Transform = 9;
|
||||
|
||||
internal const int Finished = 10;
|
||||
|
||||
internal const int Closed = 11;
|
||||
|
||||
internal const int Write = 12;
|
||||
}
|
||||
}
|
||||
171
AssetStudio/Brotli/State.cs
Normal file
171
AssetStudio/Brotli/State.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
internal sealed class State
|
||||
{
|
||||
internal int runningState = Org.Brotli.Dec.RunningState.Uninitialized;
|
||||
|
||||
internal int nextRunningState;
|
||||
|
||||
internal readonly Org.Brotli.Dec.BitReader br = new Org.Brotli.Dec.BitReader();
|
||||
|
||||
internal byte[] ringBuffer;
|
||||
|
||||
internal readonly int[] blockTypeTrees = new int[3 * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];
|
||||
|
||||
internal readonly int[] blockLenTrees = new int[3 * Org.Brotli.Dec.Huffman.HuffmanMaxTableSize];
|
||||
|
||||
internal int metaBlockLength;
|
||||
|
||||
internal bool inputEnd;
|
||||
|
||||
internal bool isUncompressed;
|
||||
|
||||
internal bool isMetadata;
|
||||
|
||||
internal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup0 = new Org.Brotli.Dec.HuffmanTreeGroup();
|
||||
|
||||
internal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup1 = new Org.Brotli.Dec.HuffmanTreeGroup();
|
||||
|
||||
internal readonly Org.Brotli.Dec.HuffmanTreeGroup hGroup2 = new Org.Brotli.Dec.HuffmanTreeGroup();
|
||||
|
||||
internal readonly int[] blockLength = new int[3];
|
||||
|
||||
internal readonly int[] numBlockTypes = new int[3];
|
||||
|
||||
internal readonly int[] blockTypeRb = new int[6];
|
||||
|
||||
internal readonly int[] distRb = new int[] { 16, 15, 11, 4 };
|
||||
|
||||
internal int pos = 0;
|
||||
|
||||
internal int maxDistance = 0;
|
||||
|
||||
internal int distRbIdx = 0;
|
||||
|
||||
internal bool trivialLiteralContext = false;
|
||||
|
||||
internal int literalTreeIndex = 0;
|
||||
|
||||
internal int literalTree;
|
||||
|
||||
internal int j;
|
||||
|
||||
internal int insertLength;
|
||||
|
||||
internal byte[] contextModes;
|
||||
|
||||
internal byte[] contextMap;
|
||||
|
||||
internal int contextMapSlice;
|
||||
|
||||
internal int distContextMapSlice;
|
||||
|
||||
internal int contextLookupOffset1;
|
||||
|
||||
internal int contextLookupOffset2;
|
||||
|
||||
internal int treeCommandOffset;
|
||||
|
||||
internal int distanceCode;
|
||||
|
||||
internal byte[] distContextMap;
|
||||
|
||||
internal int numDirectDistanceCodes;
|
||||
|
||||
internal int distancePostfixMask;
|
||||
|
||||
internal int distancePostfixBits;
|
||||
|
||||
internal int distance;
|
||||
|
||||
internal int copyLength;
|
||||
|
||||
internal int copyDst;
|
||||
|
||||
internal int maxBackwardDistance;
|
||||
|
||||
internal int maxRingBufferSize;
|
||||
|
||||
internal int ringBufferSize = 0;
|
||||
|
||||
internal long expectedTotalSize = 0;
|
||||
|
||||
internal byte[] customDictionary = new byte[0];
|
||||
|
||||
internal int bytesToIgnore = 0;
|
||||
|
||||
internal int outputOffset;
|
||||
|
||||
internal int outputLength;
|
||||
|
||||
internal int outputUsed;
|
||||
|
||||
internal int bytesWritten;
|
||||
|
||||
internal int bytesToWrite;
|
||||
|
||||
internal byte[] output;
|
||||
|
||||
// Current meta-block header information.
|
||||
// TODO: Update to current spec.
|
||||
private static int DecodeWindowBits(Org.Brotli.Dec.BitReader br)
|
||||
{
|
||||
if (Org.Brotli.Dec.BitReader.ReadBits(br, 1) == 0)
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
int n = Org.Brotli.Dec.BitReader.ReadBits(br, 3);
|
||||
if (n != 0)
|
||||
{
|
||||
return 17 + n;
|
||||
}
|
||||
n = Org.Brotli.Dec.BitReader.ReadBits(br, 3);
|
||||
if (n != 0)
|
||||
{
|
||||
return 8 + n;
|
||||
}
|
||||
return 17;
|
||||
}
|
||||
|
||||
/// <summary>Associate input with decoder state.</summary>
|
||||
/// <param name="state">uninitialized state without associated input</param>
|
||||
/// <param name="input">compressed data source</param>
|
||||
internal static void SetInput(Org.Brotli.Dec.State state, System.IO.Stream input)
|
||||
{
|
||||
if (state.runningState != Org.Brotli.Dec.RunningState.Uninitialized)
|
||||
{
|
||||
throw new System.InvalidOperationException("State MUST be uninitialized");
|
||||
}
|
||||
Org.Brotli.Dec.BitReader.Init(state.br, input);
|
||||
int windowBits = DecodeWindowBits(state.br);
|
||||
if (windowBits == 9)
|
||||
{
|
||||
/* Reserved case for future expansion. */
|
||||
throw new Org.Brotli.Dec.BrotliRuntimeException("Invalid 'windowBits' code");
|
||||
}
|
||||
state.maxRingBufferSize = 1 << windowBits;
|
||||
state.maxBackwardDistance = state.maxRingBufferSize - 16;
|
||||
state.runningState = Org.Brotli.Dec.RunningState.BlockStart;
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"/>
|
||||
internal static void Close(Org.Brotli.Dec.State state)
|
||||
{
|
||||
if (state.runningState == Org.Brotli.Dec.RunningState.Uninitialized)
|
||||
{
|
||||
throw new System.InvalidOperationException("State MUST be initialized");
|
||||
}
|
||||
if (state.runningState == Org.Brotli.Dec.RunningState.Closed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
state.runningState = Org.Brotli.Dec.RunningState.Closed;
|
||||
Org.Brotli.Dec.BitReader.Close(state.br);
|
||||
}
|
||||
}
|
||||
}
|
||||
154
AssetStudio/Brotli/Transform.cs
Normal file
154
AssetStudio/Brotli/Transform.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Transformations on dictionary words.</summary>
|
||||
internal sealed class Transform
|
||||
{
|
||||
private readonly byte[] prefix;
|
||||
|
||||
private readonly int type;
|
||||
|
||||
private readonly byte[] suffix;
|
||||
|
||||
internal Transform(string prefix, int type, string suffix)
|
||||
{
|
||||
this.prefix = ReadUniBytes(prefix);
|
||||
this.type = type;
|
||||
this.suffix = ReadUniBytes(suffix);
|
||||
}
|
||||
|
||||
internal static byte[] ReadUniBytes(string uniBytes)
|
||||
{
|
||||
byte[] result = new byte[uniBytes.Length];
|
||||
for (int i = 0; i < result.Length; ++i)
|
||||
{
|
||||
result[i] = unchecked((byte)uniBytes[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal 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,
|
||||
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.OmitFirst1, string.Empty), new Org.Brotli.Dec.Transform
|
||||
(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
|
||||
, 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
|
||||
.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
|
||||
(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
|
||||
, ", "), 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
|
||||
.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,
|
||||
Org.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
|
||||
Org.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
|
||||
.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
|
||||
(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
|
||||
, 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
|
||||
.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
|
||||
(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
|
||||
, " 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
|
||||
(" 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
|
||||
.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
|
||||
(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
|
||||
, 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
|
||||
, 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
|
||||
(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
|
||||
.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
|
||||
(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
|
||||
.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(
|
||||
string.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
|
||||
, "\""), 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
|
||||
.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/",
|
||||
Org.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
|
||||
, "'"), 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
|
||||
.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
|
||||
(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 "
|
||||
), 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
|
||||
.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
|
||||
(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,
|
||||
"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
|
||||
.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
|
||||
(" ", 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, "='"
|
||||
), 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
|
||||
.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
|
||||
, 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
|
||||
, "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(" ",
|
||||
Org.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
|
||||
(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.
|
||||
UppercaseAll, ". "), 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
|
||||
.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
|
||||
.UppercaseFirst, "='") };
|
||||
|
||||
internal static int TransformDictionaryWord(byte[] dst, int dstOffset, byte[] word, int wordOffset, int len, Org.Brotli.Dec.Transform transform)
|
||||
{
|
||||
int offset = dstOffset;
|
||||
// Copy prefix.
|
||||
byte[] @string = transform.prefix;
|
||||
int tmp = @string.Length;
|
||||
int i = 0;
|
||||
// In most cases tmp < 10 -> no benefits from System.arrayCopy
|
||||
while (i < tmp)
|
||||
{
|
||||
dst[offset++] = @string[i++];
|
||||
}
|
||||
// Copy trimmed word.
|
||||
int op = transform.type;
|
||||
tmp = Org.Brotli.Dec.WordTransformType.GetOmitFirst(op);
|
||||
if (tmp > len)
|
||||
{
|
||||
tmp = len;
|
||||
}
|
||||
wordOffset += tmp;
|
||||
len -= tmp;
|
||||
len -= Org.Brotli.Dec.WordTransformType.GetOmitLast(op);
|
||||
i = len;
|
||||
while (i > 0)
|
||||
{
|
||||
dst[offset++] = word[wordOffset++];
|
||||
i--;
|
||||
}
|
||||
if (op == Org.Brotli.Dec.WordTransformType.UppercaseAll || op == Org.Brotli.Dec.WordTransformType.UppercaseFirst)
|
||||
{
|
||||
int uppercaseOffset = offset - len;
|
||||
if (op == Org.Brotli.Dec.WordTransformType.UppercaseFirst)
|
||||
{
|
||||
len = 1;
|
||||
}
|
||||
while (len > 0)
|
||||
{
|
||||
tmp = dst[uppercaseOffset] & unchecked((int)(0xFF));
|
||||
if (tmp < unchecked((int)(0xc0)))
|
||||
{
|
||||
if (tmp >= 'a' && tmp <= 'z')
|
||||
{
|
||||
dst[uppercaseOffset] ^= unchecked((byte)32);
|
||||
}
|
||||
uppercaseOffset += 1;
|
||||
len -= 1;
|
||||
}
|
||||
else if (tmp < unchecked((int)(0xe0)))
|
||||
{
|
||||
dst[uppercaseOffset + 1] ^= unchecked((byte)32);
|
||||
uppercaseOffset += 2;
|
||||
len -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[uppercaseOffset + 2] ^= unchecked((byte)5);
|
||||
uppercaseOffset += 3;
|
||||
len -= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copy suffix.
|
||||
@string = transform.suffix;
|
||||
tmp = @string.Length;
|
||||
i = 0;
|
||||
while (i < tmp)
|
||||
{
|
||||
dst[offset++] = @string[i++];
|
||||
}
|
||||
return offset - dstOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
AssetStudio/Brotli/Utils.cs
Normal file
59
AssetStudio/Brotli/Utils.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>A set of utility methods.</summary>
|
||||
internal sealed class Utils
|
||||
{
|
||||
private static readonly byte[] ByteZeroes = new byte[1024];
|
||||
|
||||
private static readonly int[] IntZeroes = new int[1024];
|
||||
|
||||
/// <summary>Fills byte array with zeroes.</summary>
|
||||
/// <remarks>
|
||||
/// Fills byte array with zeroes.
|
||||
/// <p> Current implementation uses
|
||||
/// <see cref="System.Array.Copy(object, int, object, int, int)"/>
|
||||
/// , so it should be used for length not
|
||||
/// less than 16.
|
||||
/// </remarks>
|
||||
/// <param name="dest">array to fill with zeroes</param>
|
||||
/// <param name="offset">the first byte to fill</param>
|
||||
/// <param name="length">number of bytes to change</param>
|
||||
internal static void FillWithZeroes(byte[] dest, int offset, int length)
|
||||
{
|
||||
int cursor = 0;
|
||||
while (cursor < length)
|
||||
{
|
||||
int step = System.Math.Min(cursor + 1024, length) - cursor;
|
||||
System.Array.Copy(ByteZeroes, 0, dest, offset + cursor, step);
|
||||
cursor += step;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Fills int array with zeroes.</summary>
|
||||
/// <remarks>
|
||||
/// Fills int array with zeroes.
|
||||
/// <p> Current implementation uses
|
||||
/// <see cref="System.Array.Copy(object, int, object, int, int)"/>
|
||||
/// , so it should be used for length not
|
||||
/// less than 16.
|
||||
/// </remarks>
|
||||
/// <param name="dest">array to fill with zeroes</param>
|
||||
/// <param name="offset">the first item to fill</param>
|
||||
/// <param name="length">number of item to change</param>
|
||||
internal static void FillWithZeroes(int[] dest, int offset, int length)
|
||||
{
|
||||
int cursor = 0;
|
||||
while (cursor < length)
|
||||
{
|
||||
int step = System.Math.Min(cursor + 1024, length) - cursor;
|
||||
System.Array.Copy(IntZeroes, 0, dest, offset + cursor, step);
|
||||
cursor += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
68
AssetStudio/Brotli/WordTransformType.cs
Normal file
68
AssetStudio/Brotli/WordTransformType.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
/* Copyright 2015 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
namespace Org.Brotli.Dec
|
||||
{
|
||||
/// <summary>Enumeration of all possible word transformations.</summary>
|
||||
/// <remarks>
|
||||
/// Enumeration of all possible word transformations.
|
||||
/// <p>There are two simple types of transforms: omit X first/last symbols, two character-case
|
||||
/// transforms and the identity transform.
|
||||
/// </remarks>
|
||||
internal sealed class WordTransformType
|
||||
{
|
||||
internal const int Identity = 0;
|
||||
|
||||
internal const int OmitLast1 = 1;
|
||||
|
||||
internal const int OmitLast2 = 2;
|
||||
|
||||
internal const int OmitLast3 = 3;
|
||||
|
||||
internal const int OmitLast4 = 4;
|
||||
|
||||
internal const int OmitLast5 = 5;
|
||||
|
||||
internal const int OmitLast6 = 6;
|
||||
|
||||
internal const int OmitLast7 = 7;
|
||||
|
||||
internal const int OmitLast8 = 8;
|
||||
|
||||
internal const int OmitLast9 = 9;
|
||||
|
||||
internal const int UppercaseFirst = 10;
|
||||
|
||||
internal const int UppercaseAll = 11;
|
||||
|
||||
internal const int OmitFirst1 = 12;
|
||||
|
||||
internal const int OmitFirst2 = 13;
|
||||
|
||||
internal const int OmitFirst3 = 14;
|
||||
|
||||
internal const int OmitFirst4 = 15;
|
||||
|
||||
internal const int OmitFirst5 = 16;
|
||||
|
||||
internal const int OmitFirst6 = 17;
|
||||
|
||||
internal const int OmitFirst7 = 18;
|
||||
|
||||
internal const int OmitFirst8 = 19;
|
||||
|
||||
internal const int OmitFirst9 = 20;
|
||||
|
||||
internal static int GetOmitFirst(int type)
|
||||
{
|
||||
return type >= OmitFirst1 ? (type - OmitFirst1 + 1) : 0;
|
||||
}
|
||||
|
||||
internal static int GetOmitLast(int type)
|
||||
{
|
||||
return type <= OmitLast9 ? (type - OmitLast1 + 1) : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
AssetStudio/BuildTarget.cs
Normal file
47
AssetStudio/BuildTarget.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum BuildTarget
|
||||
{
|
||||
UnknownPlatform = 3716,
|
||||
DashboardWidget = 1,
|
||||
StandaloneOSX = 2,
|
||||
StandaloneOSXPPC = 3,
|
||||
StandaloneOSXIntel = 4,
|
||||
StandaloneWindows,
|
||||
WebPlayer,
|
||||
WebPlayerStreamed,
|
||||
Wii = 8,
|
||||
iOS = 9,
|
||||
PS3,
|
||||
XBOX360,
|
||||
Android = 13,
|
||||
StandaloneGLESEmu = 14,
|
||||
NaCl = 16,
|
||||
StandaloneLinux = 17,
|
||||
FlashPlayer = 18,
|
||||
StandaloneWindows64 = 19,
|
||||
WebGL,
|
||||
WSAPlayer,
|
||||
StandaloneLinux64 = 24,
|
||||
StandaloneLinuxUniversal,
|
||||
WP8Player,
|
||||
StandaloneOSXIntel64,
|
||||
BlackBerry,
|
||||
Tizen,
|
||||
PSP2,
|
||||
PS4,
|
||||
PSM,
|
||||
XboxOne,
|
||||
SamsungTV,
|
||||
N3DS,
|
||||
WiiU,
|
||||
tvOS,
|
||||
Switch,
|
||||
NoTarget = -2
|
||||
}
|
||||
}
|
||||
20
AssetStudio/BuildType.cs
Normal file
20
AssetStudio/BuildType.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class BuildType
|
||||
{
|
||||
private string buildType;
|
||||
|
||||
public BuildType(string type)
|
||||
{
|
||||
buildType = type;
|
||||
}
|
||||
|
||||
public bool IsAlpha => buildType == "a";
|
||||
public bool IsPatch => buildType == "p";
|
||||
}
|
||||
}
|
||||
246
AssetStudio/BundleFile.cs
Normal file
246
AssetStudio/BundleFile.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Lz4;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StreamFile
|
||||
{
|
||||
public string fileName;
|
||||
public Stream stream;
|
||||
}
|
||||
|
||||
public class BlockInfo
|
||||
{
|
||||
public uint compressedSize;
|
||||
public uint uncompressedSize;
|
||||
public short flag;
|
||||
}
|
||||
|
||||
public class BundleFile
|
||||
{
|
||||
private string path;
|
||||
public string versionPlayer;
|
||||
public string versionEngine;
|
||||
public List<StreamFile> fileList = new List<StreamFile>();
|
||||
|
||||
public BundleFile(EndianBinaryReader bundleReader, string path)
|
||||
{
|
||||
this.path = path;
|
||||
var signature = bundleReader.ReadStringToNull();
|
||||
switch (signature)
|
||||
{
|
||||
case "UnityWeb":
|
||||
case "UnityRaw":
|
||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
||||
{
|
||||
var format = bundleReader.ReadInt32();
|
||||
versionPlayer = bundleReader.ReadStringToNull();
|
||||
versionEngine = bundleReader.ReadStringToNull();
|
||||
if (format < 6)
|
||||
{
|
||||
int bundleSize = bundleReader.ReadInt32();
|
||||
}
|
||||
else if (format == 6)
|
||||
{
|
||||
ReadFormat6(bundleReader, true);
|
||||
return;
|
||||
}
|
||||
short dummy2 = bundleReader.ReadInt16();
|
||||
int offset = bundleReader.ReadInt16();
|
||||
int dummy3 = bundleReader.ReadInt32();
|
||||
int lzmaChunks = bundleReader.ReadInt32();
|
||||
|
||||
int lzmaSize = 0;
|
||||
long streamSize = 0;
|
||||
|
||||
for (int i = 0; i < lzmaChunks; i++)
|
||||
{
|
||||
lzmaSize = bundleReader.ReadInt32();
|
||||
streamSize = bundleReader.ReadInt32();
|
||||
}
|
||||
|
||||
bundleReader.Position = offset;
|
||||
switch (signature)
|
||||
{
|
||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": //.bytes
|
||||
case "UnityWeb":
|
||||
{
|
||||
var lzmaBuffer = bundleReader.ReadBytes(lzmaSize);
|
||||
using (var lzmaStream = new EndianBinaryReader(SevenZipHelper.StreamDecompress(new MemoryStream(lzmaBuffer))))
|
||||
{
|
||||
GetAssetsFiles(lzmaStream, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "UnityRaw":
|
||||
{
|
||||
GetAssetsFiles(bundleReader, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "UnityFS":
|
||||
{
|
||||
var format = bundleReader.ReadInt32();
|
||||
versionPlayer = bundleReader.ReadStringToNull();
|
||||
versionEngine = bundleReader.ReadStringToNull();
|
||||
if (format == 6)
|
||||
{
|
||||
ReadFormat6(bundleReader);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetAssetsFiles(EndianBinaryReader reader, int offset)
|
||||
{
|
||||
int fileCount = reader.ReadInt32();
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
var file = new StreamFile();
|
||||
file.fileName = Path.GetFileName(reader.ReadStringToNull());
|
||||
int fileOffset = reader.ReadInt32();
|
||||
fileOffset += offset;
|
||||
int fileSize = reader.ReadInt32();
|
||||
long nextFile = reader.Position;
|
||||
reader.Position = fileOffset;
|
||||
var buffer = reader.ReadBytes(fileSize);
|
||||
file.stream = new MemoryStream(buffer);
|
||||
fileList.Add(file);
|
||||
reader.Position = nextFile;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadFormat6(EndianBinaryReader bundleReader, bool padding = false)
|
||||
{
|
||||
var bundleSize = bundleReader.ReadInt64();
|
||||
int compressedSize = bundleReader.ReadInt32();
|
||||
int uncompressedSize = bundleReader.ReadInt32();
|
||||
int flag = bundleReader.ReadInt32();
|
||||
if (padding)
|
||||
bundleReader.ReadByte();
|
||||
byte[] blocksInfoBytes;
|
||||
if ((flag & 0x80) != 0)//at end of file
|
||||
{
|
||||
var position = bundleReader.Position;
|
||||
bundleReader.Position = bundleReader.BaseStream.Length - compressedSize;
|
||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
||||
bundleReader.Position = position;
|
||||
}
|
||||
else
|
||||
{
|
||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
||||
}
|
||||
MemoryStream blocksInfoStream;
|
||||
switch (flag & 0x3F)
|
||||
{
|
||||
default://None
|
||||
{
|
||||
blocksInfoStream = new MemoryStream(blocksInfoBytes);
|
||||
break;
|
||||
}
|
||||
case 1://LZMA
|
||||
{
|
||||
blocksInfoStream = SevenZipHelper.StreamDecompress(new MemoryStream(blocksInfoBytes));
|
||||
break;
|
||||
}
|
||||
case 2://LZ4
|
||||
case 3://LZ4HC
|
||||
{
|
||||
byte[] uncompressedBytes = new byte[uncompressedSize];
|
||||
using (var decoder = new Lz4DecoderStream(new MemoryStream(blocksInfoBytes)))
|
||||
{
|
||||
decoder.Read(uncompressedBytes, 0, uncompressedSize);
|
||||
}
|
||||
blocksInfoStream = new MemoryStream(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
//case 4:LZHAM?
|
||||
}
|
||||
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoStream))
|
||||
{
|
||||
blocksInfoReader.Position = 0x10;
|
||||
int blockcount = blocksInfoReader.ReadInt32();
|
||||
var blockInfos = new BlockInfo[blockcount];
|
||||
for (int i = 0; i < blockcount; i++)
|
||||
{
|
||||
blockInfos[i] = new BlockInfo
|
||||
{
|
||||
uncompressedSize = blocksInfoReader.ReadUInt32(),
|
||||
compressedSize = blocksInfoReader.ReadUInt32(),
|
||||
flag = blocksInfoReader.ReadInt16()
|
||||
};
|
||||
}
|
||||
Stream dataStream;
|
||||
var uncompressedSizeSum = blockInfos.Sum(x => x.uncompressedSize);
|
||||
if (uncompressedSizeSum > int.MaxValue)
|
||||
{
|
||||
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
|
||||
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
||||
dataStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataStream = new MemoryStream();
|
||||
}
|
||||
foreach (var blockInfo in blockInfos)
|
||||
{
|
||||
switch (blockInfo.flag & 0x3F)
|
||||
{
|
||||
default://None
|
||||
{
|
||||
bundleReader.BaseStream.CopyTo(dataStream, blockInfo.compressedSize);
|
||||
break;
|
||||
}
|
||||
case 1://LZMA
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(bundleReader.BaseStream, dataStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
case 2://LZ4
|
||||
case 3://LZ4HC
|
||||
{
|
||||
var lz4Stream = new Lz4DecoderStream(bundleReader.BaseStream, blockInfo.compressedSize);
|
||||
lz4Stream.CopyTo(dataStream, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
//case 4:LZHAM?
|
||||
}
|
||||
}
|
||||
dataStream.Position = 0;
|
||||
using (dataStream)
|
||||
{
|
||||
var entryinfo_count = blocksInfoReader.ReadInt32();
|
||||
for (int i = 0; i < entryinfo_count; i++)
|
||||
{
|
||||
var file = new StreamFile();
|
||||
var entryinfo_offset = blocksInfoReader.ReadInt64();
|
||||
var entryinfo_size = blocksInfoReader.ReadInt64();
|
||||
flag = blocksInfoReader.ReadInt32();
|
||||
file.fileName = Path.GetFileName(blocksInfoReader.ReadStringToNull());
|
||||
if (entryinfo_size > int.MaxValue)
|
||||
{
|
||||
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size);
|
||||
file.stream = memoryMappedFile.CreateViewStream();*/
|
||||
var extractPath = path + "_unpacked\\";
|
||||
Directory.CreateDirectory(extractPath);
|
||||
file.stream = File.Create(extractPath + file.fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
file.stream = new MemoryStream();
|
||||
}
|
||||
dataStream.Position = entryinfo_offset;
|
||||
dataStream.CopyTo(file.stream, entryinfo_size);
|
||||
file.stream.Position = 0;
|
||||
fileList.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
286
AssetStudio/ClassIDType.cs
Normal file
286
AssetStudio/ClassIDType.cs
Normal file
@@ -0,0 +1,286 @@
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum ClassIDType
|
||||
{
|
||||
UnknownType = -1,
|
||||
Object = 0,
|
||||
GameObject = 1,
|
||||
Component = 2,
|
||||
LevelGameManager = 3,
|
||||
Transform = 4,
|
||||
TimeManager = 5,
|
||||
GlobalGameManager = 6,
|
||||
Behaviour = 8,
|
||||
GameManager = 9,
|
||||
AudioManager = 11,
|
||||
ParticleAnimator = 12,
|
||||
InputManager = 13,
|
||||
EllipsoidParticleEmitter = 15,
|
||||
Pipeline = 17,
|
||||
EditorExtension = 18,
|
||||
Physics2DSettings = 19,
|
||||
Camera = 20,
|
||||
Material = 21,
|
||||
MeshRenderer = 23,
|
||||
Renderer = 25,
|
||||
ParticleRenderer = 26,
|
||||
Texture = 27,
|
||||
Texture2D = 28,
|
||||
SceneSettings = 29,
|
||||
GraphicsSettings = 30,
|
||||
MeshFilter = 33,
|
||||
OcclusionPortal = 41,
|
||||
Mesh = 43,
|
||||
Skybox = 45,
|
||||
QualitySettings = 47,
|
||||
Shader = 48,
|
||||
TextAsset = 49,
|
||||
Rigidbody2D = 50,
|
||||
Physics2DManager = 51,
|
||||
Collider2D = 53,
|
||||
Rigidbody = 54,
|
||||
PhysicsManager = 55,
|
||||
Collider = 56,
|
||||
Joint = 57,
|
||||
CircleCollider2D = 58,
|
||||
HingeJoint = 59,
|
||||
PolygonCollider2D = 60,
|
||||
BoxCollider2D = 61,
|
||||
PhysicsMaterial2D = 62,
|
||||
MeshCollider = 64,
|
||||
BoxCollider = 65,
|
||||
SpriteCollider2D = 66,
|
||||
EdgeCollider2D = 68,
|
||||
CapsuleCollider2D = 70,
|
||||
ComputeShader = 72,
|
||||
AnimationClip = 74,
|
||||
ConstantForce = 75,
|
||||
WorldParticleCollider = 76,
|
||||
TagManager = 78,
|
||||
AudioListener = 81,
|
||||
AudioSource = 82,
|
||||
AudioClip = 83,
|
||||
RenderTexture = 84,
|
||||
CustomRenderTexture = 86,
|
||||
MeshParticleEmitter = 87,
|
||||
ParticleEmitter = 88,
|
||||
Cubemap = 89,
|
||||
Avatar = 90,
|
||||
AnimatorController = 91,
|
||||
GUILayer = 92,
|
||||
RuntimeAnimatorController = 93,
|
||||
ScriptMapper = 94,
|
||||
Animator = 95,
|
||||
TrailRenderer = 96,
|
||||
DelayedCallManager = 98,
|
||||
TextMesh = 102,
|
||||
RenderSettings = 104,
|
||||
Light = 108,
|
||||
CGProgram = 109,
|
||||
BaseAnimationTrack = 110,
|
||||
Animation = 111,
|
||||
MonoBehaviour = 114,
|
||||
MonoScript = 115,
|
||||
MonoManager = 116,
|
||||
Texture3D = 117,
|
||||
NewAnimationTrack = 118,
|
||||
Projector = 119,
|
||||
LineRenderer = 120,
|
||||
Flare = 121,
|
||||
Halo = 122,
|
||||
LensFlare = 123,
|
||||
FlareLayer = 124,
|
||||
HaloLayer = 125,
|
||||
NavMeshAreas = 126,
|
||||
HaloManager = 127,
|
||||
Font = 128,
|
||||
PlayerSettings = 129,
|
||||
NamedObject = 130,
|
||||
GUITexture = 131,
|
||||
GUIText = 132,
|
||||
GUIElement = 133,
|
||||
PhysicMaterial = 134,
|
||||
SphereCollider = 135,
|
||||
CapsuleCollider = 136,
|
||||
SkinnedMeshRenderer = 137,
|
||||
FixedJoint = 138,
|
||||
RaycastCollider = 140,
|
||||
BuildSettings = 141,
|
||||
AssetBundle = 142,
|
||||
CharacterController = 143,
|
||||
CharacterJoint = 144,
|
||||
SpringJoint = 145,
|
||||
WheelCollider = 146,
|
||||
ResourceManager = 147,
|
||||
NetworkView = 148,
|
||||
NetworkManager = 149,
|
||||
PreloadData = 150,
|
||||
MovieTexture = 152,
|
||||
ConfigurableJoint = 153,
|
||||
TerrainCollider = 154,
|
||||
MasterServerInterface = 155,
|
||||
TerrainData = 156,
|
||||
LightmapSettings = 157,
|
||||
WebCamTexture = 158,
|
||||
EditorSettings = 159,
|
||||
InteractiveCloth = 160,
|
||||
ClothRenderer = 161,
|
||||
EditorUserSettings = 162,
|
||||
SkinnedCloth = 163,
|
||||
AudioReverbFilter = 164,
|
||||
AudioHighPassFilter = 165,
|
||||
AudioChorusFilter = 166,
|
||||
AudioReverbZone = 167,
|
||||
AudioEchoFilter = 168,
|
||||
AudioLowPassFilter = 169,
|
||||
AudioDistortionFilter = 170,
|
||||
SparseTexture = 171,
|
||||
AudioBehaviour = 180,
|
||||
AudioFilter = 181,
|
||||
WindZone = 182,
|
||||
Cloth = 183,
|
||||
SubstanceArchive = 184,
|
||||
ProceduralMaterial = 185,
|
||||
ProceduralTexture = 186,
|
||||
Texture2DArray = 187,
|
||||
CubemapArray = 188,
|
||||
OffMeshLink = 191,
|
||||
OcclusionArea = 192,
|
||||
Tree = 193,
|
||||
NavMeshObsolete = 194,
|
||||
NavMeshAgent = 195,
|
||||
NavMeshSettings = 196,
|
||||
LightProbesLegacy = 197,
|
||||
ParticleSystem = 198,
|
||||
ParticleSystemRenderer = 199,
|
||||
ShaderVariantCollection = 200,
|
||||
LODGroup = 205,
|
||||
BlendTree = 206,
|
||||
Motion = 207,
|
||||
NavMeshObstacle = 208,
|
||||
TerrainInstance = 210,
|
||||
SpriteRenderer = 212,
|
||||
Sprite = 213,
|
||||
CachedSpriteAtlas = 214,
|
||||
ReflectionProbe = 215,
|
||||
ReflectionProbes = 216,
|
||||
Terrain = 218,
|
||||
LightProbeGroup = 220,
|
||||
AnimatorOverrideController = 221,
|
||||
CanvasRenderer = 222,
|
||||
Canvas = 223,
|
||||
RectTransform = 224,
|
||||
CanvasGroup = 225,
|
||||
BillboardAsset = 226,
|
||||
BillboardRenderer = 227,
|
||||
SpeedTreeWindAsset = 228,
|
||||
AnchoredJoint2D = 229,
|
||||
Joint2D = 230,
|
||||
SpringJoint2D = 231,
|
||||
DistanceJoint2D = 232,
|
||||
HingeJoint2D = 233,
|
||||
SliderJoint2D = 234,
|
||||
WheelJoint2D = 235,
|
||||
ClusterInputManager = 236,
|
||||
BaseVideoTexture = 237,
|
||||
NavMeshData = 238,
|
||||
AudioMixer = 240,
|
||||
AudioMixerController = 241,
|
||||
AudioMixerGroupController = 243,
|
||||
AudioMixerEffectController = 244,
|
||||
AudioMixerSnapshotController = 245,
|
||||
PhysicsUpdateBehaviour2D = 246,
|
||||
ConstantForce2D = 247,
|
||||
Effector2D = 248,
|
||||
AreaEffector2D = 249,
|
||||
PointEffector2D = 250,
|
||||
PlatformEffector2D = 251,
|
||||
SurfaceEffector2D = 252,
|
||||
BuoyancyEffector2D = 253,
|
||||
RelativeJoint2D = 254,
|
||||
FixedJoint2D = 255,
|
||||
FrictionJoint2D = 256,
|
||||
TargetJoint2D = 257,
|
||||
LightProbes = 258,
|
||||
LightProbeProxyVolume = 259,
|
||||
SampleClip = 271,
|
||||
AudioMixerSnapshot = 272,
|
||||
AudioMixerGroup = 273,
|
||||
NScreenBridge = 280,
|
||||
AssetBundleManifest = 290,
|
||||
UnityAdsManager = 292,
|
||||
RuntimeInitializeOnLoadManager = 300,
|
||||
CloudWebServicesManager = 301,
|
||||
UnityAnalyticsManager = 303,
|
||||
CrashReportManager = 304,
|
||||
PerformanceReportingManager = 305,
|
||||
UnityConnectSettings = 310,
|
||||
AvatarMask = 319,
|
||||
VideoPlayer = 328,
|
||||
VideoClip = 329,
|
||||
OcclusionCullingData = 363,
|
||||
//kLargestRuntimeClassID = 364
|
||||
SmallestEditorClassID = 1000,
|
||||
Prefab = 1001,
|
||||
EditorExtensionImpl = 1002,
|
||||
AssetImporter = 1003,
|
||||
AssetDatabase = 1004,
|
||||
Mesh3DSImporter = 1005,
|
||||
TextureImporter = 1006,
|
||||
ShaderImporter = 1007,
|
||||
ComputeShaderImporter = 1008,
|
||||
AudioImporter = 1020,
|
||||
HierarchyState = 1026,
|
||||
GUIDSerializer = 1027,
|
||||
AssetMetaData = 1028,
|
||||
DefaultAsset = 1029,
|
||||
DefaultImporter = 1030,
|
||||
TextScriptImporter = 1031,
|
||||
SceneAsset = 1032,
|
||||
NativeFormatImporter = 1034,
|
||||
MonoImporter = 1035,
|
||||
AssetServerCache = 1037,
|
||||
LibraryAssetImporter = 1038,
|
||||
ModelImporter = 1040,
|
||||
FBXImporter = 1041,
|
||||
TrueTypeFontImporter = 1042,
|
||||
MovieImporter = 1044,
|
||||
EditorBuildSettings = 1045,
|
||||
DDSImporter = 1046,
|
||||
InspectorExpandedState = 1048,
|
||||
AnnotationManager = 1049,
|
||||
PluginImporter = 1050,
|
||||
EditorUserBuildSettings = 1051,
|
||||
PVRImporter = 1052,
|
||||
ASTCImporter = 1053,
|
||||
KTXImporter = 1054,
|
||||
IHVImageFormatImporter = 1055,
|
||||
AnimatorStateTransition = 1101,
|
||||
AnimatorState = 1102,
|
||||
HumanTemplate = 1105,
|
||||
AnimatorStateMachine = 1107,
|
||||
PreviewAssetType = 1108,
|
||||
AnimatorTransition = 1109,
|
||||
SpeedTreeImporter = 1110,
|
||||
AnimatorTransitionBase = 1111,
|
||||
SubstanceImporter = 1112,
|
||||
LightmapParameters = 1113,
|
||||
LightmapSnapshot = 1120,
|
||||
GISRaster = 1121,
|
||||
GISRasterImporter = 1122,
|
||||
CadImporter = 1123,
|
||||
SketchUpImporter = 1124,
|
||||
BuildReport = 1125,
|
||||
PackedAssets = 1126,
|
||||
VideoClipImporter = 1127,
|
||||
ActivationLogComponent = 2000,
|
||||
//kLargestEditorClassID = 2001
|
||||
//kClassIdOutOfHierarchy = 100000
|
||||
SubDerived = 367388927,
|
||||
SiblingDerived = 334799969,
|
||||
SpriteAtlas = 687078895,
|
||||
Derived = 1091556383,
|
||||
LowerResBlitTexture = 1480428607,
|
||||
RenderPassAttachment = 1571458007
|
||||
}
|
||||
}
|
||||
23
AssetStudio/Classes/Animation.cs
Normal file
23
AssetStudio/Classes/Animation.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class Animation : Behaviour
|
||||
{
|
||||
public List<PPtr> m_Animations;
|
||||
|
||||
public Animation(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_Animation = reader.ReadPPtr();
|
||||
int numAnimations = reader.ReadInt32();
|
||||
m_Animations = new List<PPtr>(numAnimations);
|
||||
for (int i = 0; i < numAnimations; i++)
|
||||
{
|
||||
m_Animations.Add(reader.ReadPPtr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
973
AssetStudio/Classes/AnimationClip.cs
Normal file
973
AssetStudio/Classes/AnimationClip.cs
Normal file
@@ -0,0 +1,973 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpDX;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class Keyframe<T>
|
||||
{
|
||||
public float time;
|
||||
public T value;
|
||||
public T inSlope;
|
||||
public T outSlope;
|
||||
public int weightedMode;
|
||||
public T inWeight;
|
||||
public T outWeight;
|
||||
|
||||
|
||||
public Keyframe(ObjectReader reader, Func<T> readerFunc)
|
||||
{
|
||||
time = reader.ReadSingle();
|
||||
value = readerFunc();
|
||||
inSlope = readerFunc();
|
||||
outSlope = readerFunc();
|
||||
if (reader.version[0] >= 2018)
|
||||
{
|
||||
weightedMode = reader.ReadInt32();
|
||||
inWeight = readerFunc();
|
||||
outWeight = readerFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AnimationCurve<T>
|
||||
{
|
||||
public List<Keyframe<T>> m_Curve;
|
||||
public int m_PreInfinity;
|
||||
public int m_PostInfinity;
|
||||
public int m_RotationOrder;
|
||||
|
||||
public AnimationCurve(ObjectReader reader, Func<T> readerFunc)
|
||||
{
|
||||
var version = reader.version;
|
||||
int numCurves = reader.ReadInt32();
|
||||
m_Curve = new List<Keyframe<T>>(numCurves);
|
||||
for (int i = 0; i < numCurves; i++)
|
||||
{
|
||||
m_Curve.Add(new Keyframe<T>(reader, readerFunc));
|
||||
}
|
||||
|
||||
m_PreInfinity = reader.ReadInt32();
|
||||
m_PostInfinity = reader.ReadInt32();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
|
||||
{
|
||||
m_RotationOrder = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class QuaternionCurve
|
||||
{
|
||||
public AnimationCurve<Quaternion> curve;
|
||||
public string path;
|
||||
|
||||
public QuaternionCurve(ObjectReader reader)
|
||||
{
|
||||
curve = new AnimationCurve<Quaternion>(reader, reader.ReadQuaternion);
|
||||
path = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
public class PackedFloatVector
|
||||
{
|
||||
public uint m_NumItems;
|
||||
public float m_Range;
|
||||
public float m_Start;
|
||||
public byte[] m_Data;
|
||||
public byte m_BitSize;
|
||||
|
||||
public PackedFloatVector(ObjectReader reader)
|
||||
{
|
||||
m_NumItems = reader.ReadUInt32();
|
||||
m_Range = reader.ReadSingle();
|
||||
m_Start = reader.ReadSingle();
|
||||
|
||||
int numData = reader.ReadInt32();
|
||||
m_Data = reader.ReadBytes(numData);
|
||||
reader.AlignStream(4);
|
||||
|
||||
m_BitSize = reader.ReadByte();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
public float[] UnpackFloats(int itemCountInChunk, int chunkStride, int start = 0, int numChunks = -1)
|
||||
{
|
||||
int bitPos = m_BitSize * start;
|
||||
int indexPos = bitPos / 8;
|
||||
bitPos %= 8;
|
||||
|
||||
float scale = 1.0f / m_Range;
|
||||
if (numChunks == -1)
|
||||
numChunks = (int)m_NumItems / itemCountInChunk;
|
||||
var end = chunkStride * numChunks / 4;
|
||||
var data = new List<float>();
|
||||
for (var index = 0; index != end; index += chunkStride / 4)
|
||||
{
|
||||
for (int i = 0; i < itemCountInChunk; ++i)
|
||||
{
|
||||
uint x = 0;
|
||||
|
||||
int bits = 0;
|
||||
while (bits < m_BitSize)
|
||||
{
|
||||
x |= (uint)((m_Data[indexPos] >> bitPos) << bits);
|
||||
int num = Math.Min(m_BitSize - bits, 8 - bitPos);
|
||||
bitPos += num;
|
||||
bits += num;
|
||||
if (bitPos == 8)
|
||||
{
|
||||
indexPos++;
|
||||
bitPos = 0;
|
||||
}
|
||||
}
|
||||
x &= (uint)(1 << m_BitSize) - 1u;
|
||||
data.Add(x / (scale * ((1 << m_BitSize) - 1)) + m_Start);
|
||||
}
|
||||
}
|
||||
|
||||
return data.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public class PackedIntVector
|
||||
{
|
||||
public uint m_NumItems;
|
||||
public byte[] m_Data;
|
||||
public byte m_BitSize;
|
||||
|
||||
public PackedIntVector(ObjectReader reader)
|
||||
{
|
||||
m_NumItems = reader.ReadUInt32();
|
||||
|
||||
int numData = reader.ReadInt32();
|
||||
m_Data = reader.ReadBytes(numData);
|
||||
reader.AlignStream(4);
|
||||
|
||||
m_BitSize = reader.ReadByte();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
public int[] UnpackInts()
|
||||
{
|
||||
var data = new int[m_NumItems];
|
||||
int indexPos = 0;
|
||||
int bitPos = 0;
|
||||
for (int i = 0; i < m_NumItems; i++)
|
||||
{
|
||||
int bits = 0;
|
||||
data[i] = 0;
|
||||
while (bits < m_BitSize)
|
||||
{
|
||||
data[i] |= (m_Data[indexPos] >> bitPos) << bits;
|
||||
int num = Math.Min(m_BitSize - bits, 8 - bitPos);
|
||||
bitPos += num;
|
||||
bits += num;
|
||||
if (bitPos == 8)
|
||||
{
|
||||
indexPos++;
|
||||
bitPos = 0;
|
||||
}
|
||||
}
|
||||
data[i] &= (1 << m_BitSize) - 1;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public class PackedQuatVector
|
||||
{
|
||||
public uint m_NumItems;
|
||||
public byte[] m_Data;
|
||||
|
||||
public PackedQuatVector(ObjectReader reader)
|
||||
{
|
||||
m_NumItems = reader.ReadUInt32();
|
||||
|
||||
int numData = reader.ReadInt32();
|
||||
m_Data = reader.ReadBytes(numData);
|
||||
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
public Quaternion[] UnpackQuats()
|
||||
{
|
||||
var data = new Quaternion[m_NumItems];
|
||||
int indexPos = 0;
|
||||
int bitPos = 0;
|
||||
|
||||
for (int i = 0; i < m_NumItems; i++)
|
||||
{
|
||||
uint flags = 0;
|
||||
|
||||
int bits = 0;
|
||||
while (bits < 3)
|
||||
{
|
||||
flags |= (uint)((m_Data[indexPos] >> bitPos) << bits);
|
||||
int num = Math.Min(3 - bits, 8 - bitPos);
|
||||
bitPos += num;
|
||||
bits += num;
|
||||
if (bitPos == 8)
|
||||
{
|
||||
indexPos++;
|
||||
bitPos = 0;
|
||||
}
|
||||
}
|
||||
flags &= 7;
|
||||
|
||||
|
||||
var q = new Quaternion();
|
||||
float sum = 0;
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
if ((flags & 3) != j)
|
||||
{
|
||||
int bitSize = ((flags & 3) + 1) % 4 == j ? 9 : 10;
|
||||
uint x = 0;
|
||||
|
||||
bits = 0;
|
||||
while (bits < bitSize)
|
||||
{
|
||||
x |= (uint)((m_Data[indexPos] >> bitPos) << bits);
|
||||
int num = Math.Min(bitSize - bits, 8 - bitPos);
|
||||
bitPos += num;
|
||||
bits += num;
|
||||
if (bitPos == 8)
|
||||
{
|
||||
indexPos++;
|
||||
bitPos = 0;
|
||||
}
|
||||
}
|
||||
x &= (uint)((1 << bitSize) - 1);
|
||||
q[j] = x / (0.5f * ((1 << bitSize) - 1)) - 1;
|
||||
sum += q[j] * q[j];
|
||||
}
|
||||
}
|
||||
|
||||
int lastComponent = (int)(flags & 3);
|
||||
q[lastComponent] = (float)Math.Sqrt(1 - sum);
|
||||
if ((flags & 4) != 0u)
|
||||
q[lastComponent] = -q[lastComponent];
|
||||
data[i] = q;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public class CompressedAnimationCurve
|
||||
{
|
||||
public string m_Path;
|
||||
public PackedIntVector m_Times;
|
||||
public PackedQuatVector m_Values;
|
||||
public PackedFloatVector m_Slopes;
|
||||
public int m_PreInfinity;
|
||||
public int m_PostInfinity;
|
||||
|
||||
public CompressedAnimationCurve(ObjectReader reader)
|
||||
{
|
||||
m_Path = reader.ReadAlignedString();
|
||||
m_Times = new PackedIntVector(reader);
|
||||
m_Values = new PackedQuatVector(reader);
|
||||
m_Slopes = new PackedFloatVector(reader);
|
||||
m_PreInfinity = reader.ReadInt32();
|
||||
m_PostInfinity = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class Vector3Curve
|
||||
{
|
||||
public AnimationCurve<Vector3> curve;
|
||||
public string path;
|
||||
|
||||
public Vector3Curve(ObjectReader reader)
|
||||
{
|
||||
curve = new AnimationCurve<Vector3>(reader, reader.ReadVector3);
|
||||
path = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
public class FloatCurve
|
||||
{
|
||||
public AnimationCurve<float> curve;
|
||||
public string attribute;
|
||||
public string path;
|
||||
public int classID;
|
||||
public PPtr script;
|
||||
|
||||
|
||||
public FloatCurve(ObjectReader reader)
|
||||
{
|
||||
curve = new AnimationCurve<float>(reader, reader.ReadSingle);
|
||||
attribute = reader.ReadAlignedString();
|
||||
path = reader.ReadAlignedString();
|
||||
classID = reader.ReadInt32();
|
||||
script = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
|
||||
public class PPtrKeyframe
|
||||
{
|
||||
public float time;
|
||||
public PPtr value;
|
||||
|
||||
|
||||
public PPtrKeyframe(ObjectReader reader)
|
||||
{
|
||||
time = reader.ReadSingle();
|
||||
value = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
|
||||
public class PPtrCurve
|
||||
{
|
||||
public List<PPtrKeyframe> curve;
|
||||
public string attribute;
|
||||
public string path;
|
||||
public int classID;
|
||||
public PPtr script;
|
||||
|
||||
|
||||
public PPtrCurve(ObjectReader reader)
|
||||
{
|
||||
int numCurves = reader.ReadInt32();
|
||||
curve = new List<PPtrKeyframe>(numCurves);
|
||||
for (int i = 0; i < numCurves; i++)
|
||||
{
|
||||
curve.Add(new PPtrKeyframe(reader));
|
||||
}
|
||||
|
||||
attribute = reader.ReadAlignedString();
|
||||
path = reader.ReadAlignedString();
|
||||
classID = reader.ReadInt32();
|
||||
script = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
|
||||
public class AABB
|
||||
{
|
||||
public Vector3 m_Center;
|
||||
public Vector3 m_Extend;
|
||||
|
||||
public AABB(ObjectReader reader)
|
||||
{
|
||||
m_Center = reader.ReadVector3();
|
||||
m_Extend = reader.ReadVector3();
|
||||
}
|
||||
}
|
||||
|
||||
public class xform
|
||||
{
|
||||
public object t;
|
||||
public Quaternion q;
|
||||
public object s;
|
||||
|
||||
public xform(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
t = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
|
||||
q = reader.ReadQuaternion();
|
||||
s = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
|
||||
}
|
||||
}
|
||||
|
||||
public class HandPose
|
||||
{
|
||||
public xform m_GrabX;
|
||||
public float[] m_DoFArray;
|
||||
public float m_Override;
|
||||
public float m_CloseOpen;
|
||||
public float m_InOut;
|
||||
public float m_Grab;
|
||||
|
||||
public HandPose(ObjectReader reader)
|
||||
{
|
||||
m_GrabX = new xform(reader);
|
||||
|
||||
int numDoFs = reader.ReadInt32();
|
||||
m_DoFArray = reader.ReadSingleArray(numDoFs);
|
||||
|
||||
m_Override = reader.ReadSingle();
|
||||
m_CloseOpen = reader.ReadSingle();
|
||||
m_InOut = reader.ReadSingle();
|
||||
m_Grab = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
public class HumanGoal
|
||||
{
|
||||
public xform m_X;
|
||||
public float m_WeightT;
|
||||
public float m_WeightR;
|
||||
public object m_HintT;
|
||||
public float m_HintWeightT;
|
||||
|
||||
public HumanGoal(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_X = new xform(reader);
|
||||
m_WeightT = reader.ReadSingle();
|
||||
m_WeightR = reader.ReadSingle();
|
||||
if (version[0] >= 5)//5.0 and up
|
||||
{
|
||||
m_HintT = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
|
||||
m_HintWeightT = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class HumanPose
|
||||
{
|
||||
public xform m_RootX;
|
||||
public object m_LookAtPosition;
|
||||
public Vector4 m_LookAtWeight;
|
||||
public List<HumanGoal> m_GoalArray;
|
||||
public HandPose m_LeftHandPose;
|
||||
public HandPose m_RightHandPose;
|
||||
public float[] m_DoFArray;
|
||||
public object[] m_TDoFArray;
|
||||
|
||||
public HumanPose(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_RootX = new xform(reader);
|
||||
m_LookAtPosition = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
|
||||
m_LookAtWeight = reader.ReadVector4();
|
||||
|
||||
int numGoals = reader.ReadInt32();
|
||||
m_GoalArray = new List<HumanGoal>(numGoals);
|
||||
for (int i = 0; i < numGoals; i++)
|
||||
{
|
||||
m_GoalArray.Add(new HumanGoal(reader));
|
||||
}
|
||||
|
||||
m_LeftHandPose = new HandPose(reader);
|
||||
m_RightHandPose = new HandPose(reader);
|
||||
|
||||
int numDoFs = reader.ReadInt32();
|
||||
m_DoFArray = reader.ReadSingleArray(numDoFs);
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2))//5.2 and up
|
||||
{
|
||||
int numTDof = reader.ReadInt32();
|
||||
m_TDoFArray = new object[numTDof];
|
||||
for (int i = 0; i < numTDof; i++)
|
||||
{
|
||||
m_TDoFArray[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StreamedClip
|
||||
{
|
||||
public uint[] data;
|
||||
public uint curveCount;
|
||||
|
||||
public StreamedClip(ObjectReader reader)
|
||||
{
|
||||
int numData = reader.ReadInt32();
|
||||
data = reader.ReadUInt32Array(numData);
|
||||
curveCount = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
public class StreamedCurveKey
|
||||
{
|
||||
public int index;
|
||||
public float[] coeff;
|
||||
|
||||
public float value;
|
||||
public float outSlope;
|
||||
public float inSlope;
|
||||
|
||||
public StreamedCurveKey(BinaryReader reader)
|
||||
{
|
||||
index = reader.ReadInt32();
|
||||
coeff = reader.ReadSingleArray(4);
|
||||
|
||||
outSlope = coeff[2];
|
||||
value = coeff[3];
|
||||
}
|
||||
|
||||
public float CalculateNextInSlope(float dx, StreamedCurveKey rhs)
|
||||
{
|
||||
//Stepped
|
||||
if (coeff[0] == 0f && coeff[1] == 0f && coeff[2] == 0f)
|
||||
{
|
||||
return float.PositiveInfinity;
|
||||
}
|
||||
|
||||
dx = Math.Max(dx, 0.0001f);
|
||||
var dy = rhs.value - value;
|
||||
var length = 1.0f / (dx * dx);
|
||||
var d1 = outSlope * dx;
|
||||
var d2 = dy + dy + dy - d1 - d1 - coeff[1] / length;
|
||||
return d2 / dx;
|
||||
}
|
||||
}
|
||||
|
||||
public class StreamedFrame
|
||||
{
|
||||
public float time;
|
||||
public List<StreamedCurveKey> keyList;
|
||||
|
||||
public StreamedFrame(BinaryReader reader)
|
||||
{
|
||||
time = reader.ReadSingle();
|
||||
|
||||
int numKeys = reader.ReadInt32();
|
||||
keyList = new List<StreamedCurveKey>(numKeys);
|
||||
for (int i = 0; i < numKeys; i++)
|
||||
{
|
||||
keyList.Add(new StreamedCurveKey(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<StreamedFrame> ReadData()
|
||||
{
|
||||
var frameList = new List<StreamedFrame>();
|
||||
using (Stream stream = new MemoryStream())
|
||||
{
|
||||
BinaryWriter writer = new BinaryWriter(stream);
|
||||
writer.Write(data);
|
||||
stream.Position = 0;
|
||||
while (stream.Position < stream.Length)
|
||||
{
|
||||
frameList.Add(new StreamedFrame(new BinaryReader(stream)));
|
||||
}
|
||||
}
|
||||
|
||||
for (int frameIndex = 2; frameIndex < frameList.Count - 1; frameIndex++)
|
||||
{
|
||||
var frame = frameList[frameIndex];
|
||||
foreach (var curveKey in frame.keyList)
|
||||
{
|
||||
for (int i = frameIndex - 1; i >= 0; i--)
|
||||
{
|
||||
var preFrame = frameList[i];
|
||||
var preCurveKey = preFrame.keyList.Find(x => x.index == curveKey.index);
|
||||
if (preCurveKey != null)
|
||||
{
|
||||
curveKey.inSlope = preCurveKey.CalculateNextInSlope(frame.time - preFrame.time, curveKey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return frameList;
|
||||
}
|
||||
}
|
||||
|
||||
public class DenseClip
|
||||
{
|
||||
public int m_FrameCount;
|
||||
public uint m_CurveCount;
|
||||
public float m_SampleRate;
|
||||
public float m_BeginTime;
|
||||
public float[] m_SampleArray;
|
||||
|
||||
public DenseClip(ObjectReader reader)
|
||||
{
|
||||
m_FrameCount = reader.ReadInt32();
|
||||
m_CurveCount = reader.ReadUInt32();
|
||||
m_SampleRate = reader.ReadSingle();
|
||||
m_BeginTime = reader.ReadSingle();
|
||||
|
||||
int numSamples = reader.ReadInt32();
|
||||
m_SampleArray = reader.ReadSingleArray(numSamples);
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstantClip
|
||||
{
|
||||
public float[] data;
|
||||
|
||||
public ConstantClip(ObjectReader reader)
|
||||
{
|
||||
int numData = reader.ReadInt32();
|
||||
data = reader.ReadSingleArray(numData);
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueConstant
|
||||
{
|
||||
public uint m_ID;
|
||||
public uint m_TypeID;
|
||||
public uint m_Type;
|
||||
public uint m_Index;
|
||||
|
||||
public ValueConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_ID = reader.ReadUInt32();
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 5))//5.5 down
|
||||
{
|
||||
m_TypeID = reader.ReadUInt32();
|
||||
}
|
||||
m_Type = reader.ReadUInt32();
|
||||
m_Index = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueArrayConstant
|
||||
{
|
||||
public List<ValueConstant> m_ValueArray;
|
||||
|
||||
public ValueArrayConstant(ObjectReader reader)
|
||||
{
|
||||
int numVals = reader.ReadInt32();
|
||||
m_ValueArray = new List<ValueConstant>(numVals);
|
||||
for (int i = 0; i < numVals; i++)
|
||||
{
|
||||
m_ValueArray.Add(new ValueConstant(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Clip
|
||||
{
|
||||
public StreamedClip m_StreamedClip;
|
||||
public DenseClip m_DenseClip;
|
||||
public ConstantClip m_ConstantClip;
|
||||
public ValueArrayConstant m_Binding;
|
||||
|
||||
public Clip(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_StreamedClip = new StreamedClip(reader);
|
||||
m_DenseClip = new DenseClip(reader);
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
{
|
||||
m_ConstantClip = new ConstantClip(reader);
|
||||
}
|
||||
m_Binding = new ValueArrayConstant(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueDelta
|
||||
{
|
||||
public float m_Start;
|
||||
public float m_Stop;
|
||||
|
||||
public ValueDelta(ObjectReader reader)
|
||||
{
|
||||
m_Start = reader.ReadSingle();
|
||||
m_Stop = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
public class ClipMuscleConstant
|
||||
{
|
||||
public HumanPose m_DeltaPose;
|
||||
public xform m_StartX;
|
||||
public xform m_StopX;
|
||||
public xform m_LeftFootStartX;
|
||||
public xform m_RightFootStartX;
|
||||
public xform m_MotionStartX;
|
||||
public xform m_MotionStopX;
|
||||
public object m_AverageSpeed;
|
||||
public Clip m_Clip;
|
||||
public float m_StartTime;
|
||||
public float m_StopTime;
|
||||
public float m_OrientationOffsetY;
|
||||
public float m_Level;
|
||||
public float m_CycleOffset;
|
||||
public float m_AverageAngularSpeed;
|
||||
public int[] m_IndexArray;
|
||||
public List<ValueDelta> m_ValueArrayDelta;
|
||||
public float[] m_ValueArrayReferencePose;
|
||||
public bool m_Mirror;
|
||||
public bool m_LoopTime;
|
||||
public bool m_LoopBlend;
|
||||
public bool m_LoopBlendOrientation;
|
||||
public bool m_LoopBlendPositionY;
|
||||
public bool m_LoopBlendPositionXZ;
|
||||
public bool m_StartAtOrigin;
|
||||
public bool m_KeepOriginalOrientation;
|
||||
public bool m_KeepOriginalPositionY;
|
||||
public bool m_KeepOriginalPositionXZ;
|
||||
public bool m_HeightFromFeet;
|
||||
|
||||
public ClipMuscleConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_DeltaPose = new HumanPose(reader);
|
||||
m_StartX = new xform(reader);
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up
|
||||
{
|
||||
m_StopX = new xform(reader);
|
||||
}
|
||||
m_LeftFootStartX = new xform(reader);
|
||||
m_RightFootStartX = new xform(reader);
|
||||
if (version[0] < 5)//5.0 down
|
||||
{
|
||||
m_MotionStartX = new xform(reader);
|
||||
m_MotionStopX = new xform(reader);
|
||||
}
|
||||
m_AverageSpeed = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
|
||||
m_Clip = new Clip(reader);
|
||||
m_StartTime = reader.ReadSingle();
|
||||
m_StopTime = reader.ReadSingle();
|
||||
m_OrientationOffsetY = reader.ReadSingle();
|
||||
m_Level = reader.ReadSingle();
|
||||
m_CycleOffset = reader.ReadSingle();
|
||||
m_AverageAngularSpeed = reader.ReadSingle();
|
||||
|
||||
int numIndices = reader.ReadInt32();
|
||||
m_IndexArray = reader.ReadInt32Array(numIndices);
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
|
||||
{
|
||||
int numAdditionalCurveIndexs = reader.ReadInt32();
|
||||
var m_AdditionalCurveIndexArray = new List<int>(numAdditionalCurveIndexs);
|
||||
for (int i = 0; i < numAdditionalCurveIndexs; i++)
|
||||
{
|
||||
m_AdditionalCurveIndexArray.Add(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
int numDeltas = reader.ReadInt32();
|
||||
m_ValueArrayDelta = new List<ValueDelta>(numDeltas);
|
||||
for (int i = 0; i < numDeltas; i++)
|
||||
{
|
||||
m_ValueArrayDelta.Add(new ValueDelta(reader));
|
||||
}
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
|
||||
{
|
||||
m_ValueArrayReferencePose = reader.ReadSingleArray(reader.ReadInt32());
|
||||
}
|
||||
|
||||
m_Mirror = reader.ReadBoolean();
|
||||
m_LoopTime = reader.ReadBoolean();
|
||||
m_LoopBlend = reader.ReadBoolean();
|
||||
m_LoopBlendOrientation = reader.ReadBoolean();
|
||||
m_LoopBlendPositionY = reader.ReadBoolean();
|
||||
m_LoopBlendPositionXZ = reader.ReadBoolean();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up
|
||||
{
|
||||
m_StartAtOrigin = reader.ReadBoolean();
|
||||
}
|
||||
m_KeepOriginalOrientation = reader.ReadBoolean();
|
||||
m_KeepOriginalPositionY = reader.ReadBoolean();
|
||||
m_KeepOriginalPositionXZ = reader.ReadBoolean();
|
||||
m_HeightFromFeet = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class GenericBinding
|
||||
{
|
||||
public uint path;
|
||||
public uint attribute;
|
||||
public PPtr script;
|
||||
public ClassIDType typeID;
|
||||
public byte customType;
|
||||
public byte isPPtrCurve;
|
||||
|
||||
public GenericBinding(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
path = reader.ReadUInt32();
|
||||
attribute = reader.ReadUInt32();
|
||||
script = reader.ReadPPtr();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
{
|
||||
typeID = (ClassIDType)reader.ReadInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
typeID = (ClassIDType)reader.ReadUInt16();
|
||||
}
|
||||
customType = reader.ReadByte();
|
||||
isPPtrCurve = reader.ReadByte();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class AnimationClipBindingConstant
|
||||
{
|
||||
public List<GenericBinding> genericBindings;
|
||||
public List<PPtr> pptrCurveMapping;
|
||||
|
||||
public AnimationClipBindingConstant(ObjectReader reader)
|
||||
{
|
||||
int numBindings = reader.ReadInt32();
|
||||
genericBindings = new List<GenericBinding>(numBindings);
|
||||
for (int i = 0; i < numBindings; i++)
|
||||
{
|
||||
genericBindings.Add(new GenericBinding(reader));
|
||||
}
|
||||
|
||||
int numMappings = reader.ReadInt32();
|
||||
pptrCurveMapping = new List<PPtr>(numMappings);
|
||||
for (int i = 0; i < numMappings; i++)
|
||||
{
|
||||
pptrCurveMapping.Add(reader.ReadPPtr());
|
||||
}
|
||||
}
|
||||
|
||||
public GenericBinding FindBinding(int index)
|
||||
{
|
||||
int curves = 0;
|
||||
foreach (var b in genericBindings)
|
||||
{
|
||||
if (b.typeID == ClassIDType.Transform)
|
||||
{
|
||||
switch (b.attribute)
|
||||
{
|
||||
case 1: //kBindTransformPosition
|
||||
case 3: //kBindTransformScale
|
||||
case 4: //kBindTransformEuler
|
||||
curves += 3;
|
||||
break;
|
||||
case 2: //kBindTransformRotation
|
||||
curves += 4;
|
||||
break;
|
||||
default:
|
||||
curves += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
curves += 1;
|
||||
}
|
||||
if (curves > index)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum AnimationType
|
||||
{
|
||||
kLegacy = 1,
|
||||
kGeneric = 2,
|
||||
kHumanoid = 3
|
||||
};
|
||||
|
||||
public sealed class AnimationClip : NamedObject
|
||||
{
|
||||
public AnimationType m_AnimationType;
|
||||
public bool m_Legacy;
|
||||
public bool m_Compressed;
|
||||
public bool m_UseHighQualityCurve;
|
||||
public List<QuaternionCurve> m_RotationCurves;
|
||||
public List<CompressedAnimationCurve> m_CompressedRotationCurves;
|
||||
public List<Vector3Curve> m_EulerCurves;
|
||||
public List<Vector3Curve> m_PositionCurves;
|
||||
public List<Vector3Curve> m_ScaleCurves;
|
||||
public List<FloatCurve> m_FloatCurves;
|
||||
public List<PPtrCurve> m_PPtrCurves;
|
||||
public float m_SampleRate;
|
||||
public int m_WrapMode;
|
||||
public AABB m_Bounds;
|
||||
public uint m_MuscleClipSize;
|
||||
public ClipMuscleConstant m_MuscleClip;
|
||||
public AnimationClipBindingConstant m_ClipBindingConstant;
|
||||
//public List<AnimationEvent> m_Events;
|
||||
|
||||
|
||||
public AnimationClip(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] >= 5)//5.0 and up
|
||||
{
|
||||
m_Legacy = reader.ReadBoolean();
|
||||
}
|
||||
else if (version[0] >= 4)//4.0 and up
|
||||
{
|
||||
m_AnimationType = (AnimationType)reader.ReadInt32();
|
||||
if (m_AnimationType == AnimationType.kLegacy)
|
||||
m_Legacy = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Legacy = true;
|
||||
}
|
||||
m_Compressed = reader.ReadBoolean();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3))//4.3 and up
|
||||
{
|
||||
m_UseHighQualityCurve = reader.ReadBoolean();
|
||||
}
|
||||
reader.AlignStream(4);
|
||||
int numRCurves = reader.ReadInt32();
|
||||
m_RotationCurves = new List<QuaternionCurve>(numRCurves);
|
||||
for (int i = 0; i < numRCurves; i++)
|
||||
{
|
||||
m_RotationCurves.Add(new QuaternionCurve(reader));
|
||||
}
|
||||
|
||||
int numCRCurves = reader.ReadInt32();
|
||||
m_CompressedRotationCurves = new List<CompressedAnimationCurve>(numCRCurves);
|
||||
for (int i = 0; i < numCRCurves; i++)
|
||||
{
|
||||
m_CompressedRotationCurves.Add(new CompressedAnimationCurve(reader));
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
|
||||
{
|
||||
int numEulerCurves = reader.ReadInt32();
|
||||
m_EulerCurves = new List<Vector3Curve>(numEulerCurves);
|
||||
for (int i = 0; i < numEulerCurves; i++)
|
||||
{
|
||||
m_EulerCurves.Add(new Vector3Curve(reader));
|
||||
}
|
||||
}
|
||||
|
||||
int numPCurves = reader.ReadInt32();
|
||||
m_PositionCurves = new List<Vector3Curve>(numPCurves);
|
||||
for (int i = 0; i < numPCurves; i++)
|
||||
{
|
||||
m_PositionCurves.Add(new Vector3Curve(reader));
|
||||
}
|
||||
|
||||
int numSCurves = reader.ReadInt32();
|
||||
m_ScaleCurves = new List<Vector3Curve>(numSCurves);
|
||||
for (int i = 0; i < numSCurves; i++)
|
||||
{
|
||||
m_ScaleCurves.Add(new Vector3Curve(reader));
|
||||
}
|
||||
|
||||
int numFCurves = reader.ReadInt32();
|
||||
m_FloatCurves = new List<FloatCurve>(numFCurves);
|
||||
for (int i = 0; i < numFCurves; i++)
|
||||
{
|
||||
m_FloatCurves.Add(new FloatCurve(reader));
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
{
|
||||
int numPtrCurves = reader.ReadInt32();
|
||||
m_PPtrCurves = new List<PPtrCurve>(numPtrCurves);
|
||||
for (int i = 0; i < numPtrCurves; i++)
|
||||
{
|
||||
m_PPtrCurves.Add(new PPtrCurve(reader));
|
||||
}
|
||||
}
|
||||
|
||||
m_SampleRate = reader.ReadSingle();
|
||||
m_WrapMode = reader.ReadInt32();
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up
|
||||
{
|
||||
m_Bounds = new AABB(reader);
|
||||
}
|
||||
if (version[0] >= 4)//4.0 and up
|
||||
{
|
||||
m_MuscleClipSize = reader.ReadUInt32();
|
||||
m_MuscleClip = new ClipMuscleConstant(reader);
|
||||
}
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
{
|
||||
m_ClipBindingConstant = new AnimationClipBindingConstant(reader);
|
||||
}
|
||||
/*int numEvents = reader.ReadInt32();
|
||||
m_Events = new List<AnimationEvent>(numEvents);
|
||||
for (int i = 0; i < numEvents; i++)
|
||||
{
|
||||
m_Events.Add(new AnimationEvent(stream, file.Version[0] - '0'));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
63
AssetStudio/Classes/Animator.cs
Normal file
63
AssetStudio/Classes/Animator.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class Animator : Behaviour
|
||||
{
|
||||
public PPtr m_Avatar;
|
||||
public PPtr m_Controller;
|
||||
public bool m_HasTransformHierarchy;
|
||||
|
||||
public Animator(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Avatar = reader.ReadPPtr();
|
||||
m_Controller = reader.ReadPPtr();
|
||||
var m_CullingMode = reader.ReadInt32();
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
{
|
||||
var m_UpdateMode = reader.ReadInt32();
|
||||
}
|
||||
|
||||
var m_ApplyRootMotion = reader.ReadBoolean();
|
||||
if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down
|
||||
{
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
var m_LinearVelocityBlending = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
|
||||
{
|
||||
var m_AnimatePhysics = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
{
|
||||
m_HasTransformHierarchy = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
{
|
||||
var m_AllowConstantClipSamplingOptimization = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] >= 5 && version[0] < 2018) //5.0 and up - 2018 down
|
||||
{
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
{
|
||||
var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
558
AssetStudio/Classes/AnimatorController.cs
Normal file
558
AssetStudio/Classes/AnimatorController.cs
Normal file
@@ -0,0 +1,558 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SharpDX;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class HumanPoseMask
|
||||
{
|
||||
public uint word0;
|
||||
public uint word1;
|
||||
public uint word2;
|
||||
|
||||
public HumanPoseMask(ObjectReader reader)
|
||||
{
|
||||
word0 = reader.ReadUInt32();
|
||||
word1 = reader.ReadUInt32();
|
||||
if (reader.version[0] >= 5) //5.0 and up
|
||||
{
|
||||
word2 = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SkeletonMaskElement
|
||||
{
|
||||
public uint m_PathHash;
|
||||
public float m_Weight;
|
||||
|
||||
public SkeletonMaskElement(ObjectReader reader)
|
||||
{
|
||||
m_PathHash = reader.ReadUInt32();
|
||||
m_Weight = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
public class SkeletonMask
|
||||
{
|
||||
public SkeletonMaskElement[] m_Data;
|
||||
|
||||
public SkeletonMask(ObjectReader reader)
|
||||
{
|
||||
int numElements = reader.ReadInt32();
|
||||
m_Data = new SkeletonMaskElement[numElements];
|
||||
for (int i = 0; i < numElements; i++)
|
||||
{
|
||||
m_Data[i] = new SkeletonMaskElement(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LayerConstant
|
||||
{
|
||||
public uint m_StateMachineIndex;
|
||||
public uint m_StateMachineMotionSetIndex;
|
||||
public HumanPoseMask m_BodyMask;
|
||||
public SkeletonMask m_SkeletonMask;
|
||||
public uint m_Binding;
|
||||
public int m_LayerBlendingMode;
|
||||
public float m_DefaultWeight;
|
||||
public bool m_IKPass;
|
||||
public bool m_SyncedLayerAffectsTiming;
|
||||
|
||||
public LayerConstant(ObjectReader reader)
|
||||
{
|
||||
m_StateMachineIndex = reader.ReadUInt32();
|
||||
m_StateMachineMotionSetIndex = reader.ReadUInt32();
|
||||
m_BodyMask = new HumanPoseMask(reader);
|
||||
m_SkeletonMask = new SkeletonMask(reader);
|
||||
m_Binding = reader.ReadUInt32();
|
||||
m_LayerBlendingMode = reader.ReadInt32();
|
||||
m_DefaultWeight = reader.ReadSingle();
|
||||
m_IKPass = reader.ReadBoolean();
|
||||
m_SyncedLayerAffectsTiming = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class ConditionConstant
|
||||
{
|
||||
public uint m_ConditionMode;
|
||||
public uint m_EventID;
|
||||
public float m_EventThreshold;
|
||||
public float m_ExitTime;
|
||||
|
||||
public ConditionConstant(ObjectReader reader)
|
||||
{
|
||||
m_ConditionMode = reader.ReadUInt32();
|
||||
m_EventID = reader.ReadUInt32();
|
||||
m_EventThreshold = reader.ReadSingle();
|
||||
m_ExitTime = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
public class TransitionConstant
|
||||
{
|
||||
public ConditionConstant[] m_ConditionConstantArray;
|
||||
public uint m_DestinationState;
|
||||
public uint m_FullPathID;
|
||||
public uint m_ID;
|
||||
public uint m_UserID;
|
||||
public float m_TransitionDuration;
|
||||
public float m_TransitionOffset;
|
||||
public float m_ExitTime;
|
||||
public bool m_HasExitTime;
|
||||
public bool m_HasFixedDuration;
|
||||
public int m_InterruptionSource;
|
||||
public bool m_OrderedInterruption;
|
||||
public bool m_Atomic;
|
||||
public bool m_CanTransitionToSelf;
|
||||
|
||||
public TransitionConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
int numConditions = reader.ReadInt32();
|
||||
m_ConditionConstantArray = new ConditionConstant[numConditions];
|
||||
for (int i = 0; i < numConditions; i++)
|
||||
{
|
||||
m_ConditionConstantArray[i] = new ConditionConstant(reader);
|
||||
}
|
||||
|
||||
m_DestinationState = reader.ReadUInt32();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
m_FullPathID = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_ID = reader.ReadUInt32();
|
||||
m_UserID = reader.ReadUInt32();
|
||||
m_TransitionDuration = reader.ReadSingle();
|
||||
m_TransitionOffset = reader.ReadSingle();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
m_ExitTime = reader.ReadSingle();
|
||||
m_HasExitTime = reader.ReadBoolean();
|
||||
m_HasFixedDuration = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
m_InterruptionSource = reader.ReadInt32();
|
||||
m_OrderedInterruption = reader.ReadBoolean();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Atomic = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
m_CanTransitionToSelf = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class LeafInfoConstant
|
||||
{
|
||||
public uint[] m_IDArray;
|
||||
public uint m_IndexOffset;
|
||||
|
||||
public LeafInfoConstant(ObjectReader reader)
|
||||
{
|
||||
m_IDArray = reader.ReadUInt32Array(reader.ReadInt32());
|
||||
m_IndexOffset = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class MotionNeighborList
|
||||
{
|
||||
public uint[] m_NeighborArray;
|
||||
|
||||
public MotionNeighborList(ObjectReader reader)
|
||||
{
|
||||
m_NeighborArray = reader.ReadUInt32Array(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
|
||||
public class Blend2dDataConstant
|
||||
{
|
||||
public Vector2[] m_ChildPositionArray;
|
||||
public float[] m_ChildMagnitudeArray;
|
||||
public Vector2[] m_ChildPairVectorArray;
|
||||
public float[] m_ChildPairAvgMagInvArray;
|
||||
public MotionNeighborList[] m_ChildNeighborListArray;
|
||||
|
||||
public Blend2dDataConstant(ObjectReader reader)
|
||||
{
|
||||
m_ChildPositionArray = reader.ReadVector2Array(reader.ReadInt32());
|
||||
m_ChildMagnitudeArray = reader.ReadSingleArray(reader.ReadInt32());
|
||||
m_ChildPairVectorArray = reader.ReadVector2Array(reader.ReadInt32());
|
||||
m_ChildPairAvgMagInvArray = reader.ReadSingleArray(reader.ReadInt32());
|
||||
|
||||
int numNeighbours = reader.ReadInt32();
|
||||
m_ChildNeighborListArray = new MotionNeighborList[numNeighbours];
|
||||
for (int i = 0; i < numNeighbours; i++)
|
||||
{
|
||||
m_ChildNeighborListArray[i] = new MotionNeighborList(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Blend1dDataConstant // wrong labeled
|
||||
{
|
||||
public float[] m_ChildThresholdArray;
|
||||
|
||||
public Blend1dDataConstant(ObjectReader reader)
|
||||
{
|
||||
m_ChildThresholdArray = reader.ReadSingleArray(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
|
||||
public class BlendDirectDataConstant
|
||||
{
|
||||
public uint[] m_ChildBlendEventIDArray;
|
||||
public bool m_NormalizedBlendValues;
|
||||
|
||||
public BlendDirectDataConstant(ObjectReader reader)
|
||||
{
|
||||
m_ChildBlendEventIDArray = reader.ReadUInt32Array(reader.ReadInt32());
|
||||
m_NormalizedBlendValues = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class BlendTreeNodeConstant
|
||||
{
|
||||
public uint m_BlendType;
|
||||
public uint m_BlendEventID;
|
||||
public uint m_BlendEventYID;
|
||||
public uint[] m_ChildIndices;
|
||||
public Blend1dDataConstant m_Blend1dData;
|
||||
public Blend2dDataConstant m_Blend2dData;
|
||||
public BlendDirectDataConstant m_BlendDirectData;
|
||||
public uint m_ClipID;
|
||||
public uint m_ClipIndex;
|
||||
public float m_Duration;
|
||||
public float m_CycleOffset;
|
||||
public bool m_Mirror;
|
||||
|
||||
public BlendTreeNodeConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_BlendType = reader.ReadUInt32();
|
||||
m_BlendEventID = reader.ReadUInt32();
|
||||
m_BlendEventYID = reader.ReadUInt32();
|
||||
m_ChildIndices = reader.ReadUInt32Array(reader.ReadInt32());
|
||||
m_Blend1dData = new Blend1dDataConstant(reader);
|
||||
m_Blend2dData = new Blend2dDataConstant(reader);
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
m_BlendDirectData = new BlendDirectDataConstant(reader);
|
||||
}
|
||||
|
||||
m_ClipID = reader.ReadUInt32();
|
||||
if (version[0] < 5) //5.0 down
|
||||
{
|
||||
m_ClipIndex = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_Duration = reader.ReadSingle();
|
||||
m_CycleOffset = reader.ReadSingle();
|
||||
m_Mirror = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class BlendTreeConstant
|
||||
{
|
||||
public BlendTreeNodeConstant[] m_NodeArray;
|
||||
|
||||
public BlendTreeConstant(ObjectReader reader)
|
||||
{
|
||||
int numNodes = reader.ReadInt32();
|
||||
m_NodeArray = new BlendTreeNodeConstant[numNodes];
|
||||
for (int i = 0; i < numNodes; i++)
|
||||
{
|
||||
m_NodeArray[i] = new BlendTreeNodeConstant(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class StateConstant
|
||||
{
|
||||
public TransitionConstant[] m_TransitionConstantArray;
|
||||
public int[] m_BlendTreeConstantIndexArray;
|
||||
public LeafInfoConstant[] m_LeafInfoArray;
|
||||
public BlendTreeConstant[] m_BlendTreeConstantArray;
|
||||
public uint m_NameID;
|
||||
public uint m_PathID;
|
||||
public uint m_FullPathID;
|
||||
public uint m_TagID;
|
||||
public uint m_SpeedParamID;
|
||||
public uint m_MirrorParamID;
|
||||
public uint m_CycleOffsetParamID;
|
||||
public float m_Speed;
|
||||
public float m_CycleOffset;
|
||||
public bool m_IKOnFeet;
|
||||
public bool m_WriteDefaultValues;
|
||||
public bool m_Loop;
|
||||
public bool m_Mirror;
|
||||
|
||||
public StateConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
int numTransistions = reader.ReadInt32();
|
||||
m_TransitionConstantArray = new TransitionConstant[numTransistions];
|
||||
for (int i = 0; i < numTransistions; i++)
|
||||
{
|
||||
m_TransitionConstantArray[i] = new TransitionConstant(reader);
|
||||
}
|
||||
|
||||
int numBlendIndices = reader.ReadInt32();
|
||||
m_BlendTreeConstantIndexArray = new int[numBlendIndices];
|
||||
for (int i = 0; i < numBlendIndices; i++)
|
||||
{
|
||||
m_BlendTreeConstantIndexArray[i] = reader.ReadInt32();
|
||||
}
|
||||
|
||||
if (version[0] < 5) //5.0 down
|
||||
{
|
||||
int numInfos = reader.ReadInt32();
|
||||
m_LeafInfoArray = new LeafInfoConstant[numInfos];
|
||||
for (int i = 0; i < numInfos; i++)
|
||||
{
|
||||
m_LeafInfoArray[i] = new LeafInfoConstant(reader);
|
||||
}
|
||||
}
|
||||
|
||||
int numBlends = reader.ReadInt32();
|
||||
m_BlendTreeConstantArray = new BlendTreeConstant[numBlends];
|
||||
for (int i = 0; i < numBlends; i++)
|
||||
{
|
||||
m_BlendTreeConstantArray[i] = new BlendTreeConstant(reader);
|
||||
}
|
||||
|
||||
m_NameID = reader.ReadUInt32();
|
||||
m_PathID = reader.ReadUInt32();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
m_FullPathID = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_TagID = reader.ReadUInt32();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
m_SpeedParamID = reader.ReadUInt32();
|
||||
m_MirrorParamID = reader.ReadUInt32();
|
||||
m_CycleOffsetParamID = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
var m_TimeParamID = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_Speed = reader.ReadSingle();
|
||||
m_CycleOffset = reader.ReadSingle();
|
||||
m_IKOnFeet = reader.ReadBoolean();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
m_WriteDefaultValues = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
m_Loop = reader.ReadBoolean();
|
||||
m_Mirror = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class SelectorTransitionConstant
|
||||
{
|
||||
public uint m_Destination;
|
||||
public ConditionConstant[] m_ConditionConstantArray;
|
||||
|
||||
public SelectorTransitionConstant(ObjectReader reader)
|
||||
{
|
||||
m_Destination = reader.ReadUInt32();
|
||||
|
||||
int numConditions = reader.ReadInt32();
|
||||
m_ConditionConstantArray = new ConditionConstant[numConditions];
|
||||
for (int i = 0; i < numConditions; i++)
|
||||
{
|
||||
m_ConditionConstantArray[i] = new ConditionConstant(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SelectorStateConstant
|
||||
{
|
||||
public SelectorTransitionConstant[] m_TransitionConstantArray;
|
||||
public uint m_FullPathID;
|
||||
public bool m_isEntry;
|
||||
|
||||
public SelectorStateConstant(ObjectReader reader)
|
||||
{
|
||||
int numTransitions = reader.ReadInt32();
|
||||
m_TransitionConstantArray = new SelectorTransitionConstant[numTransitions];
|
||||
for (int i = 0; i < numTransitions; i++)
|
||||
{
|
||||
m_TransitionConstantArray[i] = new SelectorTransitionConstant(reader);
|
||||
}
|
||||
|
||||
m_FullPathID = reader.ReadUInt32();
|
||||
m_isEntry = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class StateMachineConstant
|
||||
{
|
||||
public StateConstant[] m_StateConstantArray;
|
||||
public TransitionConstant[] m_AnyStateTransitionConstantArray;
|
||||
public SelectorStateConstant[] m_SelectorStateConstantArray;
|
||||
public uint m_DefaultState;
|
||||
public uint m_MotionSetCount;
|
||||
|
||||
public StateMachineConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
int numStates = reader.ReadInt32();
|
||||
m_StateConstantArray = new StateConstant[numStates];
|
||||
for (int i = 0; i < numStates; i++)
|
||||
{
|
||||
m_StateConstantArray[i] = new StateConstant(reader);
|
||||
}
|
||||
|
||||
int numAnyStates = reader.ReadInt32();
|
||||
m_AnyStateTransitionConstantArray = new TransitionConstant[numAnyStates];
|
||||
for (int i = 0; i < numAnyStates; i++)
|
||||
{
|
||||
m_AnyStateTransitionConstantArray[i] = new TransitionConstant(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
int numSelectors = reader.ReadInt32();
|
||||
m_SelectorStateConstantArray = new SelectorStateConstant[numSelectors];
|
||||
for (int i = 0; i < numSelectors; i++)
|
||||
{
|
||||
m_SelectorStateConstantArray[i] = new SelectorStateConstant(reader);
|
||||
}
|
||||
}
|
||||
|
||||
m_DefaultState = reader.ReadUInt32();
|
||||
m_MotionSetCount = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueArray
|
||||
{
|
||||
public bool[] m_BoolValues;
|
||||
public int[] m_IntValues;
|
||||
public float[] m_FloatValues;
|
||||
public object[] m_PositionValues;
|
||||
public Vector4[] m_QuaternionValues;
|
||||
public object[] m_ScaleValues;
|
||||
|
||||
public ValueArray(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down
|
||||
{
|
||||
int numBools = reader.ReadInt32();
|
||||
m_BoolValues = new bool[numBools];
|
||||
for (int i = 0; i < numBools; i++)
|
||||
{
|
||||
m_BoolValues[i] = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
reader.AlignStream(4);
|
||||
|
||||
m_IntValues = reader.ReadInt32Array(reader.ReadInt32());
|
||||
m_FloatValues = reader.ReadSingleArray(reader.ReadInt32());
|
||||
}
|
||||
|
||||
int numPosValues = reader.ReadInt32();
|
||||
m_PositionValues = new object[numPosValues];
|
||||
for (int i = 0; i < numPosValues; i++)
|
||||
{
|
||||
m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4(); //5.4 and up
|
||||
}
|
||||
|
||||
m_QuaternionValues = reader.ReadVector4Array(reader.ReadInt32());
|
||||
|
||||
int numScaleValues = reader.ReadInt32();
|
||||
m_ScaleValues = new object[numScaleValues];
|
||||
for (int i = 0; i < numScaleValues; i++)
|
||||
{
|
||||
m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4(); //5.4 adn up
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
|
||||
{
|
||||
m_FloatValues = reader.ReadSingleArray(reader.ReadInt32());
|
||||
m_IntValues = reader.ReadInt32Array(reader.ReadInt32());
|
||||
|
||||
int numBools = reader.ReadInt32();
|
||||
m_BoolValues = new bool[numBools];
|
||||
for (int i = 0; i < numBools; i++)
|
||||
{
|
||||
m_BoolValues[i] = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ControllerConstant
|
||||
{
|
||||
public LayerConstant[] m_LayerArray;
|
||||
public StateMachineConstant[] m_StateMachineArray;
|
||||
public ValueArrayConstant m_Values;
|
||||
public ValueArray m_DefaultValues;
|
||||
|
||||
public ControllerConstant(ObjectReader reader)
|
||||
{
|
||||
int numLayers = reader.ReadInt32();
|
||||
m_LayerArray = new LayerConstant[numLayers];
|
||||
for (int i = 0; i < numLayers; i++)
|
||||
{
|
||||
m_LayerArray[i] = new LayerConstant(reader);
|
||||
}
|
||||
|
||||
int numStates = reader.ReadInt32();
|
||||
m_StateMachineArray = new StateMachineConstant[numStates];
|
||||
for (int i = 0; i < numStates; i++)
|
||||
{
|
||||
m_StateMachineArray[i] = new StateMachineConstant(reader);
|
||||
}
|
||||
|
||||
m_Values = new ValueArrayConstant(reader);
|
||||
m_DefaultValues = new ValueArray(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AnimatorController : NamedObject
|
||||
{
|
||||
public PPtr[] m_AnimationClips;
|
||||
|
||||
public AnimatorController(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_ControllerSize = reader.ReadUInt32();
|
||||
var m_Controller = new ControllerConstant(reader);
|
||||
|
||||
int tosSize = reader.ReadInt32();
|
||||
var m_TOS = new List<KeyValuePair<uint, string>>(tosSize);
|
||||
for (int i = 0; i < tosSize; i++)
|
||||
{
|
||||
m_TOS.Add(new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString()));
|
||||
}
|
||||
|
||||
int numClips = reader.ReadInt32();
|
||||
m_AnimationClips = new PPtr[numClips];
|
||||
for (int i = 0; i < numClips; i++)
|
||||
{
|
||||
m_AnimationClips[i] = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
AssetStudio/Classes/AnimatorOverrideController.cs
Normal file
27
AssetStudio/Classes/AnimatorOverrideController.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class AnimatorOverrideController : NamedObject
|
||||
{
|
||||
public PPtr m_Controller;
|
||||
public PPtr[][] m_Clips;
|
||||
|
||||
public AnimatorOverrideController(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Controller = reader.ReadPPtr();
|
||||
|
||||
int numOverrides = reader.ReadInt32();
|
||||
m_Clips = new PPtr[numOverrides][];
|
||||
for (int i = 0; i < numOverrides; i++)
|
||||
{
|
||||
m_Clips[i] = new PPtr[2];
|
||||
m_Clips[i][0] = reader.ReadPPtr();
|
||||
m_Clips[i][1] = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Unity_Studio
|
||||
namespace AssetStudio
|
||||
{
|
||||
|
||||
class AssetBundle
|
||||
public sealed class AssetBundle : NamedObject
|
||||
{
|
||||
public class AssetInfo
|
||||
{
|
||||
@@ -21,30 +21,24 @@ namespace Unity_Studio
|
||||
public AssetInfo second;
|
||||
}
|
||||
|
||||
|
||||
public List<ContainerData> m_Container = new List<ContainerData>();
|
||||
|
||||
public AssetBundle(AssetPreloadData preloadData)
|
||||
public AssetBundle(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var sourceFile = preloadData.sourceFile;
|
||||
var a_Stream = preloadData.sourceFile.a_Stream;
|
||||
a_Stream.Position = preloadData.Offset;
|
||||
|
||||
var m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32());
|
||||
var size = a_Stream.ReadInt32();
|
||||
var size = reader.ReadInt32();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
sourceFile.ReadPPtr();
|
||||
reader.ReadPPtr();
|
||||
}
|
||||
size = a_Stream.ReadInt32();
|
||||
size = reader.ReadInt32();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
var temp = new ContainerData();
|
||||
temp.first = a_Stream.ReadAlignedString(a_Stream.ReadInt32());
|
||||
temp.first = reader.ReadAlignedString();
|
||||
temp.second = new AssetInfo();
|
||||
temp.second.preloadIndex = a_Stream.ReadInt32();
|
||||
temp.second.preloadSize = a_Stream.ReadInt32();
|
||||
temp.second.asset = sourceFile.ReadPPtr();
|
||||
temp.second.preloadIndex = reader.ReadInt32();
|
||||
temp.second.preloadSize = reader.ReadInt32();
|
||||
temp.second.asset = reader.ReadPPtr();
|
||||
m_Container.Add(temp);
|
||||
}
|
||||
}
|
||||
127
AssetStudio/Classes/AudioClip.cs
Normal file
127
AssetStudio/Classes/AudioClip.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class AudioClip : NamedObject
|
||||
{
|
||||
public int m_Format;
|
||||
public AudioType m_Type;
|
||||
public bool m_3D;
|
||||
public bool m_UseHardware;
|
||||
|
||||
//version 5
|
||||
public int m_LoadType;
|
||||
public int m_Channels;
|
||||
public int m_Frequency;
|
||||
public int m_BitsPerSample;
|
||||
public float m_Length;
|
||||
public bool m_IsTrackerFormat;
|
||||
public int m_SubsoundIndex;
|
||||
public bool m_PreloadAudioData;
|
||||
public bool m_LoadInBackground;
|
||||
public bool m_Legacy3D;
|
||||
public AudioCompressionFormat m_CompressionFormat;
|
||||
|
||||
public string m_Source;
|
||||
public long m_Offset;
|
||||
public long m_Size;
|
||||
public byte[] m_AudioData;
|
||||
|
||||
public AudioClip(ObjectReader reader, bool readData) : base(reader)
|
||||
{
|
||||
if (version[0] < 5)
|
||||
{
|
||||
m_Format = reader.ReadInt32();
|
||||
m_Type = (AudioType)reader.ReadInt32();
|
||||
m_3D = reader.ReadBoolean();
|
||||
m_UseHardware = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
|
||||
if (version[0] >= 4 || (version[0] == 3 && version[1] >= 2)) //3.2.0 to 5
|
||||
{
|
||||
int m_Stream = reader.ReadInt32();
|
||||
m_Size = reader.ReadInt32();
|
||||
var tsize = m_Size % 4 != 0 ? m_Size + 4 - m_Size % 4 : m_Size;
|
||||
if (reader.byteSize + reader.byteStart - reader.Position != tsize)
|
||||
{
|
||||
m_Offset = reader.ReadInt32();
|
||||
m_Source = sourceFile.fullName + ".resS";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Size = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LoadType = reader.ReadInt32();
|
||||
m_Channels = reader.ReadInt32();
|
||||
m_Frequency = reader.ReadInt32();
|
||||
m_BitsPerSample = reader.ReadInt32();
|
||||
m_Length = reader.ReadSingle();
|
||||
m_IsTrackerFormat = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
m_SubsoundIndex = reader.ReadInt32();
|
||||
m_PreloadAudioData = reader.ReadBoolean();
|
||||
m_LoadInBackground = reader.ReadBoolean();
|
||||
m_Legacy3D = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
m_3D = m_Legacy3D;
|
||||
|
||||
m_Source = reader.ReadAlignedString();
|
||||
m_Offset = reader.ReadInt64();
|
||||
m_Size = reader.ReadInt64();
|
||||
m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();
|
||||
}
|
||||
|
||||
if (readData)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(m_Source))
|
||||
{
|
||||
m_AudioData = ResourcesHelper.GetData(m_Source, sourceFile, m_Offset, (int)m_Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Size > 0)
|
||||
m_AudioData = reader.ReadBytes((int)m_Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum AudioType
|
||||
{
|
||||
UNKNOWN,
|
||||
ACC,
|
||||
AIFF,
|
||||
IT = 10,
|
||||
MOD = 12,
|
||||
MPEG,
|
||||
OGGVORBIS,
|
||||
S3M = 17,
|
||||
WAV = 20,
|
||||
XM,
|
||||
XMA,
|
||||
VAG,
|
||||
AUDIOQUEUE
|
||||
}
|
||||
|
||||
public enum AudioCompressionFormat
|
||||
{
|
||||
PCM,
|
||||
Vorbis,
|
||||
ADPCM,
|
||||
MP3,
|
||||
VAG,
|
||||
HEVAG,
|
||||
XMA,
|
||||
AAC,
|
||||
GCADPCM,
|
||||
ATRAC9
|
||||
}
|
||||
}
|
||||
368
AssetStudio/Classes/Avatar.cs
Normal file
368
AssetStudio/Classes/Avatar.cs
Normal file
@@ -0,0 +1,368 @@
|
||||
using SharpDX;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class Node
|
||||
{
|
||||
public int m_ParentId;
|
||||
public int m_AxesId;
|
||||
|
||||
public Node(ObjectReader reader)
|
||||
{
|
||||
m_ParentId = reader.ReadInt32();
|
||||
m_AxesId = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class Limit
|
||||
{
|
||||
public object m_Min;
|
||||
public object m_Max;
|
||||
|
||||
public Limit(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up
|
||||
{
|
||||
m_Min = reader.ReadVector3();
|
||||
m_Max = reader.ReadVector3();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Min = reader.ReadVector4();
|
||||
m_Max = reader.ReadVector4();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Axes
|
||||
{
|
||||
public Vector4 m_PreQ;
|
||||
public Vector4 m_PostQ;
|
||||
public object m_Sgn;
|
||||
public Limit m_Limit;
|
||||
public float m_Length;
|
||||
public uint m_Type;
|
||||
|
||||
public Axes(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_PreQ = reader.ReadVector4();
|
||||
m_PostQ = reader.ReadVector4();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
|
||||
{
|
||||
m_Sgn = reader.ReadVector3();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Sgn = reader.ReadVector4();
|
||||
}
|
||||
m_Limit = new Limit(reader);
|
||||
m_Length = reader.ReadSingle();
|
||||
m_Type = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class Skeleton
|
||||
{
|
||||
public List<Node> m_Node;
|
||||
public List<uint> m_ID;
|
||||
public List<Axes> m_AxesArray;
|
||||
|
||||
|
||||
public Skeleton(ObjectReader reader)
|
||||
{
|
||||
int numNodes = reader.ReadInt32();
|
||||
m_Node = new List<Node>(numNodes);
|
||||
for (int i = 0; i < numNodes; i++)
|
||||
{
|
||||
m_Node.Add(new Node(reader));
|
||||
}
|
||||
|
||||
int numIDs = reader.ReadInt32();
|
||||
m_ID = new List<uint>(numIDs);
|
||||
for (int i = 0; i < numIDs; i++)
|
||||
{
|
||||
m_ID.Add(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
int numAxes = reader.ReadInt32();
|
||||
m_AxesArray = new List<Axes>(numAxes);
|
||||
for (int i = 0; i < numAxes; i++)
|
||||
{
|
||||
m_AxesArray.Add(new Axes(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SkeletonPose
|
||||
{
|
||||
public List<xform> m_X;
|
||||
|
||||
public SkeletonPose()
|
||||
{
|
||||
m_X = new List<xform>();
|
||||
}
|
||||
|
||||
public SkeletonPose(ObjectReader reader)
|
||||
{
|
||||
int numXforms = reader.ReadInt32();
|
||||
m_X = new List<xform>(numXforms);
|
||||
for (int i = 0; i < numXforms; i++)
|
||||
{
|
||||
m_X.Add(new xform(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Hand
|
||||
{
|
||||
public List<int> m_HandBoneIndex;
|
||||
|
||||
public Hand(ObjectReader reader)
|
||||
{
|
||||
int numIndexes = reader.ReadInt32();
|
||||
m_HandBoneIndex = new List<int>(numIndexes);
|
||||
for (int i = 0; i < numIndexes; i++)
|
||||
{
|
||||
m_HandBoneIndex.Add(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Handle
|
||||
{
|
||||
public xform m_X;
|
||||
public uint m_ParentHumanIndex;
|
||||
public uint m_ID;
|
||||
|
||||
public Handle(ObjectReader reader)
|
||||
{
|
||||
m_X = new xform(reader);
|
||||
m_ParentHumanIndex = reader.ReadUInt32();
|
||||
m_ID = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class Collider
|
||||
{
|
||||
public xform m_X;
|
||||
public uint m_Type;
|
||||
public uint m_XMotionType;
|
||||
public uint m_YMotionType;
|
||||
public uint m_ZMotionType;
|
||||
public float m_MinLimitX;
|
||||
public float m_MaxLimitX;
|
||||
public float m_MaxLimitY;
|
||||
public float m_MaxLimitZ;
|
||||
|
||||
public Collider(ObjectReader reader)
|
||||
{
|
||||
m_X = new xform(reader);
|
||||
m_Type = reader.ReadUInt32();
|
||||
m_XMotionType = reader.ReadUInt32();
|
||||
m_YMotionType = reader.ReadUInt32();
|
||||
m_ZMotionType = reader.ReadUInt32();
|
||||
m_MinLimitX = reader.ReadSingle();
|
||||
m_MaxLimitX = reader.ReadSingle();
|
||||
m_MaxLimitY = reader.ReadSingle();
|
||||
m_MaxLimitZ = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
public class Human
|
||||
{
|
||||
public xform m_RootX;
|
||||
public Skeleton m_Skeleton;
|
||||
public SkeletonPose m_SkeletonPose;
|
||||
public Hand m_LeftHand;
|
||||
public Hand m_RightHand;
|
||||
public List<Handle> m_Handles;
|
||||
public List<Collider> m_ColliderArray;
|
||||
public List<int> m_HumanBoneIndex;
|
||||
public List<float> m_HumanBoneMass;
|
||||
public List<int> m_ColliderIndex;
|
||||
public float m_Scale;
|
||||
public float m_ArmTwist;
|
||||
public float m_ForeArmTwist;
|
||||
public float m_UpperLegTwist;
|
||||
public float m_LegTwist;
|
||||
public float m_ArmStretch;
|
||||
public float m_LegStretch;
|
||||
public float m_FeetSpacing;
|
||||
public bool m_HasLeftHand;
|
||||
public bool m_HasRightHand;
|
||||
public bool m_HasTDoF;
|
||||
|
||||
public Human(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_RootX = new xform(reader);
|
||||
m_Skeleton = new Skeleton(reader);
|
||||
m_SkeletonPose = new SkeletonPose(reader);
|
||||
m_LeftHand = new Hand(reader);
|
||||
m_RightHand = new Hand(reader);
|
||||
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||
{
|
||||
int numHandles = reader.ReadInt32();
|
||||
m_Handles = new List<Handle>(numHandles);
|
||||
for (int i = 0; i < numHandles; i++)
|
||||
{
|
||||
m_Handles.Add(new Handle(reader));
|
||||
}
|
||||
|
||||
int numColliders = reader.ReadInt32();
|
||||
m_ColliderArray = new List<Collider>(numColliders);
|
||||
for (int i = 0; i < numColliders; i++)
|
||||
{
|
||||
m_ColliderArray.Add(new Collider(reader));
|
||||
}
|
||||
}
|
||||
|
||||
int numIndexes = reader.ReadInt32();
|
||||
m_HumanBoneIndex = new List<int>(numIndexes);
|
||||
for (int i = 0; i < numIndexes; i++)
|
||||
{
|
||||
m_HumanBoneIndex.Add(reader.ReadInt32());
|
||||
}
|
||||
|
||||
int numMasses = reader.ReadInt32();
|
||||
m_HumanBoneMass = new List<float>(numMasses);
|
||||
for (int i = 0; i < numMasses; i++)
|
||||
{
|
||||
m_HumanBoneMass.Add(reader.ReadSingle());
|
||||
}
|
||||
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||
{
|
||||
int numColliderIndexes = reader.ReadInt32();
|
||||
m_ColliderIndex = new List<int>(numColliderIndexes);
|
||||
for (int i = 0; i < numColliderIndexes; i++)
|
||||
{
|
||||
m_ColliderIndex.Add(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
|
||||
m_Scale = reader.ReadSingle();
|
||||
m_ArmTwist = reader.ReadSingle();
|
||||
m_ForeArmTwist = reader.ReadSingle();
|
||||
m_UpperLegTwist = reader.ReadSingle();
|
||||
m_LegTwist = reader.ReadSingle();
|
||||
m_ArmStretch = reader.ReadSingle();
|
||||
m_LegStretch = reader.ReadSingle();
|
||||
m_FeetSpacing = reader.ReadSingle();
|
||||
m_HasLeftHand = reader.ReadBoolean();
|
||||
m_HasRightHand = reader.ReadBoolean();
|
||||
m_HasTDoF = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class AvatarConstant
|
||||
{
|
||||
public Skeleton m_AvatarSkeleton;
|
||||
public SkeletonPose m_AvatarSkeletonPose;
|
||||
public SkeletonPose m_DefaultPose;
|
||||
public List<uint> m_SkeletonNameIDArray;
|
||||
public Human m_Human;
|
||||
public List<int> m_HumanSkeletonIndexArray;
|
||||
public List<int> m_HumanSkeletonReverseIndexArray;
|
||||
public int m_RootMotionBoneIndex;
|
||||
public xform m_RootMotionBoneX;
|
||||
public Skeleton m_RootMotionSkeleton;
|
||||
public SkeletonPose m_RootMotionSkeletonPose;
|
||||
public List<int> m_RootMotionSkeletonIndexArray;
|
||||
|
||||
public AvatarConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_AvatarSkeleton = new Skeleton(reader);
|
||||
m_AvatarSkeletonPose = new SkeletonPose(reader);
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
{
|
||||
m_DefaultPose = new SkeletonPose(reader);
|
||||
int numIDs = reader.ReadInt32();
|
||||
m_SkeletonNameIDArray = new List<uint>(numIDs);
|
||||
for (int i = 0; i < numIDs; i++)
|
||||
{
|
||||
m_SkeletonNameIDArray.Add(reader.ReadUInt32());
|
||||
}
|
||||
}
|
||||
|
||||
m_Human = new Human(reader);
|
||||
|
||||
int numIndexes = reader.ReadInt32();
|
||||
m_HumanSkeletonIndexArray = new List<int>(numIndexes);
|
||||
for (int i = 0; i < numIndexes; i++)
|
||||
{
|
||||
m_HumanSkeletonIndexArray.Add(reader.ReadInt32());
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
{
|
||||
int numReverseIndexes = reader.ReadInt32();
|
||||
m_HumanSkeletonReverseIndexArray = new List<int>(numReverseIndexes);
|
||||
for (int i = 0; i < numReverseIndexes; i++)
|
||||
{
|
||||
m_HumanSkeletonReverseIndexArray.Add(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
|
||||
m_RootMotionBoneIndex = reader.ReadInt32();
|
||||
m_RootMotionBoneX = new xform(reader);
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
{
|
||||
m_RootMotionSkeleton = new Skeleton(reader);
|
||||
m_RootMotionSkeletonPose = new SkeletonPose(reader);
|
||||
|
||||
int numMotionIndexes = reader.ReadInt32();
|
||||
m_RootMotionSkeletonIndexArray = new List<int>(numMotionIndexes);
|
||||
for (int i = 0; i < numMotionIndexes; i++)
|
||||
{
|
||||
m_RootMotionSkeletonIndexArray.Add(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Avatar : NamedObject
|
||||
{
|
||||
public uint m_AvatarSize;
|
||||
public AvatarConstant m_Avatar;
|
||||
public List<KeyValuePair<uint, string>> m_TOS;
|
||||
|
||||
public Avatar(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_AvatarSize = reader.ReadUInt32();
|
||||
m_Avatar = new AvatarConstant(reader);
|
||||
|
||||
int numTOS = reader.ReadInt32();
|
||||
m_TOS = new List<KeyValuePair<uint, string>>(numTOS);
|
||||
for (int i = 0; i < numTOS; i++)
|
||||
{
|
||||
m_TOS.Add(new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString()));
|
||||
}
|
||||
}
|
||||
|
||||
public string FindBoneName(uint hash)
|
||||
{
|
||||
foreach (var pair in m_TOS)
|
||||
{
|
||||
if (pair.Key == hash)
|
||||
{
|
||||
return pair.Value.Substring(pair.Value.LastIndexOf('/') + 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public string FindBonePath(uint hash)
|
||||
{
|
||||
return m_TOS.Find(pair => pair.Key == hash).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
AssetStudio/Classes/Behaviour.cs
Normal file
18
AssetStudio/Classes/Behaviour.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public abstract class Behaviour : Component
|
||||
{
|
||||
public byte m_Enabled;
|
||||
|
||||
protected Behaviour(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Enabled = reader.ReadByte();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
AssetStudio/Classes/BuildSettings.cs
Normal file
28
AssetStudio/Classes/BuildSettings.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class BuildSettings : Object
|
||||
{
|
||||
public string m_Version;
|
||||
|
||||
public BuildSettings(ObjectReader reader) : base(reader)
|
||||
{
|
||||
int levelsNum = reader.ReadInt32();
|
||||
for (int i = 0; i < levelsNum; i++)
|
||||
{
|
||||
var level = reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
var hasRenderTexture = reader.ReadBoolean();
|
||||
var hasPROVersion = reader.ReadBoolean();
|
||||
var hasPublishingRights = reader.ReadBoolean();
|
||||
var hasShadows = reader.ReadBoolean();
|
||||
|
||||
m_Version = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
AssetStudio/Classes/Component.cs
Normal file
17
AssetStudio/Classes/Component.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public abstract class Component : EditorExtension
|
||||
{
|
||||
public PPtr m_GameObject;
|
||||
|
||||
protected Component(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_GameObject = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
}
|
||||
19
AssetStudio/Classes/EditorExtension.cs
Normal file
19
AssetStudio/Classes/EditorExtension.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public abstract class EditorExtension : Object
|
||||
{
|
||||
protected EditorExtension(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (platform == BuildTarget.NoTarget)
|
||||
{
|
||||
var m_PrefabParentObject = reader.ReadPPtr();
|
||||
var m_PrefabInternal = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
121
AssetStudio/Classes/Font.cs
Normal file
121
AssetStudio/Classes/Font.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class Font : NamedObject
|
||||
{
|
||||
public byte[] m_FontData;
|
||||
|
||||
public Font(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up
|
||||
{
|
||||
var m_LineSpacing = reader.ReadSingle();
|
||||
var m_DefaultMaterial = reader.ReadPPtr();
|
||||
var m_FontSize = reader.ReadSingle();
|
||||
var m_Texture = reader.ReadPPtr();
|
||||
int m_AsciiStartOffset = reader.ReadInt32();
|
||||
var m_Tracking = reader.ReadSingle();
|
||||
var m_CharacterSpacing = reader.ReadInt32();
|
||||
var m_CharacterPadding = reader.ReadInt32();
|
||||
var m_ConvertCase = reader.ReadInt32();
|
||||
int m_CharacterRects_size = reader.ReadInt32();
|
||||
for (int i = 0; i < m_CharacterRects_size; i++)
|
||||
{
|
||||
reader.Position += 44;//CharacterInfo data 41
|
||||
}
|
||||
int m_KerningValues_size = reader.ReadInt32();
|
||||
for (int i = 0; i < m_KerningValues_size; i++)
|
||||
{
|
||||
reader.Position += 8;
|
||||
}
|
||||
var m_PixelScale = reader.ReadSingle();
|
||||
int m_FontData_size = reader.ReadInt32();
|
||||
if (m_FontData_size > 0)
|
||||
{
|
||||
m_FontData = reader.ReadBytes(m_FontData_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int m_AsciiStartOffset = reader.ReadInt32();
|
||||
|
||||
if (version[0] <= 3)
|
||||
{
|
||||
int m_FontCountX = reader.ReadInt32();
|
||||
int m_FontCountY = reader.ReadInt32();
|
||||
}
|
||||
|
||||
float m_Kerning = reader.ReadSingle();
|
||||
float m_LineSpacing = reader.ReadSingle();
|
||||
|
||||
if (version[0] <= 3)
|
||||
{
|
||||
int m_PerCharacterKerning_size = reader.ReadInt32();
|
||||
for (int i = 0; i < m_PerCharacterKerning_size; i++)
|
||||
{
|
||||
int first = reader.ReadInt32();
|
||||
float second = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int m_CharacterSpacing = reader.ReadInt32();
|
||||
int m_CharacterPadding = reader.ReadInt32();
|
||||
}
|
||||
|
||||
int m_ConvertCase = reader.ReadInt32();
|
||||
PPtr m_DefaultMaterial = reader.ReadPPtr();
|
||||
|
||||
int m_CharacterRects_size = reader.ReadInt32();
|
||||
for (int i = 0; i < m_CharacterRects_size; i++)
|
||||
{
|
||||
int index = reader.ReadInt32();
|
||||
//Rectf uv
|
||||
float uvx = reader.ReadSingle();
|
||||
float uvy = reader.ReadSingle();
|
||||
float uvwidth = reader.ReadSingle();
|
||||
float uvheight = reader.ReadSingle();
|
||||
//Rectf vert
|
||||
float vertx = reader.ReadSingle();
|
||||
float verty = reader.ReadSingle();
|
||||
float vertwidth = reader.ReadSingle();
|
||||
float vertheight = reader.ReadSingle();
|
||||
float width = reader.ReadSingle();
|
||||
|
||||
if (version[0] >= 4)
|
||||
{
|
||||
var flipped = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
PPtr m_Texture = reader.ReadPPtr();
|
||||
|
||||
int m_KerningValues_size = reader.ReadInt32();
|
||||
for (int i = 0; i < m_KerningValues_size; i++)
|
||||
{
|
||||
int pairfirst = reader.ReadInt16();
|
||||
int pairsecond = reader.ReadInt16();
|
||||
float second = reader.ReadSingle();
|
||||
}
|
||||
|
||||
if (version[0] <= 3)
|
||||
{
|
||||
var m_GridFont = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
else { float m_PixelScale = reader.ReadSingle(); }
|
||||
|
||||
int m_FontData_size = reader.ReadInt32();
|
||||
if (m_FontData_size > 0)
|
||||
{
|
||||
m_FontData = reader.ReadBytes(m_FontData_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
AssetStudio/Classes/GameObject.cs
Normal file
39
AssetStudio/Classes/GameObject.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class GameObject : EditorExtension
|
||||
{
|
||||
public List<PPtr> m_Components;
|
||||
public string m_Name;
|
||||
public PPtr m_Transform;
|
||||
public PPtr m_MeshRenderer;
|
||||
public PPtr m_MeshFilter;
|
||||
public PPtr m_SkinnedMeshRenderer;
|
||||
public PPtr m_Animator;
|
||||
|
||||
public GameObject(ObjectReader reader) : base(reader)
|
||||
{
|
||||
int m_Component_size = reader.ReadInt32();
|
||||
m_Components = new List<PPtr>(m_Component_size);
|
||||
for (int j = 0; j < m_Component_size; j++)
|
||||
{
|
||||
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5.0 and up
|
||||
{
|
||||
m_Components.Add(reader.ReadPPtr());
|
||||
}
|
||||
else
|
||||
{
|
||||
int first = reader.ReadInt32();
|
||||
m_Components.Add(reader.ReadPPtr());
|
||||
}
|
||||
}
|
||||
|
||||
var m_Layer = reader.ReadInt32();
|
||||
m_Name = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
}
|
||||
117
AssetStudio/Classes/Material.cs
Normal file
117
AssetStudio/Classes/Material.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class TexEnv
|
||||
{
|
||||
public string name;
|
||||
public PPtr m_Texture;
|
||||
public float[] m_Scale;
|
||||
public float[] m_Offset;
|
||||
}
|
||||
|
||||
public class strFloatPair
|
||||
{
|
||||
public string first;
|
||||
public float second;
|
||||
}
|
||||
|
||||
public class strColorPair
|
||||
{
|
||||
public string first;
|
||||
public float[] second;
|
||||
}
|
||||
|
||||
public sealed class Material : NamedObject
|
||||
{
|
||||
public PPtr m_Shader;
|
||||
public string[] m_ShaderKeywords;
|
||||
public int m_CustomRenderQueue;
|
||||
public TexEnv[] m_TexEnvs;
|
||||
public strFloatPair[] m_Floats;
|
||||
public strColorPair[] m_Colors;
|
||||
|
||||
public Material(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Shader = reader.ReadPPtr();
|
||||
|
||||
if (version[0] == 4 && (version[1] >= 2 || (version[1] == 1 && !buildType.IsAlpha)))
|
||||
{
|
||||
m_ShaderKeywords = new string[reader.ReadInt32()];
|
||||
for (int i = 0; i < m_ShaderKeywords.Length; i++)
|
||||
{
|
||||
m_ShaderKeywords[i] = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
else if (version[0] >= 5)//5.0 and up
|
||||
{
|
||||
m_ShaderKeywords = new[] { reader.ReadAlignedString() };
|
||||
uint m_LightmapFlags = reader.ReadUInt32();
|
||||
if (version[0] == 5 && version[1] >= 6 || version[0] > 5)//5.6.0 and up
|
||||
{
|
||||
var m_EnableInstancingVariants = reader.ReadBoolean();
|
||||
//var m_DoubleSidedGI = a_Stream.ReadBoolean();//2017.x
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] > 4 || version[0] == 4 && version[1] >= 3) { m_CustomRenderQueue = reader.ReadInt32(); }
|
||||
|
||||
if (version[0] == 5 && version[1] >= 1 || version[0] > 5)//5.1 and up
|
||||
{
|
||||
string[][] stringTagMap = new string[reader.ReadInt32()][];
|
||||
for (int i = 0; i < stringTagMap.Length; i++)
|
||||
{
|
||||
stringTagMap[i] = new[] { reader.ReadAlignedString(), reader.ReadAlignedString() };
|
||||
}
|
||||
}
|
||||
//disabledShaderPasses
|
||||
if ((version[0] == 5 && version[1] >= 6) || version[0] > 5)//5.6.0 and up
|
||||
{
|
||||
var size = reader.ReadInt32();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
//m_SavedProperties
|
||||
m_TexEnvs = new TexEnv[reader.ReadInt32()];
|
||||
for (int i = 0; i < m_TexEnvs.Length; i++)
|
||||
{
|
||||
TexEnv m_TexEnv = new TexEnv()
|
||||
{
|
||||
name = reader.ReadAlignedString(),
|
||||
m_Texture = reader.ReadPPtr(),
|
||||
m_Scale = new[] { reader.ReadSingle(), reader.ReadSingle() },
|
||||
m_Offset = new[] { reader.ReadSingle(), reader.ReadSingle() }
|
||||
};
|
||||
m_TexEnvs[i] = m_TexEnv;
|
||||
}
|
||||
|
||||
m_Floats = new strFloatPair[reader.ReadInt32()];
|
||||
for (int i = 0; i < m_Floats.Length; i++)
|
||||
{
|
||||
strFloatPair m_Float = new strFloatPair()
|
||||
{
|
||||
first = reader.ReadAlignedString(),
|
||||
second = reader.ReadSingle()
|
||||
};
|
||||
m_Floats[i] = m_Float;
|
||||
}
|
||||
|
||||
m_Colors = new strColorPair[reader.ReadInt32()];
|
||||
for (int i = 0; i < m_Colors.Length; i++)
|
||||
{
|
||||
strColorPair m_Color = new strColorPair()
|
||||
{
|
||||
first = reader.ReadAlignedString(),
|
||||
second = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }
|
||||
};
|
||||
m_Colors[i] = m_Color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1138
AssetStudio/Classes/Mesh.cs
Normal file
1138
AssetStudio/Classes/Mesh.cs
Normal file
File diff suppressed because it is too large
Load Diff
18
AssetStudio/Classes/MeshFilter.cs
Normal file
18
AssetStudio/Classes/MeshFilter.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class MeshFilter : Component
|
||||
{
|
||||
public long preloadIndex;
|
||||
public PPtr m_Mesh;
|
||||
|
||||
public MeshFilter(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Mesh = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
AssetStudio/Classes/MeshRenderer.cs
Normal file
15
AssetStudio/Classes/MeshRenderer.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class MeshRenderer : Renderer
|
||||
{
|
||||
public MeshRenderer(ObjectReader reader) : base(reader)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
19
AssetStudio/Classes/MonoBehaviour.cs
Normal file
19
AssetStudio/Classes/MonoBehaviour.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class MonoBehaviour : Behaviour
|
||||
{
|
||||
public PPtr m_Script;
|
||||
public string m_Name;
|
||||
|
||||
public MonoBehaviour(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Script = reader.ReadPPtr();
|
||||
m_Name = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
}
|
||||
44
AssetStudio/Classes/MonoScript.cs
Normal file
44
AssetStudio/Classes/MonoScript.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class MonoScript : NamedObject
|
||||
{
|
||||
public string m_ClassName;
|
||||
public string m_Namespace = string.Empty;
|
||||
public string m_AssemblyName;
|
||||
|
||||
public MonoScript(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up
|
||||
{
|
||||
var m_ExecutionOrder = reader.ReadInt32();
|
||||
}
|
||||
if (version[0] < 5) //5.0 down
|
||||
{
|
||||
var m_PropertiesHash = reader.ReadUInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
var m_PropertiesHash = reader.ReadBytes(16);
|
||||
}
|
||||
if (version[0] < 3) //3.0 down
|
||||
{
|
||||
var m_PathName = reader.ReadAlignedString();
|
||||
}
|
||||
m_ClassName = reader.ReadAlignedString();
|
||||
if (version[0] >= 3) //3.0 and up
|
||||
{
|
||||
m_Namespace = reader.ReadAlignedString();
|
||||
}
|
||||
m_AssemblyName = reader.ReadAlignedString();
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||
{
|
||||
var m_IsEditorScript = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
AssetStudio/Classes/MovieTexture.cs
Normal file
21
AssetStudio/Classes/MovieTexture.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class MovieTexture : Texture
|
||||
{
|
||||
public byte[] m_MovieData;
|
||||
|
||||
public MovieTexture(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_Loop = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
//PPtr<AudioClip>
|
||||
reader.ReadPPtr();
|
||||
m_MovieData = reader.ReadBytes(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
17
AssetStudio/Classes/NamedObject.cs
Normal file
17
AssetStudio/Classes/NamedObject.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class NamedObject : EditorExtension
|
||||
{
|
||||
public string m_Name;
|
||||
|
||||
public NamedObject(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Name = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
AssetStudio/Classes/Object.cs
Normal file
31
AssetStudio/Classes/Object.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public abstract class Object
|
||||
{
|
||||
protected SerializedFile sourceFile;
|
||||
public ObjectReader reader;
|
||||
public int[] version;
|
||||
protected BuildType buildType;
|
||||
public BuildTarget platform;
|
||||
|
||||
protected Object(ObjectReader reader)
|
||||
{
|
||||
this.reader = reader;
|
||||
reader.Reset();
|
||||
sourceFile = reader.assetsFile;
|
||||
version = reader.version;
|
||||
buildType = reader.buildType;
|
||||
platform = reader.platform;
|
||||
|
||||
if (platform == BuildTarget.NoTarget)
|
||||
{
|
||||
var m_ObjectHideFlags = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
AssetStudio/Classes/PPtr.cs
Normal file
89
AssetStudio/Classes/PPtr.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class PPtr
|
||||
{
|
||||
public int m_FileID;
|
||||
public long m_PathID;
|
||||
|
||||
public SerializedFile assetsFile;
|
||||
public int index = -2; //-2 - Prepare, -1 - Missing
|
||||
|
||||
private bool TryGetAssetsFile(out SerializedFile result)
|
||||
{
|
||||
result = null;
|
||||
if (m_FileID == 0)
|
||||
{
|
||||
result = assetsFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)
|
||||
{
|
||||
var assetsManager = assetsFile.assetsManager;
|
||||
var assetsfileList = assetsManager.assetsFileList;
|
||||
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
|
||||
|
||||
if (index == -2)
|
||||
{
|
||||
var m_External = assetsFile.m_Externals[m_FileID - 1];
|
||||
var name = m_External.fileName.ToUpper();
|
||||
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
||||
{
|
||||
index = assetsfileList.FindIndex(x => x.upperFileName == name);
|
||||
assetsFileIndexCache.Add(name, index);
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
result = assetsfileList[index];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGet(out ObjectReader result)
|
||||
{
|
||||
result = null;
|
||||
if (TryGetAssetsFile(out var sourceFile))
|
||||
{
|
||||
if (sourceFile.ObjectReaders.TryGetValue(m_PathID, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetTransform(out Transform m_Transform)
|
||||
{
|
||||
if (TryGetAssetsFile(out var sourceFile))
|
||||
{
|
||||
if (sourceFile.Transforms.TryGetValue(m_PathID, out m_Transform))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_Transform = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetGameObject(out GameObject m_GameObject)
|
||||
{
|
||||
if (TryGetAssetsFile(out var sourceFile))
|
||||
{
|
||||
if (sourceFile.GameObjects.TryGetValue(m_PathID, out m_GameObject))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_GameObject = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
51
AssetStudio/Classes/PlayerSettings.cs
Normal file
51
AssetStudio/Classes/PlayerSettings.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class PlayerSettings : Object
|
||||
{
|
||||
public string companyName;
|
||||
public string productName;
|
||||
|
||||
public PlayerSettings(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4.0 nad up
|
||||
{
|
||||
var productGUID = reader.ReadBytes(16);
|
||||
}
|
||||
|
||||
var AndroidProfiler = reader.ReadBoolean();
|
||||
//bool AndroidFilterTouchesWhenObscured 2017.2 and up
|
||||
//bool AndroidEnableSustainedPerformanceMode 2018 and up
|
||||
reader.AlignStream(4);
|
||||
int defaultScreenOrientation = reader.ReadInt32();
|
||||
int targetDevice = reader.ReadInt32();
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 3)) //5.3 down
|
||||
{
|
||||
if (version[0] < 5) //5.0 down
|
||||
{
|
||||
int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 6)) //4.6 and up
|
||||
{
|
||||
var targetIOSGraphics = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
int targetResolution = reader.ReadInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
var useOnDemandResources = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
|
||||
{
|
||||
var accelerometerFrequency = reader.ReadInt32();
|
||||
}
|
||||
companyName = reader.ReadAlignedString();
|
||||
productName = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
}
|
||||
14
AssetStudio/Classes/RectTransform.cs
Normal file
14
AssetStudio/Classes/RectTransform.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class RectTransform : Transform
|
||||
{
|
||||
public RectTransform(ObjectReader reader) : base(reader)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
116
AssetStudio/Classes/Renderer.cs
Normal file
116
AssetStudio/Classes/Renderer.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StaticBatchInfo
|
||||
{
|
||||
public ushort firstSubMesh;
|
||||
public ushort subMeshCount;
|
||||
}
|
||||
|
||||
public abstract class Renderer : Component
|
||||
{
|
||||
public PPtr[] m_Materials;
|
||||
public StaticBatchInfo m_StaticBatchInfo;
|
||||
public uint[] m_SubsetIndices;
|
||||
|
||||
protected Renderer(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] < 5)
|
||||
{
|
||||
var m_Enabled = reader.ReadBoolean();
|
||||
var m_CastShadows = reader.ReadByte();
|
||||
var m_ReceiveShadows = reader.ReadBoolean();
|
||||
var m_LightmapIndex = reader.ReadByte();
|
||||
}
|
||||
else
|
||||
{
|
||||
var m_Enabled = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
var m_CastShadows = reader.ReadByte();
|
||||
var m_ReceiveShadows = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
if (version[0] >= 2018)//2018 and up
|
||||
{
|
||||
var m_RenderingLayerMask = reader.ReadUInt32();
|
||||
}
|
||||
var m_LightmapIndex = reader.ReadUInt16();
|
||||
var m_LightmapIndexDynamic = reader.ReadUInt16();
|
||||
}
|
||||
|
||||
if (version[0] >= 3)
|
||||
{
|
||||
reader.Position += 16;//Vector4f m_LightmapTilingOffset
|
||||
}
|
||||
|
||||
if (version[0] >= 5)
|
||||
{
|
||||
reader.Position += 16;//Vector4f m_LightmapTilingOffsetDynamic
|
||||
}
|
||||
|
||||
m_Materials = new PPtr[reader.ReadInt32()];
|
||||
for (int m = 0; m < m_Materials.Length; m++)
|
||||
{
|
||||
m_Materials[m] = reader.ReadPPtr();
|
||||
}
|
||||
|
||||
if (version[0] < 3)
|
||||
{
|
||||
reader.Position += 16;//m_LightmapTilingOffset vector4d
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5.0 and up
|
||||
{
|
||||
m_StaticBatchInfo = new StaticBatchInfo
|
||||
{
|
||||
firstSubMesh = reader.ReadUInt16(),
|
||||
subMeshCount = reader.ReadUInt16()
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
int numSubsetIndices = reader.ReadInt32();
|
||||
m_SubsetIndices = reader.ReadUInt32Array(numSubsetIndices);
|
||||
}
|
||||
|
||||
var m_StaticBatchRoot = reader.ReadPPtr();
|
||||
|
||||
if ((version[0] == 5 && version[1] >= 4) || version[0] > 5)//5.4.0 and up
|
||||
{
|
||||
var m_ProbeAnchor = reader.ReadPPtr();
|
||||
var m_LightProbeVolumeOverride = reader.ReadPPtr();
|
||||
}
|
||||
else if (version[0] >= 4 || (version[0] == 3 && version[1] >= 5))//3.5 - 5.3
|
||||
{
|
||||
var m_UseLightProbes = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
if (version[0] == 5)//5.0 and up
|
||||
{
|
||||
int m_ReflectionProbeUsage = reader.ReadInt32();
|
||||
}
|
||||
var m_LightProbeAnchor = reader.ReadPPtr();
|
||||
}
|
||||
|
||||
if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3))//4.3 and up
|
||||
{
|
||||
if (version[0] == 4 && version[1] == 3)//4.3
|
||||
{
|
||||
int m_SortingLayer = reader.ReadInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
int m_SortingLayerID = reader.ReadInt32();
|
||||
//SInt16 m_SortingOrder 5.6 and up
|
||||
}
|
||||
|
||||
int m_SortingOrder = reader.ReadInt16();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
796
AssetStudio/Classes/Shader.cs
Normal file
796
AssetStudio/Classes/Shader.cs
Normal file
@@ -0,0 +1,796 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StructParameter
|
||||
{
|
||||
public List<MatrixParameter> m_MatrixParams;
|
||||
public List<VectorParameter> m_VectorParams;
|
||||
|
||||
public StructParameter(BinaryReader reader)
|
||||
{
|
||||
var m_NameIndex = reader.ReadInt32();
|
||||
var m_Index = reader.ReadInt32();
|
||||
var m_ArraySize = reader.ReadInt32();
|
||||
var m_StructSize = reader.ReadInt32();
|
||||
|
||||
int numVectorParams = reader.ReadInt32();
|
||||
m_VectorParams = new List<VectorParameter>(numVectorParams);
|
||||
for (int i = 0; i < numVectorParams; i++)
|
||||
{
|
||||
m_VectorParams.Add(new VectorParameter(reader));
|
||||
}
|
||||
|
||||
int numMatrixParams = reader.ReadInt32();
|
||||
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
|
||||
for (int i = 0; i < numMatrixParams; i++)
|
||||
{
|
||||
m_MatrixParams.Add(new MatrixParameter(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SamplerParameter
|
||||
{
|
||||
public uint sampler;
|
||||
public int bindPoint;
|
||||
|
||||
public SamplerParameter(BinaryReader reader)
|
||||
{
|
||||
sampler = reader.ReadUInt32();
|
||||
bindPoint = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
public enum TextureDimension
|
||||
{
|
||||
kTexDimUnknown = -1,
|
||||
kTexDimNone = 0,
|
||||
kTexDimAny = 1,
|
||||
kTexDim2D = 2,
|
||||
kTexDim3D = 3,
|
||||
kTexDimCUBE = 4,
|
||||
kTexDim2DArray = 5,
|
||||
kTexDimCubeArray = 6,
|
||||
kTexDimForce32Bit = 2147483647
|
||||
};
|
||||
|
||||
public class SerializedTextureProperty
|
||||
{
|
||||
public string m_DefaultName;
|
||||
public TextureDimension m_TexDim;
|
||||
|
||||
public SerializedTextureProperty(BinaryReader reader)
|
||||
{
|
||||
m_DefaultName = reader.ReadAlignedString();
|
||||
m_TexDim = (TextureDimension)reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public enum SerializedPropertyType
|
||||
{
|
||||
kColor = 0,
|
||||
kVector = 1,
|
||||
kFloat = 2,
|
||||
kRange = 3,
|
||||
kTexture = 4
|
||||
};
|
||||
|
||||
public class SerializedProperty
|
||||
{
|
||||
public string m_Name;
|
||||
public string m_Description;
|
||||
public List<string> m_Attributes;
|
||||
public SerializedPropertyType m_Type;
|
||||
public uint m_Flags;
|
||||
public List<float> m_DefValue;
|
||||
public SerializedTextureProperty m_DefTexture;
|
||||
|
||||
public SerializedProperty(BinaryReader reader)
|
||||
{
|
||||
m_Name = reader.ReadAlignedString();
|
||||
m_Description = reader.ReadAlignedString();
|
||||
|
||||
int numAttributes = reader.ReadInt32();
|
||||
m_Attributes = new List<string>(numAttributes);
|
||||
for (int i = 0; i < numAttributes; i++)
|
||||
{
|
||||
m_Attributes.Add(reader.ReadAlignedString());
|
||||
}
|
||||
|
||||
m_Type = (SerializedPropertyType)reader.ReadInt32();
|
||||
m_Flags = reader.ReadUInt32();
|
||||
|
||||
int numValues = 4;
|
||||
m_DefValue = new List<float>(numValues);
|
||||
for (int i = 0; i < numValues; i++)
|
||||
{
|
||||
m_DefValue.Add(reader.ReadSingle());
|
||||
}
|
||||
|
||||
m_DefTexture = new SerializedTextureProperty(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedProperties
|
||||
{
|
||||
public List<SerializedProperty> m_Props;
|
||||
|
||||
public SerializedProperties(BinaryReader reader)
|
||||
{
|
||||
int numProps = reader.ReadInt32();
|
||||
m_Props = new List<SerializedProperty>(numProps);
|
||||
for (int i = 0; i < numProps; i++)
|
||||
{
|
||||
m_Props.Add(new SerializedProperty(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedShaderFloatValue
|
||||
{
|
||||
public float val;
|
||||
public string name;
|
||||
|
||||
public SerializedShaderFloatValue(BinaryReader reader)
|
||||
{
|
||||
val = reader.ReadSingle();
|
||||
name = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedShaderRTBlendState
|
||||
{
|
||||
public SerializedShaderFloatValue srcBlend;
|
||||
public SerializedShaderFloatValue destBlend;
|
||||
public SerializedShaderFloatValue srcBlendAlpha;
|
||||
public SerializedShaderFloatValue destBlendAlpha;
|
||||
public SerializedShaderFloatValue blendOp;
|
||||
public SerializedShaderFloatValue blendOpAlpha;
|
||||
public SerializedShaderFloatValue colMask;
|
||||
|
||||
public SerializedShaderRTBlendState(BinaryReader reader)
|
||||
{
|
||||
srcBlend = new SerializedShaderFloatValue(reader);
|
||||
destBlend = new SerializedShaderFloatValue(reader);
|
||||
srcBlendAlpha = new SerializedShaderFloatValue(reader);
|
||||
destBlendAlpha = new SerializedShaderFloatValue(reader);
|
||||
blendOp = new SerializedShaderFloatValue(reader);
|
||||
blendOpAlpha = new SerializedShaderFloatValue(reader);
|
||||
colMask = new SerializedShaderFloatValue(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedStencilOp
|
||||
{
|
||||
public SerializedShaderFloatValue pass;
|
||||
public SerializedShaderFloatValue fail;
|
||||
public SerializedShaderFloatValue zFail;
|
||||
public SerializedShaderFloatValue comp;
|
||||
|
||||
public SerializedStencilOp(BinaryReader reader)
|
||||
{
|
||||
pass = new SerializedShaderFloatValue(reader);
|
||||
fail = new SerializedShaderFloatValue(reader);
|
||||
zFail = new SerializedShaderFloatValue(reader);
|
||||
comp = new SerializedShaderFloatValue(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedShaderVectorValue
|
||||
{
|
||||
public SerializedShaderFloatValue x;
|
||||
public SerializedShaderFloatValue y;
|
||||
public SerializedShaderFloatValue z;
|
||||
public SerializedShaderFloatValue w;
|
||||
public string name;
|
||||
|
||||
public SerializedShaderVectorValue(BinaryReader reader)
|
||||
{
|
||||
x = new SerializedShaderFloatValue(reader);
|
||||
y = new SerializedShaderFloatValue(reader);
|
||||
z = new SerializedShaderFloatValue(reader);
|
||||
w = new SerializedShaderFloatValue(reader);
|
||||
name = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
public enum FogMode
|
||||
{
|
||||
kFogUnknown = -1,
|
||||
kFogDisabled = 0,
|
||||
kFogLinear = 1,
|
||||
kFogExp = 2,
|
||||
kFogExp2 = 3,
|
||||
kFogModeCount = 4
|
||||
};
|
||||
|
||||
public class SerializedShaderState
|
||||
{
|
||||
public string m_Name;
|
||||
public SerializedShaderRTBlendState rtBlend0;
|
||||
public SerializedShaderRTBlendState rtBlend1;
|
||||
public SerializedShaderRTBlendState rtBlend2;
|
||||
public SerializedShaderRTBlendState rtBlend3;
|
||||
public SerializedShaderRTBlendState rtBlend4;
|
||||
public SerializedShaderRTBlendState rtBlend5;
|
||||
public SerializedShaderRTBlendState rtBlend6;
|
||||
public SerializedShaderRTBlendState rtBlend7;
|
||||
public bool rtSeparateBlend;
|
||||
public SerializedShaderFloatValue zClip;
|
||||
public SerializedShaderFloatValue zTest;
|
||||
public SerializedShaderFloatValue zWrite;
|
||||
public SerializedShaderFloatValue culling;
|
||||
public SerializedShaderFloatValue offsetFactor;
|
||||
public SerializedShaderFloatValue offsetUnits;
|
||||
public SerializedShaderFloatValue alphaToMask;
|
||||
public SerializedStencilOp stencilOp;
|
||||
public SerializedStencilOp stencilOpFront;
|
||||
public SerializedStencilOp stencilOpBack;
|
||||
public SerializedShaderFloatValue stencilReadMask;
|
||||
public SerializedShaderFloatValue stencilWriteMask;
|
||||
public SerializedShaderFloatValue stencilRef;
|
||||
public SerializedShaderFloatValue fogStart;
|
||||
public SerializedShaderFloatValue fogEnd;
|
||||
public SerializedShaderFloatValue fogDensity;
|
||||
public SerializedShaderVectorValue fogColor;
|
||||
public FogMode fogMode;
|
||||
public int gpuProgramID;
|
||||
public SerializedTagMap m_Tags;
|
||||
public int m_LOD;
|
||||
public bool lighting;
|
||||
|
||||
public SerializedShaderState(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
m_Name = reader.ReadAlignedString();
|
||||
rtBlend0 = new SerializedShaderRTBlendState(reader);
|
||||
rtBlend1 = new SerializedShaderRTBlendState(reader);
|
||||
rtBlend2 = new SerializedShaderRTBlendState(reader);
|
||||
rtBlend3 = new SerializedShaderRTBlendState(reader);
|
||||
rtBlend4 = new SerializedShaderRTBlendState(reader);
|
||||
rtBlend5 = new SerializedShaderRTBlendState(reader);
|
||||
rtBlend6 = new SerializedShaderRTBlendState(reader);
|
||||
rtBlend7 = new SerializedShaderRTBlendState(reader);
|
||||
rtSeparateBlend = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
zClip = new SerializedShaderFloatValue(reader);
|
||||
}
|
||||
zTest = new SerializedShaderFloatValue(reader);
|
||||
zWrite = new SerializedShaderFloatValue(reader);
|
||||
culling = new SerializedShaderFloatValue(reader);
|
||||
offsetFactor = new SerializedShaderFloatValue(reader);
|
||||
offsetUnits = new SerializedShaderFloatValue(reader);
|
||||
alphaToMask = new SerializedShaderFloatValue(reader);
|
||||
stencilOp = new SerializedStencilOp(reader);
|
||||
stencilOpFront = new SerializedStencilOp(reader);
|
||||
stencilOpBack = new SerializedStencilOp(reader);
|
||||
stencilReadMask = new SerializedShaderFloatValue(reader);
|
||||
stencilWriteMask = new SerializedShaderFloatValue(reader);
|
||||
stencilRef = new SerializedShaderFloatValue(reader);
|
||||
fogStart = new SerializedShaderFloatValue(reader);
|
||||
fogEnd = new SerializedShaderFloatValue(reader);
|
||||
fogDensity = new SerializedShaderFloatValue(reader);
|
||||
fogColor = new SerializedShaderVectorValue(reader);
|
||||
fogMode = (FogMode)reader.ReadInt32();
|
||||
gpuProgramID = reader.ReadInt32();
|
||||
m_Tags = new SerializedTagMap(reader);
|
||||
m_LOD = reader.ReadInt32();
|
||||
lighting = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class ShaderBindChannel
|
||||
{
|
||||
public sbyte source;
|
||||
public sbyte target;
|
||||
|
||||
public ShaderBindChannel(BinaryReader reader)
|
||||
{
|
||||
source = reader.ReadSByte();
|
||||
target = reader.ReadSByte();
|
||||
}
|
||||
}
|
||||
|
||||
public class ParserBindChannels
|
||||
{
|
||||
public List<ShaderBindChannel> m_Channels;
|
||||
public uint m_SourceMap;
|
||||
|
||||
public ParserBindChannels(BinaryReader reader)
|
||||
{
|
||||
int numChannels = reader.ReadInt32();
|
||||
m_Channels = new List<ShaderBindChannel>(numChannels);
|
||||
for (int i = 0; i < numChannels; i++)
|
||||
{
|
||||
m_Channels.Add(new ShaderBindChannel(reader));
|
||||
}
|
||||
reader.AlignStream(4);
|
||||
|
||||
m_SourceMap = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class VectorParameter
|
||||
{
|
||||
public int m_NameIndex;
|
||||
public int m_Index;
|
||||
public int m_ArraySize;
|
||||
public sbyte m_Type;
|
||||
public sbyte m_Dim;
|
||||
|
||||
public VectorParameter(BinaryReader reader)
|
||||
{
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
m_ArraySize = reader.ReadInt32();
|
||||
m_Type = reader.ReadSByte();
|
||||
m_Dim = reader.ReadSByte();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class MatrixParameter
|
||||
{
|
||||
public int m_NameIndex;
|
||||
public int m_Index;
|
||||
public int m_ArraySize;
|
||||
public sbyte m_Type;
|
||||
public sbyte m_RowCount;
|
||||
|
||||
public MatrixParameter(BinaryReader reader)
|
||||
{
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
m_ArraySize = reader.ReadInt32();
|
||||
m_Type = reader.ReadSByte();
|
||||
m_RowCount = reader.ReadSByte();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class TextureParameter
|
||||
{
|
||||
public int m_NameIndex;
|
||||
public int m_Index;
|
||||
public int m_SamplerIndex;
|
||||
public sbyte m_Dim;
|
||||
|
||||
public TextureParameter(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
m_SamplerIndex = reader.ReadInt32();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
{
|
||||
var m_MultiSampled = reader.ReadBoolean();
|
||||
}
|
||||
m_Dim = reader.ReadSByte();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferBinding
|
||||
{
|
||||
public int m_NameIndex;
|
||||
public int m_Index;
|
||||
|
||||
public BufferBinding(BinaryReader reader)
|
||||
{
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstantBuffer
|
||||
{
|
||||
public int m_NameIndex;
|
||||
public List<MatrixParameter> m_MatrixParams;
|
||||
public List<VectorParameter> m_VectorParams;
|
||||
public List<StructParameter> m_StructParams;
|
||||
public int m_Size;
|
||||
|
||||
public ConstantBuffer(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
|
||||
int numMatrixParams = reader.ReadInt32();
|
||||
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
|
||||
for (int i = 0; i < numMatrixParams; i++)
|
||||
{
|
||||
m_MatrixParams.Add(new MatrixParameter(reader));
|
||||
}
|
||||
|
||||
int numVectorParams = reader.ReadInt32();
|
||||
m_VectorParams = new List<VectorParameter>(numVectorParams);
|
||||
for (int i = 0; i < numVectorParams; i++)
|
||||
{
|
||||
m_VectorParams.Add(new VectorParameter(reader));
|
||||
}
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
{
|
||||
int numStructParams = reader.ReadInt32();
|
||||
m_StructParams = new List<StructParameter>(numStructParams);
|
||||
for (int i = 0; i < numStructParams; i++)
|
||||
{
|
||||
m_StructParams.Add(new StructParameter(reader));
|
||||
}
|
||||
}
|
||||
m_Size = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class UAVParameter
|
||||
{
|
||||
public int m_NameIndex;
|
||||
public int m_Index;
|
||||
public int m_OriginalIndex;
|
||||
|
||||
public UAVParameter(BinaryReader reader)
|
||||
{
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
m_OriginalIndex = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ShaderGpuProgramType
|
||||
{
|
||||
kShaderGpuProgramUnknown = 0,
|
||||
kShaderGpuProgramGLLegacy = 1,
|
||||
kShaderGpuProgramGLES31AEP = 2,
|
||||
kShaderGpuProgramGLES31 = 3,
|
||||
kShaderGpuProgramGLES3 = 4,
|
||||
kShaderGpuProgramGLES = 5,
|
||||
kShaderGpuProgramGLCore32 = 6,
|
||||
kShaderGpuProgramGLCore41 = 7,
|
||||
kShaderGpuProgramGLCore43 = 8,
|
||||
kShaderGpuProgramDX9VertexSM20 = 9,
|
||||
kShaderGpuProgramDX9VertexSM30 = 10,
|
||||
kShaderGpuProgramDX9PixelSM20 = 11,
|
||||
kShaderGpuProgramDX9PixelSM30 = 12,
|
||||
kShaderGpuProgramDX10Level9Vertex = 13,
|
||||
kShaderGpuProgramDX10Level9Pixel = 14,
|
||||
kShaderGpuProgramDX11VertexSM40 = 15,
|
||||
kShaderGpuProgramDX11VertexSM50 = 16,
|
||||
kShaderGpuProgramDX11PixelSM40 = 17,
|
||||
kShaderGpuProgramDX11PixelSM50 = 18,
|
||||
kShaderGpuProgramDX11GeometrySM40 = 19,
|
||||
kShaderGpuProgramDX11GeometrySM50 = 20,
|
||||
kShaderGpuProgramDX11HullSM50 = 21,
|
||||
kShaderGpuProgramDX11DomainSM50 = 22,
|
||||
kShaderGpuProgramMetalVS = 23,
|
||||
kShaderGpuProgramMetalFS = 24,
|
||||
kShaderGpuProgramSPIRV = 25,
|
||||
kShaderGpuProgramConsole = 26,
|
||||
};
|
||||
|
||||
public class SerializedSubProgram
|
||||
{
|
||||
public uint m_BlobIndex;
|
||||
public ParserBindChannels m_Channels;
|
||||
public List<ushort> m_KeywordIndices;
|
||||
public sbyte m_ShaderHardwareTier;
|
||||
public ShaderGpuProgramType m_GpuProgramType;
|
||||
public List<VectorParameter> m_VectorParams;
|
||||
public List<MatrixParameter> m_MatrixParams;
|
||||
public List<TextureParameter> m_TextureParams;
|
||||
public List<BufferBinding> m_BufferParams;
|
||||
public List<ConstantBuffer> m_ConstantBuffers;
|
||||
public List<BufferBinding> m_ConstantBufferBindings;
|
||||
public List<UAVParameter> m_UAVParams;
|
||||
public List<SamplerParameter> m_Samplers;
|
||||
|
||||
public SerializedSubProgram(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
m_BlobIndex = reader.ReadUInt32();
|
||||
m_Channels = new ParserBindChannels(reader);
|
||||
|
||||
int numIndices = reader.ReadInt32();
|
||||
m_KeywordIndices = new List<ushort>(numIndices);
|
||||
for (int i = 0; i < numIndices; i++)
|
||||
{
|
||||
m_KeywordIndices.Add(reader.ReadUInt16());
|
||||
}
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
{
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
m_ShaderHardwareTier = reader.ReadSByte();
|
||||
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
||||
reader.AlignStream(4);
|
||||
|
||||
int numVectorParams = reader.ReadInt32();
|
||||
m_VectorParams = new List<VectorParameter>(numVectorParams);
|
||||
for (int i = 0; i < numVectorParams; i++)
|
||||
{
|
||||
m_VectorParams.Add(new VectorParameter(reader));
|
||||
}
|
||||
|
||||
int numMatrixParams = reader.ReadInt32();
|
||||
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
|
||||
for (int i = 0; i < numMatrixParams; i++)
|
||||
{
|
||||
m_MatrixParams.Add(new MatrixParameter(reader));
|
||||
}
|
||||
|
||||
int numTextureParams = reader.ReadInt32();
|
||||
m_TextureParams = new List<TextureParameter>(numTextureParams);
|
||||
for (int i = 0; i < numTextureParams; i++)
|
||||
{
|
||||
m_TextureParams.Add(new TextureParameter(reader));
|
||||
}
|
||||
|
||||
int numBufferParams = reader.ReadInt32();
|
||||
m_BufferParams = new List<BufferBinding>(numBufferParams);
|
||||
for (int i = 0; i < numBufferParams; i++)
|
||||
{
|
||||
m_BufferParams.Add(new BufferBinding(reader));
|
||||
}
|
||||
|
||||
int numConstantBuffers = reader.ReadInt32();
|
||||
m_ConstantBuffers = new List<ConstantBuffer>(numConstantBuffers);
|
||||
for (int i = 0; i < numConstantBuffers; i++)
|
||||
{
|
||||
m_ConstantBuffers.Add(new ConstantBuffer(reader));
|
||||
}
|
||||
|
||||
int numConstantBufferBindings = reader.ReadInt32();
|
||||
m_ConstantBufferBindings = new List<BufferBinding>(numConstantBufferBindings);
|
||||
for (int i = 0; i < numConstantBufferBindings; i++)
|
||||
{
|
||||
m_ConstantBufferBindings.Add(new BufferBinding(reader));
|
||||
}
|
||||
|
||||
int numUAVParams = reader.ReadInt32();
|
||||
m_UAVParams = new List<UAVParameter>(numUAVParams);
|
||||
for (int i = 0; i < numUAVParams; i++)
|
||||
{
|
||||
m_UAVParams.Add(new UAVParameter(reader));
|
||||
}
|
||||
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
{
|
||||
int numSamplers = reader.ReadInt32();
|
||||
m_Samplers = new List<SamplerParameter>(numSamplers);
|
||||
for (int i = 0; i < numSamplers; i++)
|
||||
{
|
||||
m_Samplers.Add(new SamplerParameter(reader));
|
||||
}
|
||||
}
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
var m_ShaderRequirements = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedProgram
|
||||
{
|
||||
public List<SerializedSubProgram> m_SubPrograms;
|
||||
|
||||
public SerializedProgram(ObjectReader reader)
|
||||
{
|
||||
int numSubPrograms = reader.ReadInt32();
|
||||
m_SubPrograms = new List<SerializedSubProgram>(numSubPrograms);
|
||||
for (int i = 0; i < numSubPrograms; i++)
|
||||
{
|
||||
m_SubPrograms.Add(new SerializedSubProgram(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum PassType
|
||||
{
|
||||
kPassTypeNormal = 0,
|
||||
kPassTypeUse = 1,
|
||||
kPassTypeGrab = 2
|
||||
};
|
||||
|
||||
public class SerializedPass
|
||||
{
|
||||
public List<KeyValuePair<string, int>> m_NameIndices;
|
||||
public PassType m_Type;
|
||||
public SerializedShaderState m_State;
|
||||
public uint m_ProgramMask;
|
||||
public SerializedProgram progVertex;
|
||||
public SerializedProgram progFragment;
|
||||
public SerializedProgram progGeometry;
|
||||
public SerializedProgram progHull;
|
||||
public SerializedProgram progDomain;
|
||||
public bool m_HasInstancingVariant;
|
||||
public string m_UseName;
|
||||
public string m_Name;
|
||||
public string m_TextureName;
|
||||
public SerializedTagMap m_Tags;
|
||||
|
||||
public SerializedPass(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
int numIndices = reader.ReadInt32();
|
||||
m_NameIndices = new List<KeyValuePair<string, int>>(numIndices);
|
||||
for (int i = 0; i < numIndices; i++)
|
||||
{
|
||||
m_NameIndices.Add(new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32()));
|
||||
}
|
||||
|
||||
m_Type = (PassType)reader.ReadInt32();
|
||||
m_State = new SerializedShaderState(reader);
|
||||
m_ProgramMask = reader.ReadUInt32();
|
||||
progVertex = new SerializedProgram(reader);
|
||||
progFragment = new SerializedProgram(reader);
|
||||
progGeometry = new SerializedProgram(reader);
|
||||
progHull = new SerializedProgram(reader);
|
||||
progDomain = new SerializedProgram(reader);
|
||||
m_HasInstancingVariant = reader.ReadBoolean();
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
{
|
||||
var m_HasProceduralInstancingVariant = reader.ReadBoolean();
|
||||
}
|
||||
reader.AlignStream(4);
|
||||
m_UseName = reader.ReadAlignedString();
|
||||
m_Name = reader.ReadAlignedString();
|
||||
m_TextureName = reader.ReadAlignedString();
|
||||
m_Tags = new SerializedTagMap(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedTagMap
|
||||
{
|
||||
public List<KeyValuePair<string, string>> tags;
|
||||
|
||||
public SerializedTagMap(BinaryReader reader)
|
||||
{
|
||||
int numTags = reader.ReadInt32();
|
||||
tags = new List<KeyValuePair<string, string>>(numTags);
|
||||
for (int i = 0; i < numTags; i++)
|
||||
{
|
||||
tags.Add(new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedSubShader
|
||||
{
|
||||
public List<SerializedPass> m_Passes;
|
||||
public SerializedTagMap m_Tags;
|
||||
public int m_LOD;
|
||||
|
||||
public SerializedSubShader(ObjectReader reader)
|
||||
{
|
||||
int numPasses = reader.ReadInt32();
|
||||
m_Passes = new List<SerializedPass>(numPasses);
|
||||
for (int i = 0; i < numPasses; i++)
|
||||
{
|
||||
m_Passes.Add(new SerializedPass(reader));
|
||||
}
|
||||
|
||||
m_Tags = new SerializedTagMap(reader);
|
||||
m_LOD = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedShaderDependency
|
||||
{
|
||||
public string from;
|
||||
public string to;
|
||||
|
||||
public SerializedShaderDependency(BinaryReader reader)
|
||||
{
|
||||
from = reader.ReadAlignedString();
|
||||
to = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedShader
|
||||
{
|
||||
public SerializedProperties m_PropInfo;
|
||||
public List<SerializedSubShader> m_SubShaders;
|
||||
public string m_Name;
|
||||
public string m_CustomEditorName;
|
||||
public string m_FallbackName;
|
||||
public List<SerializedShaderDependency> m_Dependencies;
|
||||
public bool m_DisableNoSubshadersMessage;
|
||||
|
||||
public SerializedShader(ObjectReader reader)
|
||||
{
|
||||
m_PropInfo = new SerializedProperties(reader);
|
||||
|
||||
int numSubShaders = reader.ReadInt32();
|
||||
m_SubShaders = new List<SerializedSubShader>(numSubShaders);
|
||||
for (int i = 0; i < numSubShaders; i++)
|
||||
{
|
||||
m_SubShaders.Add(new SerializedSubShader(reader));
|
||||
}
|
||||
|
||||
m_Name = reader.ReadAlignedString();
|
||||
m_CustomEditorName = reader.ReadAlignedString();
|
||||
m_FallbackName = reader.ReadAlignedString();
|
||||
|
||||
int numDependencies = reader.ReadInt32();
|
||||
m_Dependencies = new List<SerializedShaderDependency>(numDependencies);
|
||||
for (int i = 0; i < numDependencies; i++)
|
||||
{
|
||||
m_Dependencies.Add(new SerializedShaderDependency(reader));
|
||||
}
|
||||
|
||||
m_DisableNoSubshadersMessage = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
|
||||
public class Shader : NamedObject
|
||||
{
|
||||
public byte[] m_Script;
|
||||
//5.3 - 5.4
|
||||
public uint decompressedSize;
|
||||
public byte[] m_SubProgramBlob;
|
||||
//5.5 and up
|
||||
public SerializedShader m_ParsedForm;
|
||||
public List<uint> platforms;
|
||||
public List<uint> offsets;
|
||||
public List<uint> compressedLengths;
|
||||
public List<uint> decompressedLengths;
|
||||
public byte[] compressedBlob;
|
||||
|
||||
public Shader(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up
|
||||
{
|
||||
m_ParsedForm = new SerializedShader(reader);
|
||||
int numPlatforms = reader.ReadInt32();
|
||||
platforms = new List<uint>(numPlatforms);
|
||||
for (int i = 0; i < numPlatforms; i++)
|
||||
{
|
||||
platforms.Add(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
int numOffsets = reader.ReadInt32();
|
||||
offsets = new List<uint>(numOffsets);
|
||||
for (int i = 0; i < numOffsets; i++)
|
||||
{
|
||||
offsets.Add(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
int numCompressedLengths = reader.ReadInt32();
|
||||
compressedLengths = new List<uint>(numCompressedLengths);
|
||||
for (int i = 0; i < numCompressedLengths; i++)
|
||||
{
|
||||
compressedLengths.Add(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
int numDecompressedLengths = reader.ReadInt32();
|
||||
decompressedLengths = new List<uint>(numDecompressedLengths);
|
||||
for (int i = 0; i < numDecompressedLengths; i++)
|
||||
{
|
||||
decompressedLengths.Add(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
compressedBlob = reader.ReadBytes(reader.ReadInt32());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Script = reader.ReadBytes(reader.ReadInt32());
|
||||
reader.AlignStream(4);
|
||||
var m_PathName = reader.ReadAlignedString();
|
||||
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
|
||||
{
|
||||
decompressedSize = reader.ReadUInt32();
|
||||
m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
AssetStudio/Classes/SkinnedMeshRenderer.cs
Normal file
53
AssetStudio/Classes/SkinnedMeshRenderer.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class SkinnedMeshRenderer : Renderer
|
||||
{
|
||||
public PPtr m_Mesh;
|
||||
public PPtr[] m_Bones;
|
||||
public List<float> m_BlendShapeWeights;
|
||||
|
||||
public SkinnedMeshRenderer(ObjectReader reader) : base(reader)
|
||||
{
|
||||
int m_Quality = reader.ReadInt32();
|
||||
var m_UpdateWhenOffscreen = reader.ReadBoolean();
|
||||
var m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below
|
||||
reader.AlignStream(4);
|
||||
|
||||
if (version[0] == 2 && version[1] < 6)//2.6 down
|
||||
{
|
||||
var m_DisableAnimationWhenOffscreen = reader.ReadPPtr();
|
||||
}
|
||||
|
||||
m_Mesh = reader.ReadPPtr();
|
||||
|
||||
m_Bones = new PPtr[reader.ReadInt32()];
|
||||
for (int b = 0; b < m_Bones.Length; b++)
|
||||
{
|
||||
m_Bones[b] = reader.ReadPPtr();
|
||||
}
|
||||
|
||||
if (version[0] < 3)
|
||||
{
|
||||
int m_BindPose = reader.ReadInt32();
|
||||
reader.Position += m_BindPose * 16 * 4;//Matrix4x4f
|
||||
}
|
||||
else
|
||||
{
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3))//4.3 and up
|
||||
{
|
||||
int numBSWeights = reader.ReadInt32();
|
||||
m_BlendShapeWeights = new List<float>(numBSWeights);
|
||||
for (int i = 0; i < numBSWeights; i++)
|
||||
{
|
||||
m_BlendShapeWeights.Add(reader.ReadSingle());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
215
AssetStudio/Classes/Sprite.cs
Normal file
215
AssetStudio/Classes/Sprite.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SharpDX;
|
||||
using RectangleF = System.Drawing.RectangleF;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum SpritePackingRotation
|
||||
{
|
||||
kSPRNone = 0,
|
||||
kSPRFlipHorizontal = 1,
|
||||
kSPRFlipVertical = 2,
|
||||
kSPRRotate180 = 3,
|
||||
kSPRRotate90 = 4
|
||||
};
|
||||
|
||||
public enum SpritePackingMode
|
||||
{
|
||||
kSPMTight = 0,
|
||||
kSPMRectangle
|
||||
};
|
||||
|
||||
public class SpriteSettings
|
||||
{
|
||||
public uint settingsRaw;
|
||||
|
||||
public uint packed;
|
||||
public SpritePackingMode packingMode;
|
||||
public SpritePackingRotation packingRotation;
|
||||
|
||||
public SpriteSettings(ObjectReader reader)
|
||||
{
|
||||
settingsRaw = reader.ReadUInt32();
|
||||
|
||||
packed = settingsRaw & 1; //1
|
||||
packingMode = (SpritePackingMode)((settingsRaw >> 1) & 1); //1
|
||||
packingRotation = (SpritePackingRotation)((settingsRaw >> 2) & 0xf); //4
|
||||
|
||||
//meshType = (settingsRaw >> 6) & 1; //1
|
||||
//reserved
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Sprite : NamedObject
|
||||
{
|
||||
public RectangleF m_Rect;
|
||||
public float m_PixelsToUnits;
|
||||
public Vector2 m_Pivot;
|
||||
public Tuple<Guid, long> m_RenderDataKey;
|
||||
public PPtr texture;
|
||||
public PPtr m_SpriteAtlas;
|
||||
public RectangleF textureRect;
|
||||
public SpriteSettings settingsRaw;
|
||||
public PointF[][] m_PhysicsShape; //Vector2[][]
|
||||
|
||||
public Sprite(ObjectReader reader) : base(reader)
|
||||
{
|
||||
//Rectf m_Rect
|
||||
m_Rect = reader.ReadRectangleF();
|
||||
//Vector2f m_Offset
|
||||
reader.Position += 8;
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
{
|
||||
//Vector4f m_Border
|
||||
reader.Position += 16;
|
||||
}
|
||||
|
||||
m_PixelsToUnits = reader.ReadSingle();
|
||||
if (version[0] > 5
|
||||
|| (version[0] == 5 && version[1] > 4)
|
||||
|| (version[0] == 5 && version[1] == 4 && version[2] >= 2)) //5.4.2 and up
|
||||
{
|
||||
//Vector2f m_Pivot
|
||||
m_Pivot = reader.ReadVector2();
|
||||
}
|
||||
|
||||
var m_Extrude = reader.ReadUInt32();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
|
||||
{
|
||||
var m_IsPolygon = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
{
|
||||
//pair m_RenderDataKey
|
||||
var first = new Guid(reader.ReadBytes(16));
|
||||
var second = reader.ReadInt64();
|
||||
m_RenderDataKey = new Tuple<Guid, long>(first, second);
|
||||
//vector m_AtlasTags
|
||||
var size = reader.ReadInt32();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
var data = reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
//PPtr<SpriteAtlas> m_SpriteAtlas
|
||||
m_SpriteAtlas = reader.ReadPPtr();
|
||||
}
|
||||
|
||||
//SpriteRenderData m_RD
|
||||
// PPtr<Texture2D> texture
|
||||
texture = reader.ReadPPtr();
|
||||
// PPtr<Texture2D> alphaTexture
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
|
||||
{
|
||||
var alphaTexture = reader.ReadPPtr();
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
{
|
||||
// vector m_SubMeshes
|
||||
var size = reader.ReadInt32();
|
||||
// SubMesh data
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
{
|
||||
reader.Position += 48 * size;
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Position += 44 * size;
|
||||
}
|
||||
|
||||
// vector m_IndexBuffer
|
||||
size = reader.ReadInt32();
|
||||
reader.Position += size; //UInt8 data
|
||||
reader.AlignStream(4);
|
||||
// VertexData m_VertexData
|
||||
if (version[0] < 2018)//2018 down
|
||||
{
|
||||
var m_CurrentChannels = reader.ReadInt32();
|
||||
}
|
||||
var m_VertexCount = reader.ReadUInt32();
|
||||
// vector m_Channels
|
||||
size = reader.ReadInt32();
|
||||
reader.Position += size * 4; //ChannelInfo data
|
||||
// TypelessData m_DataSize
|
||||
size = reader.ReadInt32();
|
||||
reader.Position += size; //UInt8 data
|
||||
reader.AlignStream(4);
|
||||
|
||||
if (version[0] >= 2018)//2018 and up
|
||||
{
|
||||
// vector m_Bindpose
|
||||
// Matrix4x4f data
|
||||
size = reader.ReadInt32();
|
||||
reader.Position += size * 64;
|
||||
if (version[0] == 2018 && version[1] < 2) //2018.2 down
|
||||
{
|
||||
// vector m_SourceSkin
|
||||
// BoneWeights4 data
|
||||
size = reader.ReadInt32();
|
||||
reader.Position += size * 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// vector vertices
|
||||
var size = reader.ReadInt32();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
//SpriteVertex data
|
||||
reader.Position += 12; //Vector3f pos
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down
|
||||
reader.Position += 8; //Vector2f uv
|
||||
}
|
||||
|
||||
// vector indices
|
||||
size = reader.ReadInt32();
|
||||
reader.Position += 2 * size; //UInt16 data
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
|
||||
// Rectf textureRect
|
||||
textureRect = reader.ReadRectangleF();
|
||||
// Vector2f textureRectOffset
|
||||
reader.Position += 8;
|
||||
// Vector2f atlasRectOffset - 5.6 and up
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
{
|
||||
reader.Position += 8;
|
||||
}
|
||||
// unsigned int settingsRaw
|
||||
settingsRaw = new SpriteSettings(reader);
|
||||
// Vector4f uvTransform - 4.5 and up
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
{
|
||||
reader.Position += 16;
|
||||
}
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
{
|
||||
// float downscaleMultiplier - 2017 and up
|
||||
reader.Position += 4;
|
||||
//vector m_PhysicsShape - 2017 and up
|
||||
var m_PhysicsShape_size = reader.ReadInt32();
|
||||
m_PhysicsShape = new PointF[m_PhysicsShape_size][];
|
||||
for (int i = 0; i < m_PhysicsShape_size; i++)
|
||||
{
|
||||
var data_size = reader.ReadInt32();
|
||||
//Vector2f
|
||||
m_PhysicsShape[i] = new PointF[data_size];
|
||||
for (int j = 0; j < data_size; j++)
|
||||
{
|
||||
m_PhysicsShape[i][j] = new PointF(reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
}
|
||||
}
|
||||
//vector m_Bones 2018 and up
|
||||
}
|
||||
}
|
||||
}
|
||||
69
AssetStudio/Classes/SpriteAtlas.cs
Normal file
69
AssetStudio/Classes/SpriteAtlas.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class SpriteAtlasData
|
||||
{
|
||||
public PPtr texture;
|
||||
public PPtr alphaTexture;
|
||||
public System.Drawing.RectangleF textureRect;
|
||||
public Vector2 textureRectOffset;
|
||||
public Vector2 atlasRectOffset;
|
||||
public Vector4 uvTransform;
|
||||
public float downscaleMultiplier;
|
||||
public SpriteSettings settingsRaw;
|
||||
|
||||
public SpriteAtlasData(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
texture = reader.ReadPPtr();
|
||||
alphaTexture = reader.ReadPPtr();
|
||||
textureRect = reader.ReadRectangleF();
|
||||
textureRectOffset = reader.ReadVector2();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
atlasRectOffset = reader.ReadVector2();
|
||||
}
|
||||
uvTransform = reader.ReadVector4();
|
||||
downscaleMultiplier = reader.ReadSingle();
|
||||
settingsRaw = new SpriteSettings(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SpriteAtlas : NamedObject
|
||||
{
|
||||
public Dictionary<Tuple<Guid, long>, SpriteAtlasData> m_RenderDataMap;
|
||||
|
||||
public SpriteAtlas(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_PackedSpritesSize = reader.ReadInt32();
|
||||
for (int i = 0; i < m_PackedSpritesSize; i++)
|
||||
{
|
||||
reader.ReadPPtr(); //PPtr<Sprite> data
|
||||
}
|
||||
|
||||
var m_PackedSpriteNamesToIndexSize = reader.ReadInt32();
|
||||
for (int i = 0; i < m_PackedSpriteNamesToIndexSize; i++)
|
||||
{
|
||||
reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
var m_RenderDataMapSize = reader.ReadInt32();
|
||||
m_RenderDataMap = new Dictionary<Tuple<Guid, long>, SpriteAtlasData>(m_RenderDataMapSize);
|
||||
for (int i = 0; i < m_RenderDataMapSize; i++)
|
||||
{
|
||||
var first = new Guid(reader.ReadBytes(16));
|
||||
var second = reader.ReadInt64();
|
||||
var value = new SpriteAtlasData(reader);
|
||||
m_RenderDataMap.Add(new Tuple<Guid, long>(first, second), value);
|
||||
}
|
||||
//string m_Tag
|
||||
//bool m_IsVariant
|
||||
}
|
||||
}
|
||||
}
|
||||
18
AssetStudio/Classes/TextAsset.cs
Normal file
18
AssetStudio/Classes/TextAsset.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class TextAsset : NamedObject
|
||||
{
|
||||
public byte[] m_Script;
|
||||
|
||||
public TextAsset(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Script = reader.ReadBytes(reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
20
AssetStudio/Classes/Texture.cs
Normal file
20
AssetStudio/Classes/Texture.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public abstract class Texture : NamedObject
|
||||
{
|
||||
protected Texture(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
{
|
||||
var m_ForcedFallbackFormat = reader.ReadInt32();
|
||||
var m_DownscaleFallback = reader.ReadBoolean();
|
||||
reader.AlignStream(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
178
AssetStudio/Classes/Texture2D.cs
Normal file
178
AssetStudio/Classes/Texture2D.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class Texture2D : Texture
|
||||
{
|
||||
public int m_Width;
|
||||
public int m_Height;
|
||||
public int m_CompleteImageSize;
|
||||
public TextureFormat m_TextureFormat;
|
||||
public bool m_MipMap;
|
||||
public int m_MipCount;
|
||||
public bool m_IsReadable;
|
||||
public bool m_ReadAllowed;
|
||||
public int m_ImageCount;
|
||||
public int m_TextureDimension;
|
||||
//m_TextureSettings
|
||||
public int m_FilterMode;
|
||||
public int m_Aniso;
|
||||
public float m_MipBias;
|
||||
public int m_WrapMode;
|
||||
public int m_LightmapFormat;
|
||||
public int m_ColorSpace;
|
||||
//image dataa
|
||||
public int image_data_size;
|
||||
public byte[] image_data;
|
||||
//m_StreamData
|
||||
public uint offset;
|
||||
public uint size;
|
||||
public string path;
|
||||
|
||||
public Texture2D(ObjectReader reader, bool readData) : base(reader)
|
||||
{
|
||||
m_Width = reader.ReadInt32();
|
||||
m_Height = reader.ReadInt32();
|
||||
m_CompleteImageSize = reader.ReadInt32();
|
||||
m_TextureFormat = (TextureFormat)reader.ReadInt32();
|
||||
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 2))
|
||||
{
|
||||
m_MipMap = reader.ReadBoolean();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MipCount = reader.ReadInt32();
|
||||
}
|
||||
|
||||
m_IsReadable = reader.ReadBoolean(); //2.6.0 and up
|
||||
m_ReadAllowed = reader.ReadBoolean(); //3.0.0 - 5.4
|
||||
//m_StreamingMipmaps 2018.2 and up
|
||||
reader.AlignStream(4);
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
{
|
||||
var m_StreamingMipmapsPriority = reader.ReadInt32();
|
||||
}
|
||||
else if (reader.HasStructMember("m_StreamingMipmapsPriority")) //will fix in some patch version bundle
|
||||
{
|
||||
var m_StreamingMipmapsPriority = reader.ReadInt32();
|
||||
}
|
||||
if (reader.HasStructMember("m_StreamingGroupID")) //What the hell is this?
|
||||
{
|
||||
var m_StreamingGroupID = reader.ReadUInt32();
|
||||
}
|
||||
m_ImageCount = reader.ReadInt32();
|
||||
m_TextureDimension = reader.ReadInt32();
|
||||
//m_TextureSettings
|
||||
m_FilterMode = reader.ReadInt32();
|
||||
m_Aniso = reader.ReadInt32();
|
||||
m_MipBias = reader.ReadSingle();
|
||||
if (version[0] >= 2017)//2017.x and up
|
||||
{
|
||||
int m_WrapU = reader.ReadInt32();
|
||||
int m_WrapV = reader.ReadInt32();
|
||||
int m_WrapW = reader.ReadInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_WrapMode = reader.ReadInt32();
|
||||
}
|
||||
if (version[0] >= 3)
|
||||
{
|
||||
m_LightmapFormat = reader.ReadInt32();
|
||||
if (version[0] >= 4 || version[1] >= 5)//3.5.0 and up
|
||||
{
|
||||
m_ColorSpace = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
image_data_size = reader.ReadInt32();
|
||||
|
||||
if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
|
||||
{
|
||||
offset = reader.ReadUInt32();
|
||||
size = reader.ReadUInt32();
|
||||
image_data_size = (int)size;
|
||||
path = reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
if (readData)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
image_data = ResourcesHelper.GetData(path, sourceFile, offset, image_data_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
image_data = reader.ReadBytes(image_data_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureFormat
|
||||
{
|
||||
Alpha8 = 1,
|
||||
ARGB4444,
|
||||
RGB24,
|
||||
RGBA32,
|
||||
ARGB32,
|
||||
RGB565 = 7,
|
||||
R16 = 9,
|
||||
DXT1,
|
||||
DXT5 = 12,
|
||||
RGBA4444,
|
||||
BGRA32,
|
||||
RHalf,
|
||||
RGHalf,
|
||||
RGBAHalf,
|
||||
RFloat,
|
||||
RGFloat,
|
||||
RGBAFloat,
|
||||
YUY2,
|
||||
RGB9e5Float,
|
||||
BC4 = 26,
|
||||
BC5,
|
||||
BC6H = 24,
|
||||
BC7,
|
||||
DXT1Crunched = 28,
|
||||
DXT5Crunched,
|
||||
PVRTC_RGB2,
|
||||
PVRTC_RGBA2,
|
||||
PVRTC_RGB4,
|
||||
PVRTC_RGBA4,
|
||||
ETC_RGB4,
|
||||
ATC_RGB4,
|
||||
ATC_RGBA8,
|
||||
EAC_R = 41,
|
||||
EAC_R_SIGNED,
|
||||
EAC_RG,
|
||||
EAC_RG_SIGNED,
|
||||
ETC2_RGB,
|
||||
ETC2_RGBA1,
|
||||
ETC2_RGBA8,
|
||||
ASTC_RGB_4x4,
|
||||
ASTC_RGB_5x5,
|
||||
ASTC_RGB_6x6,
|
||||
ASTC_RGB_8x8,
|
||||
ASTC_RGB_10x10,
|
||||
ASTC_RGB_12x12,
|
||||
ASTC_RGBA_4x4,
|
||||
ASTC_RGBA_5x5,
|
||||
ASTC_RGBA_6x6,
|
||||
ASTC_RGBA_8x8,
|
||||
ASTC_RGBA_10x10,
|
||||
ASTC_RGBA_12x12,
|
||||
ETC_RGB4_3DS,
|
||||
ETC_RGBA8_3DS,
|
||||
RG16,
|
||||
R8,
|
||||
ETC_RGB4Crunched,
|
||||
ETC2_RGBA8Crunched,
|
||||
}
|
||||
}
|
||||
31
AssetStudio/Classes/Transform.cs
Normal file
31
AssetStudio/Classes/Transform.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using SharpDX;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class Transform : Component
|
||||
{
|
||||
public float[] m_LocalRotation;
|
||||
public float[] m_LocalPosition;
|
||||
public float[] m_LocalScale;
|
||||
public List<PPtr> m_Children;
|
||||
public PPtr m_Father;
|
||||
|
||||
public Transform(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_LocalRotation = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
|
||||
m_LocalPosition = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
|
||||
m_LocalScale = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
|
||||
int m_ChildrenCount = reader.ReadInt32();
|
||||
m_Children = new List<PPtr>(m_ChildrenCount);
|
||||
for (int j = 0; j < m_ChildrenCount; j++)
|
||||
{
|
||||
m_Children.Add(reader.ReadPPtr());
|
||||
}
|
||||
m_Father = reader.ReadPPtr();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
AssetStudio/Classes/VideoClip.cs
Normal file
64
AssetStudio/Classes/VideoClip.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class VideoClip : NamedObject
|
||||
{
|
||||
public byte[] m_VideoData;
|
||||
public string m_OriginalPath;
|
||||
public string m_Source;
|
||||
public ulong m_Size;
|
||||
|
||||
public VideoClip(ObjectReader reader, bool readData) : base(reader)
|
||||
{
|
||||
m_OriginalPath = reader.ReadAlignedString();
|
||||
var m_ProxyWidth = reader.ReadUInt32();
|
||||
var m_ProxyHeight = reader.ReadUInt32();
|
||||
var Width = reader.ReadUInt32();
|
||||
var Height = reader.ReadUInt32();
|
||||
if (version[0] >= 2017)//2017.x and up
|
||||
{
|
||||
var m_PixelAspecRatioNum = reader.ReadUInt32();
|
||||
var m_PixelAspecRatioDen = reader.ReadUInt32();
|
||||
}
|
||||
var m_FrameRate = reader.ReadDouble();
|
||||
var m_FrameCount = reader.ReadUInt64();
|
||||
var m_Format = reader.ReadInt32();
|
||||
//m_AudioChannelCount
|
||||
var size = reader.ReadInt32();
|
||||
reader.Position += size * 2;
|
||||
reader.AlignStream(4);
|
||||
//m_AudioSampleRate
|
||||
size = reader.ReadInt32();
|
||||
reader.Position += size * 4;
|
||||
//m_AudioLanguage
|
||||
size = reader.ReadInt32();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
reader.ReadAlignedString();
|
||||
}
|
||||
//StreamedResource m_ExternalResources
|
||||
m_Source = reader.ReadAlignedString();
|
||||
var m_Offset = reader.ReadUInt64();
|
||||
m_Size = reader.ReadUInt64();
|
||||
var m_HasSplitAlpha = reader.ReadBoolean();
|
||||
|
||||
if (readData)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(m_Source))
|
||||
{
|
||||
m_VideoData = ResourcesHelper.GetData(m_Source, sourceFile, (long)m_Offset, (int)m_Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Size > 0)
|
||||
m_VideoData = reader.ReadBytes((int)m_Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
AssetStudio/CommonString.cs
Normal file
116
AssetStudio/CommonString.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class CommonString
|
||||
{
|
||||
public static readonly Dictionary<int, string> StringBuffer = new Dictionary<int, string>
|
||||
{
|
||||
{0, "AABB"},
|
||||
{5, "AnimationClip"},
|
||||
{19, "AnimationCurve"},
|
||||
{34, "AnimationState"},
|
||||
{49, "Array"},
|
||||
{55, "Base"},
|
||||
{60, "BitField"},
|
||||
{69, "bitset"},
|
||||
{76, "bool"},
|
||||
{81, "char"},
|
||||
{86, "ColorRGBA"},
|
||||
{96, "Component"},
|
||||
{106, "data"},
|
||||
{111, "deque"},
|
||||
{117, "double"},
|
||||
{124, "dynamic_array"},
|
||||
{138, "FastPropertyName"},
|
||||
{155, "first"},
|
||||
{161, "float"},
|
||||
{167, "Font"},
|
||||
{172, "GameObject"},
|
||||
{183, "Generic Mono"},
|
||||
{196, "GradientNEW"},
|
||||
{208, "GUID"},
|
||||
{213, "GUIStyle"},
|
||||
{222, "int"},
|
||||
{226, "list"},
|
||||
{231, "long long"},
|
||||
{241, "map"},
|
||||
{245, "Matrix4x4f"},
|
||||
{256, "MdFour"},
|
||||
{263, "MonoBehaviour"},
|
||||
{277, "MonoScript"},
|
||||
{288, "m_ByteSize"},
|
||||
{299, "m_Curve"},
|
||||
{307, "m_EditorClassIdentifier"},
|
||||
{331, "m_EditorHideFlags"},
|
||||
{349, "m_Enabled"},
|
||||
{359, "m_ExtensionPtr"},
|
||||
{374, "m_GameObject"},
|
||||
{387, "m_Index"},
|
||||
{395, "m_IsArray"},
|
||||
{405, "m_IsStatic"},
|
||||
{416, "m_MetaFlag"},
|
||||
{427, "m_Name"},
|
||||
{434, "m_ObjectHideFlags"},
|
||||
{452, "m_PrefabInternal"},
|
||||
{469, "m_PrefabParentObject"},
|
||||
{490, "m_Script"},
|
||||
{499, "m_StaticEditorFlags"},
|
||||
{519, "m_Type"},
|
||||
{526, "m_Version"},
|
||||
{536, "Object"},
|
||||
{543, "pair"},
|
||||
{548, "PPtr<Component>"},
|
||||
{564, "PPtr<GameObject>"},
|
||||
{581, "PPtr<Material>"},
|
||||
{596, "PPtr<MonoBehaviour>"},
|
||||
{616, "PPtr<MonoScript>"},
|
||||
{633, "PPtr<Object>"},
|
||||
{646, "PPtr<Prefab>"},
|
||||
{659, "PPtr<Sprite>"},
|
||||
{672, "PPtr<TextAsset>"},
|
||||
{688, "PPtr<Texture>"},
|
||||
{702, "PPtr<Texture2D>"},
|
||||
{718, "PPtr<Transform>"},
|
||||
{734, "Prefab"},
|
||||
{741, "Quaternionf"},
|
||||
{753, "Rectf"},
|
||||
{759, "RectInt"},
|
||||
{767, "RectOffset"},
|
||||
{778, "second"},
|
||||
{785, "set"},
|
||||
{789, "short"},
|
||||
{795, "size"},
|
||||
{800, "SInt16"},
|
||||
{807, "SInt32"},
|
||||
{814, "SInt64"},
|
||||
{821, "SInt8"},
|
||||
{827, "staticvector"},
|
||||
{840, "string"},
|
||||
{847, "TextAsset"},
|
||||
{857, "TextMesh"},
|
||||
{866, "Texture"},
|
||||
{874, "Texture2D"},
|
||||
{884, "Transform"},
|
||||
{894, "TypelessData"},
|
||||
{907, "UInt16"},
|
||||
{914, "UInt32"},
|
||||
{921, "UInt64"},
|
||||
{928, "UInt8"},
|
||||
{934, "unsigned int"},
|
||||
{947, "unsigned long long"},
|
||||
{966, "unsigned short"},
|
||||
{981, "vector"},
|
||||
{988, "Vector2f"},
|
||||
{997, "Vector3f"},
|
||||
{1006, "Vector4f"},
|
||||
{1015, "m_ScriptingClassIdentifier"},
|
||||
{1042, "Gradient"},
|
||||
{1051, "Type*"},
|
||||
{1057, "int2_storage"},
|
||||
{1070, "int3_storage"},
|
||||
{1083, "BoundsInt"},
|
||||
{1092, "m_CorrespondingSourceObject"}
|
||||
};
|
||||
}
|
||||
}
|
||||
117
AssetStudio/EndianBinaryReader.cs
Normal file
117
AssetStudio/EndianBinaryReader.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum EndianType
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
|
||||
public class EndianBinaryReader : BinaryReader
|
||||
{
|
||||
public EndianType endian;
|
||||
|
||||
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
|
||||
{
|
||||
this.endian = endian;
|
||||
}
|
||||
|
||||
public long Position
|
||||
{
|
||||
get => BaseStream.Position;
|
||||
set => BaseStream.Position = value;
|
||||
}
|
||||
|
||||
public override short ReadInt16()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(2);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt16(buff, 0);
|
||||
}
|
||||
return base.ReadInt16();
|
||||
}
|
||||
|
||||
public override int ReadInt32()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt32(buff, 0);
|
||||
}
|
||||
return base.ReadInt32();
|
||||
}
|
||||
|
||||
public override long ReadInt64()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt64(buff, 0);
|
||||
}
|
||||
return base.ReadInt64();
|
||||
}
|
||||
|
||||
public override ushort ReadUInt16()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(2);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt16(buff, 0);
|
||||
}
|
||||
return base.ReadUInt16();
|
||||
}
|
||||
|
||||
public override uint ReadUInt32()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt32(buff, 0);
|
||||
}
|
||||
return base.ReadUInt32();
|
||||
}
|
||||
|
||||
public override ulong ReadUInt64()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt64(buff, 0);
|
||||
}
|
||||
return base.ReadUInt64();
|
||||
}
|
||||
|
||||
public override float ReadSingle()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToSingle(buff, 0);
|
||||
}
|
||||
return base.ReadSingle();
|
||||
}
|
||||
|
||||
public override double ReadDouble()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt64(buff, 0);
|
||||
}
|
||||
return base.ReadDouble();
|
||||
}
|
||||
}
|
||||
}
|
||||
103
AssetStudio/Extensions/BinaryReaderExtensions.cs
Normal file
103
AssetStudio/Extensions/BinaryReaderExtensions.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SharpDX;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class BinaryReaderExtensions
|
||||
{
|
||||
public static void AlignStream(this BinaryReader reader, int alignment)
|
||||
{
|
||||
var pos = reader.BaseStream.Position;
|
||||
var mod = pos % alignment;
|
||||
if (mod != 0)
|
||||
{
|
||||
reader.BaseStream.Position += alignment - mod;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReadAlignedString(this BinaryReader reader)
|
||||
{
|
||||
var length = reader.ReadInt32();
|
||||
if (length > 0 && length < (reader.BaseStream.Length - reader.BaseStream.Position))
|
||||
{
|
||||
var stringData = reader.ReadBytes(length);
|
||||
var result = Encoding.UTF8.GetString(stringData);
|
||||
reader.AlignStream(4);
|
||||
return result;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string ReadStringToNull(this BinaryReader reader)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
byte b;
|
||||
while (reader.BaseStream.Position != reader.BaseStream.Length && (b = reader.ReadByte()) != 0)
|
||||
bytes.Add(b);
|
||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
||||
}
|
||||
|
||||
public static Quaternion ReadQuaternion(this BinaryReader reader)
|
||||
{
|
||||
return new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
|
||||
public static Vector2 ReadVector2(this BinaryReader reader)
|
||||
{
|
||||
return new Vector2(reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
|
||||
public static Vector3 ReadVector3(this BinaryReader reader)
|
||||
{
|
||||
return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
|
||||
public static Vector4 ReadVector4(this BinaryReader reader)
|
||||
{
|
||||
return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
|
||||
public static System.Drawing.RectangleF ReadRectangleF(this BinaryReader reader)
|
||||
{
|
||||
return new System.Drawing.RectangleF(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
|
||||
private static T[] ReadArray<T>(Func<T> del, int length)
|
||||
{
|
||||
var array = new T[length];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = del();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static int[] ReadInt32Array(this BinaryReader reader, int length)
|
||||
{
|
||||
return ReadArray(reader.ReadInt32, length);
|
||||
}
|
||||
|
||||
public static uint[] ReadUInt32Array(this BinaryReader reader, int length)
|
||||
{
|
||||
return ReadArray(reader.ReadUInt32, length);
|
||||
}
|
||||
|
||||
public static float[] ReadSingleArray(this BinaryReader reader, int length)
|
||||
{
|
||||
return ReadArray(reader.ReadSingle, length);
|
||||
}
|
||||
|
||||
public static Vector2[] ReadVector2Array(this BinaryReader reader, int length)
|
||||
{
|
||||
return ReadArray(reader.ReadVector2, length);
|
||||
}
|
||||
|
||||
public static Vector4[] ReadVector4Array(this BinaryReader reader, int length)
|
||||
{
|
||||
return ReadArray(reader.ReadVector4, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
AssetStudio/Extensions/BinaryWriterExtensions.cs
Normal file
40
AssetStudio/Extensions/BinaryWriterExtensions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class BinaryWriterExtensions
|
||||
{
|
||||
private static void WriteArray<T>(Action<T> del, T[] array)
|
||||
{
|
||||
foreach (var item in array)
|
||||
{
|
||||
del(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Write(this BinaryWriter writer, uint[] array)
|
||||
{
|
||||
WriteArray(writer.Write, array);
|
||||
}
|
||||
|
||||
public static void AlignStream(this BinaryWriter writer, int alignment)
|
||||
{
|
||||
var pos = writer.BaseStream.Position;
|
||||
var mod = pos % alignment;
|
||||
if (mod != 0)
|
||||
{
|
||||
writer.Write(new byte[alignment - mod]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteAlignedString(this BinaryWriter writer, string str)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(str);
|
||||
writer.Write(bytes.Length);
|
||||
writer.Write(bytes);
|
||||
writer.AlignStream(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
AssetStudio/Extensions/StreamExtensions.cs
Normal file
24
AssetStudio/Extensions/StreamExtensions.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class StreamExtensions
|
||||
{
|
||||
private const int BufferSize = 81920;
|
||||
|
||||
public static void CopyTo(this Stream source, Stream destination, long size)
|
||||
{
|
||||
var buffer = new byte[BufferSize];
|
||||
for (var left = size; left > 0; left -= BufferSize)
|
||||
{
|
||||
int toRead = BufferSize < left ? BufferSize : (int)left;
|
||||
int read = source.Read(buffer, 0, toRead);
|
||||
destination.Write(buffer, 0, read);
|
||||
if (read != toRead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
AssetStudio/FileIdentifier.cs
Normal file
17
AssetStudio/FileIdentifier.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class FileIdentifier
|
||||
{
|
||||
public Guid guid;
|
||||
public int type; //enum { kNonAssetType = 0, kDeprecatedCachedAssetType = 1, kSerializedAssetType = 2, kMetaAssetType = 3 };
|
||||
public string pathName;
|
||||
|
||||
//custom
|
||||
public string fileName;
|
||||
}
|
||||
}
|
||||
104
AssetStudio/ImportHelper.cs
Normal file
104
AssetStudio/ImportHelper.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum FileType
|
||||
{
|
||||
AssetsFile,
|
||||
BundleFile,
|
||||
WebFile
|
||||
}
|
||||
|
||||
public static class ImportHelper
|
||||
{
|
||||
public static void MergeSplitAssets(string path, bool allDirectories = false)
|
||||
{
|
||||
var splitFiles = Directory.GetFiles(path, "*.split0", allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
|
||||
foreach (var splitFile in splitFiles)
|
||||
{
|
||||
var destFile = Path.GetFileNameWithoutExtension(splitFile);
|
||||
var destPath = Path.GetDirectoryName(splitFile) + "\\";
|
||||
var destFull = destPath + destFile;
|
||||
if (!File.Exists(destFull))
|
||||
{
|
||||
var splitParts = Directory.GetFiles(destPath, destFile + ".split*");
|
||||
using (var destStream = File.Create(destFull))
|
||||
{
|
||||
for (int i = 0; i < splitParts.Length; i++)
|
||||
{
|
||||
var splitPart = destFull + ".split" + i;
|
||||
using (var sourceStream = File.OpenRead(splitPart))
|
||||
{
|
||||
sourceStream.CopyTo(destStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] ProcessingSplitFiles(List<string> selectFile)
|
||||
{
|
||||
var splitFiles = selectFile.Where(x => x.Contains(".split"))
|
||||
.Select(x => Path.GetDirectoryName(x) + "\\" + Path.GetFileNameWithoutExtension(x))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
selectFile.RemoveAll(x => x.Contains(".split"));
|
||||
foreach (var file in splitFiles)
|
||||
{
|
||||
if (File.Exists(file))
|
||||
{
|
||||
selectFile.Add(file);
|
||||
}
|
||||
}
|
||||
return selectFile.Distinct().ToArray();
|
||||
}
|
||||
|
||||
public static FileType CheckFileType(Stream stream, out EndianBinaryReader reader)
|
||||
{
|
||||
reader = new EndianBinaryReader(stream);
|
||||
return CheckFileType(reader);
|
||||
}
|
||||
|
||||
public static FileType CheckFileType(string fileName, out EndianBinaryReader reader)
|
||||
{
|
||||
reader = new EndianBinaryReader(File.OpenRead(fileName));
|
||||
return CheckFileType(reader);
|
||||
}
|
||||
|
||||
private static FileType CheckFileType(EndianBinaryReader reader)
|
||||
{
|
||||
var signature = reader.ReadStringToNull();
|
||||
reader.Position = 0;
|
||||
switch (signature)
|
||||
{
|
||||
case "UnityWeb":
|
||||
case "UnityRaw":
|
||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
||||
case "UnityFS":
|
||||
return FileType.BundleFile;
|
||||
case "UnityWebData1.0":
|
||||
return FileType.WebFile;
|
||||
default:
|
||||
{
|
||||
var magic = reader.ReadBytes(2);
|
||||
reader.Position = 0;
|
||||
if (WebFile.gzipMagic.SequenceEqual(magic))
|
||||
{
|
||||
return FileType.WebFile;
|
||||
}
|
||||
reader.Position = 0x20;
|
||||
magic = reader.ReadBytes(6);
|
||||
reader.Position = 0;
|
||||
if (WebFile.brotliMagic.SequenceEqual(magic))
|
||||
{
|
||||
return FileType.WebFile;
|
||||
}
|
||||
return FileType.AssetsFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
AssetStudio/Libraries/OpenTK.GLControl.dll
Normal file
BIN
AssetStudio/Libraries/OpenTK.GLControl.dll
Normal file
Binary file not shown.
BIN
AssetStudio/Libraries/OpenTK.dll
Normal file
BIN
AssetStudio/Libraries/OpenTK.dll
Normal file
Binary file not shown.
BIN
AssetStudio/Libraries/SharpDX.D3DCompiler.dll
Normal file
BIN
AssetStudio/Libraries/SharpDX.D3DCompiler.dll
Normal file
Binary file not shown.
BIN
AssetStudio/Libraries/SharpDX.Mathematics.dll
Normal file
BIN
AssetStudio/Libraries/SharpDX.Mathematics.dll
Normal file
Binary file not shown.
BIN
AssetStudio/Libraries/SharpDX.dll
Normal file
BIN
AssetStudio/Libraries/SharpDX.dll
Normal file
Binary file not shown.
19
AssetStudio/Libraries/brotli_license.txt
Normal file
19
AssetStudio/Libraries/brotli_license.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
BIN
AssetStudio/Libraries/dnlib.dll
Normal file
BIN
AssetStudio/Libraries/dnlib.dll
Normal file
Binary file not shown.
BIN
AssetStudio/Libraries/x64/crunch.dll
Normal file
BIN
AssetStudio/Libraries/x64/crunch.dll
Normal file
Binary file not shown.
BIN
AssetStudio/Libraries/x64/crunchunity.dll
Normal file
BIN
AssetStudio/Libraries/x64/crunchunity.dll
Normal file
Binary file not shown.
BIN
AssetStudio/Libraries/x64/libfbxsdk.dll
Normal file
BIN
AssetStudio/Libraries/x64/libfbxsdk.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user