Compare commits
406 Commits
v0.6.4
...
v0.14.38.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eab789939d | ||
|
|
04266251aa | ||
|
|
c5f7ef6e91 | ||
|
|
4a81c461e8 | ||
|
|
b10d03d50d | ||
|
|
da98a0c5b8 | ||
|
|
76d17bacf5 | ||
|
|
6678ce082b | ||
|
|
07074b3deb | ||
|
|
df5d9f90d4 | ||
|
|
4f2d30552a | ||
|
|
d259c7a5cd | ||
|
|
c71ceb7ea6 | ||
|
|
85cf134a49 | ||
|
|
687b1d3a0d | ||
|
|
a30a0d0bc5 | ||
|
|
e1dc54d6d7 | ||
|
|
c4270e186d | ||
|
|
182a42ace2 | ||
|
|
06fbe69a97 | ||
|
|
a0bf4f9acd | ||
|
|
12568ba044 | ||
|
|
de95b02285 | ||
|
|
286edfe72c | ||
|
|
d717b223b7 | ||
|
|
9e195832ef | ||
|
|
c8d08b2793 | ||
|
|
2bcd9662be | ||
|
|
ea461ee3d2 | ||
|
|
fda821b441 | ||
|
|
5c193c761a | ||
|
|
14f47c6d30 | ||
|
|
e53eacef78 | ||
|
|
ada26db659 | ||
|
|
48ca96807f | ||
|
|
2018028853 | ||
|
|
6f138dcc05 | ||
|
|
69bcd2be67 | ||
|
|
45ad53b19a | ||
|
|
6230240ee3 | ||
|
|
73ec9f4bee | ||
|
|
f3a0bf505e | ||
|
|
290708876d | ||
|
|
5b96a29cca | ||
|
|
948e2c4d92 | ||
|
|
76da1c33ae | ||
|
|
72b84ee24d | ||
|
|
7b33d41172 | ||
|
|
c7043c1a83 | ||
|
|
d0baf26c61 | ||
|
|
60ac10b043 | ||
|
|
80dc24b487 | ||
|
|
9d32a9dd6a | ||
|
|
d96cc3c762 | ||
|
|
509df42730 | ||
|
|
4efa5b0507 | ||
|
|
cffe96b409 | ||
|
|
16dddc01e3 | ||
|
|
b5d2c2cadb | ||
|
|
1d2c0ab6cb | ||
|
|
c6b7e04c47 | ||
|
|
5704813b28 | ||
|
|
465c989e75 | ||
|
|
d335aaef9e | ||
|
|
495b48c783 | ||
|
|
05b55722fb | ||
|
|
de54257eef | ||
|
|
e62b6c3d77 | ||
|
|
dc05e5b5eb | ||
|
|
f377381e26 | ||
|
|
20f9fe493f | ||
|
|
0b462754a5 | ||
|
|
b1ea8dd346 | ||
|
|
4a46f897bd | ||
|
|
6a5ec80de7 | ||
|
|
4f2046d412 | ||
|
|
1cf59e8d67 | ||
|
|
e9e8390bbc | ||
|
|
738b084440 | ||
|
|
32cce894ac | ||
|
|
a6264b39d1 | ||
|
|
eb4981808b | ||
|
|
50c17c2ec4 | ||
|
|
e001dff3de | ||
|
|
3a0100ed37 | ||
|
|
58ab3116db | ||
|
|
6b93df41f2 | ||
|
|
b9cf7d5874 | ||
|
|
da4eb15d6b | ||
|
|
378840bc1b | ||
|
|
3441135b2f | ||
|
|
afcbba8182 | ||
|
|
cefdf08873 | ||
|
|
59be547a82 | ||
|
|
a2be5ebdac | ||
|
|
f76d3d8fcd | ||
|
|
edb6256fc9 | ||
|
|
8946a4fba5 | ||
|
|
87e1739208 | ||
|
|
10f4aaa39f | ||
|
|
957073b041 | ||
|
|
e1bb9a6cf0 | ||
|
|
558adb0b66 | ||
|
|
6a4979f999 | ||
|
|
9e76d94eea | ||
|
|
fa91820016 | ||
|
|
be091ecebb | ||
|
|
903be743ac | ||
|
|
c3c4697562 | ||
|
|
e6ed312de2 | ||
|
|
33461e068f | ||
|
|
7f13c90189 | ||
|
|
54ed3971a2 | ||
|
|
e602a5cf3b | ||
|
|
dec0a22ffe | ||
|
|
911272167a | ||
|
|
54d78d55a0 | ||
|
|
ff550b457f | ||
|
|
f449d7a8ab | ||
|
|
761579ab1a | ||
|
|
5cd4cf67cf | ||
|
|
fabfc77a52 | ||
|
|
f8ffaa0400 | ||
|
|
d156b5d947 | ||
|
|
d7551bdeb2 | ||
|
|
7d5e06bce4 | ||
|
|
0bc17f0ff5 | ||
|
|
9edc268cd4 | ||
|
|
356d5fa8a4 | ||
|
|
eb170d4f34 | ||
|
|
324c5ec7a2 | ||
|
|
ae155ca603 | ||
|
|
eb13585174 | ||
|
|
98c9eea58a | ||
|
|
067517740f | ||
|
|
3addb0e894 | ||
|
|
7452d4275e | ||
|
|
96ea522e83 | ||
|
|
ab24f049cf | ||
|
|
ec9184ba93 | ||
|
|
0a5b866a03 | ||
|
|
58d5a3fc37 | ||
|
|
19534ebb4d | ||
|
|
0a764c74d6 | ||
|
|
ab5f5fbd9d | ||
|
|
7dbc2ff95d | ||
|
|
bfaa207853 | ||
|
|
8c749e21e1 | ||
|
|
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 | ||
|
|
929781a380 | ||
|
|
4d85c7f665 | ||
|
|
7e67f354e4 | ||
|
|
0cd8d51526 | ||
|
|
6f2c4521b2 | ||
|
|
738e7d3785 | ||
|
|
fc44ba373b | ||
|
|
468976db58 | ||
|
|
647ce56f81 | ||
|
|
db92daedf0 | ||
|
|
6969412385 | ||
|
|
8da4c4623f | ||
|
|
50265c1d57 | ||
|
|
c00da37267 | ||
|
|
17d2140909 | ||
|
|
40153f6f19 | ||
|
|
e75b9858da | ||
|
|
1f69f476f9 | ||
|
|
b2ecc65885 | ||
|
|
682ef4552e | ||
|
|
96c7aaabb0 | ||
|
|
38f1f068d2 | ||
|
|
0359169802 | ||
|
|
a49d409619 | ||
|
|
7e6ef31875 | ||
|
|
5dd9f31398 | ||
|
|
120c3e235d | ||
|
|
3a6ebf7ce6 | ||
|
|
9d505c8900 | ||
|
|
d0486d855a | ||
|
|
7ddbf3ce3e | ||
|
|
4666b378b3 | ||
|
|
2a7d40616d | ||
|
|
96b8732d91 | ||
|
|
e19ecf4770 | ||
|
|
df45fa9b8e | ||
|
|
bd7a43f0dc | ||
|
|
01f1d7c14e | ||
|
|
cc74130ad4 | ||
|
|
dc8990115a | ||
|
|
1c777aa1a8 | ||
|
|
6d019e6e8a | ||
|
|
2d7fd68ff5 | ||
|
|
cdfc9cf2e6 | ||
|
|
6e3c808799 | ||
|
|
1ecf4c8c27 | ||
|
|
3dea2936d7 | ||
|
|
e4533b4ec3 | ||
|
|
9d87fead21 | ||
|
|
14bd7f9789 | ||
|
|
d02a4ea02e | ||
|
|
14829c5e1b | ||
|
|
ef29d220e0 | ||
|
|
14ec7c8259 | ||
|
|
9687f823fb | ||
|
|
bb36839774 | ||
|
|
b0114520a8 | ||
|
|
8a3af0bfba | ||
|
|
65a13e97c4 | ||
|
|
fe6b7760b0 | ||
|
|
b319e92b3e | ||
|
|
06b8fcea64 | ||
|
|
100238d232 | ||
|
|
df3e5b31cd | ||
|
|
a04c0d0223 | ||
|
|
d1ec1c29a4 | ||
|
|
a928660dd3 | ||
|
|
e37a04e05b | ||
|
|
2c721272dd | ||
|
|
6f3b438d92 | ||
|
|
f8e7303169 | ||
|
|
bd18bfb8ea | ||
|
|
86843f81da | ||
|
|
60cc81b2dd | ||
|
|
cfbcdecfe6 | ||
|
|
45b9b781b1 | ||
|
|
29068481f5 | ||
|
|
384dd2e4e3 | ||
|
|
b4bce77381 | ||
|
|
631f2e7027 | ||
|
|
2585be69f9 | ||
|
|
332e4cc6e2 | ||
|
|
16ed347a30 | ||
|
|
b580b293f3 | ||
|
|
66b9b46523 | ||
|
|
2357e55337 | ||
|
|
256eeb8f7c | ||
|
|
5688f03869 | ||
|
|
c2f7f0a92d | ||
|
|
0ad6e6a456 | ||
|
|
fff759fe72 | ||
|
|
7e7397ab7e | ||
|
|
86e30c5dc0 | ||
|
|
2e8ef2a403 | ||
|
|
7456f9b106 | ||
|
|
3b7b88be57 | ||
|
|
05fd0588e8 | ||
|
|
f60f7ac413 | ||
|
|
344f69fddc | ||
|
|
dc5691aefc | ||
|
|
797216fed4 | ||
|
|
4899d6d7d0 | ||
|
|
8637c31311 | ||
|
|
ac33fd5ab8 | ||
|
|
8ccfbcf66a | ||
|
|
2e84b08494 | ||
|
|
08bf84146b | ||
|
|
fbfdb789f5 | ||
|
|
dcde8902f1 |
172
.gitignore
vendored
172
.gitignore
vendored
@@ -1,7 +1,10 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
@@ -15,13 +18,22 @@
|
|||||||
[Dd]ebugPublic/
|
[Dd]ebugPublic/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
build/
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
bld/
|
bld/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
@@ -36,18 +48,28 @@ TestResult.xml
|
|||||||
[Rr]eleasePS/
|
[Rr]eleasePS/
|
||||||
dlldata.c
|
dlldata.c
|
||||||
|
|
||||||
# DNX
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
project.lock.json
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
*_i.c
|
*_i.c
|
||||||
*_p.c
|
*_p.c
|
||||||
*_i.h
|
*_h.h
|
||||||
*.ilk
|
*.ilk
|
||||||
*.meta
|
*.meta
|
||||||
*.obj
|
*.obj
|
||||||
|
*.iobj
|
||||||
*.pch
|
*.pch
|
||||||
*.pdb
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
*.pgc
|
*.pgc
|
||||||
*.pgd
|
*.pgd
|
||||||
*.rsp
|
*.rsp
|
||||||
@@ -57,6 +79,7 @@ artifacts/
|
|||||||
*.tlh
|
*.tlh
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tmp_proj
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
*.log
|
*.log
|
||||||
*.vspscc
|
*.vspscc
|
||||||
*.vssscc
|
*.vssscc
|
||||||
@@ -72,14 +95,21 @@ _Chutzpah*
|
|||||||
ipch/
|
ipch/
|
||||||
*.aps
|
*.aps
|
||||||
*.ncb
|
*.ncb
|
||||||
|
*.opendb
|
||||||
*.opensdf
|
*.opensdf
|
||||||
*.sdf
|
*.sdf
|
||||||
*.cachefile
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
# Visual Studio profiler
|
# Visual Studio profiler
|
||||||
*.psess
|
*.psess
|
||||||
*.vsp
|
*.vsp
|
||||||
*.vspx
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
# TFS 2012 Local Workspace
|
||||||
$tf/
|
$tf/
|
||||||
@@ -101,9 +131,18 @@ _TeamCity*
|
|||||||
# DotCover is a Code Coverage Tool
|
# DotCover is a Code Coverage Tool
|
||||||
*.dotCover
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
# MightyMoose
|
# MightyMoose
|
||||||
*.mm.*
|
*.mm.*
|
||||||
@@ -131,47 +170,68 @@ publish/
|
|||||||
# Publish Web Output
|
# Publish Web Output
|
||||||
*.[Pp]ublish.xml
|
*.[Pp]ublish.xml
|
||||||
*.azurePubxml
|
*.azurePubxml
|
||||||
## TODO: Comment the next line if you want to checkin your
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
## web deploy settings but do note that will include unencrypted
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
## passwords
|
*.pubxml
|
||||||
#*.pubxml
|
|
||||||
|
|
||||||
*.publishproj
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
**/packages/*
|
**/[Pp]ackages/*
|
||||||
# except build/, which is used as an MSBuild target.
|
# except build/, which is used as an MSBuild target.
|
||||||
!**/packages/build/
|
!**/[Pp]ackages/build/
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
#!**/packages/repositories.config
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
# Windows Azure Build Output
|
# Microsoft Azure Build Output
|
||||||
csx/
|
csx/
|
||||||
*.build.csdef
|
*.build.csdef
|
||||||
|
|
||||||
# Windows Store app package directory
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
AppPackages/
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
|
||||||
# Visual Studio cache files
|
# Visual Studio cache files
|
||||||
# files ending in .cache can be ignored
|
# files ending in .cache can be ignored
|
||||||
*.[Cc]ache
|
*.[Cc]ache
|
||||||
# but keep track of directories ending in .cache
|
# but keep track of directories ending in .cache
|
||||||
!*.[Cc]ache/
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
# Others
|
# Others
|
||||||
ClientBin/
|
ClientBin/
|
||||||
[Ss]tyle[Cc]op.*
|
|
||||||
~$*
|
~$*
|
||||||
*~
|
*~
|
||||||
*.dbmdl
|
*.dbmdl
|
||||||
*.dbproj.schemaview
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
*.pfx
|
*.pfx
|
||||||
*.publishsettings
|
*.publishsettings
|
||||||
node_modules/
|
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
# RIA/Silverlight projects
|
||||||
Generated_Code/
|
Generated_Code/
|
||||||
|
|
||||||
@@ -182,21 +242,30 @@ _UpgradeReport_Files/
|
|||||||
Backup*/
|
Backup*/
|
||||||
UpgradeLog*.XML
|
UpgradeLog*.XML
|
||||||
UpgradeLog*.htm
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
# SQL Server files
|
# SQL Server files
|
||||||
*.mdf
|
*.mdf
|
||||||
*.ldf
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
# Business Intelligence projects
|
# Business Intelligence projects
|
||||||
*.rdl.data
|
*.rdl.data
|
||||||
*.bim.layout
|
*.bim.layout
|
||||||
*.bim_*.settings
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- Backup*.rdl
|
||||||
|
|
||||||
# Microsoft Fakes
|
# Microsoft Fakes
|
||||||
FakesAssemblies/
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
# Node.js Tools for Visual Studio
|
||||||
.ntvs_analysis.dat
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
# Visual Studio 6 build log
|
||||||
*.plg
|
*.plg
|
||||||
@@ -204,7 +273,68 @@ FakesAssemblies/
|
|||||||
# Visual Studio 6 workspace options file
|
# Visual Studio 6 workspace options file
|
||||||
*.opt
|
*.opt
|
||||||
|
|
||||||
# LightSwitch generated files
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
GeneratedArtifacts/
|
*.vbw
|
||||||
_Pvt_Extensions/
|
|
||||||
ModelManifest.xml
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
71
AssetStudio.sln
Normal file
71
AssetStudio.sln
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.29920.165
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "AssetStudioFBX\AssetStudioFBX.vcxproj", "{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoder", "Texture2DDecoder\Texture2DDecoder.vcxproj", "{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{80AEC261-21EE-4E4F-A93B-7A744DC84888}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}"
|
||||||
|
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
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.Build.0 = Release|x64
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.Build.0 = Release|x64
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|x64
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|x86
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|x64
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {F8734F96-97B6-40CA-B791-6D5467F2F713}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace SevenZip
|
namespace SevenZip
|
||||||
{
|
{
|
||||||
class CRC
|
public class CRC
|
||||||
{
|
{
|
||||||
public static readonly uint[] Table;
|
public static readonly uint[] Table;
|
||||||
|
|
||||||
154
AssetStudio/AssetStudio.csproj
Normal file
154
AssetStudio/AssetStudio.csproj
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?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>{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>AssetStudio</RootNamespace>
|
||||||
|
<AssemblyName>AssetStudio</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</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>none</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<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="AssetsManager.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\PPtr.cs" />
|
||||||
|
<Compile Include="Classes\RectTransform.cs" />
|
||||||
|
<Compile Include="Classes\Renderer.cs" />
|
||||||
|
<Compile Include="Classes\RuntimeAnimatorController.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="Extensions\BinaryReaderExtensions.cs" />
|
||||||
|
<Compile Include="Extensions\BinaryWriterExtensions.cs" />
|
||||||
|
<Compile Include="Extensions\StreamExtensions.cs" />
|
||||||
|
<Compile Include="FileIdentifier.cs" />
|
||||||
|
<Compile Include="IImported.cs" />
|
||||||
|
<Compile Include="ILogger.cs" />
|
||||||
|
<Compile Include="ImportHelper.cs" />
|
||||||
|
<Compile Include="IProgress.cs" />
|
||||||
|
<Compile Include="LocalSerializedObjectIdentifier.cs" />
|
||||||
|
<Compile Include="Logger.cs" />
|
||||||
|
<Compile Include="Lz4DecoderStream.cs" />
|
||||||
|
<Compile Include="Math\Color.cs" />
|
||||||
|
<Compile Include="Math\Half.cs" />
|
||||||
|
<Compile Include="Math\HalfHelper.cs" />
|
||||||
|
<Compile Include="Math\Matrix4x4.cs" />
|
||||||
|
<Compile Include="Math\Quaternion.cs" />
|
||||||
|
<Compile Include="Math\Vector2.cs" />
|
||||||
|
<Compile Include="Math\Vector3.cs" />
|
||||||
|
<Compile Include="Math\Vector4.cs" />
|
||||||
|
<Compile Include="ObjectInfo.cs" />
|
||||||
|
<Compile Include="ObjectReader.cs" />
|
||||||
|
<Compile Include="Progress.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ResourceReader.cs" />
|
||||||
|
<Compile Include="SerializedFile.cs" />
|
||||||
|
<Compile Include="SerializedFileHeader.cs" />
|
||||||
|
<Compile Include="SerializedType.cs" />
|
||||||
|
<Compile Include="SevenZipHelper.cs" />
|
||||||
|
<Compile Include="StreamFile.cs" />
|
||||||
|
<Compile Include="TypeTreeHelper.cs" />
|
||||||
|
<Compile Include="TypeTreeNode.cs" />
|
||||||
|
<Compile Include="UType.cs" />
|
||||||
|
<Compile Include="WebFile.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
413
AssetStudio/AssetsManager.cs
Normal file
413
AssetStudio/AssetsManager.cs
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
using System;
|
||||||
|
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>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
private List<string> importFiles = new List<string>();
|
||||||
|
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public void LoadFiles(params 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
ReadAssets();
|
||||||
|
ProcessAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
Logger.Info($"Loading {fileName}");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var assetsFile = new SerializedFile(this, fullName, reader);
|
||||||
|
assetsFileList.Add(assetsFile);
|
||||||
|
assetsFileListHash.Add(assetsFile.fileName);
|
||||||
|
|
||||||
|
foreach (var sharedFile in assetsFile.m_Externals)
|
||||||
|
{
|
||||||
|
var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName;
|
||||||
|
var sharedFileName = sharedFile.fileName;
|
||||||
|
|
||||||
|
if (!importFilesHash.Contains(sharedFileName))
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
reader.Dispose();
|
||||||
|
//Logger.Warning($"Unable to load assets file {fileName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, string originalPath, string unityVersion = null)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(fullName);
|
||||||
|
if (!assetsFileListHash.Contains(fileName))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var assetsFile = new SerializedFile(this, fullName, reader);
|
||||||
|
assetsFile.originalPath = originalPath;
|
||||||
|
if (assetsFile.header.m_Version < 7)
|
||||||
|
{
|
||||||
|
assetsFile.SetVersion(unityVersion);
|
||||||
|
}
|
||||||
|
assetsFileList.Add(assetsFile);
|
||||||
|
assetsFileListHash.Add(assetsFile.fileName);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//Logger.Error($"Unable to load assets file {fileName} from {Path.GetFileName(originalPath)}");
|
||||||
|
resourceFileReaders.Add(fileName, reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(fullName);
|
||||||
|
Logger.Info("Loading " + fileName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bundleFile = new BundleFile(reader, fullName);
|
||||||
|
foreach (var file in bundleFile.fileList)
|
||||||
|
{
|
||||||
|
var subReader = new EndianBinaryReader(file.stream);
|
||||||
|
if (SerializedFile.IsSerializedFile(subReader))
|
||||||
|
{
|
||||||
|
var dummyPath = Path.GetDirectoryName(fullName) + Path.DirectorySeparatorChar + file.fileName;
|
||||||
|
LoadAssetsFromMemory(dummyPath, subReader, parentPath ?? fullName, bundleFile.m_Header.unityRevision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resourceFileReaders.Add(file.fileName, subReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
/*var str = $"Unable to load bundle file {fileName}";
|
||||||
|
if (parentPath != null)
|
||||||
|
{
|
||||||
|
str += $" from {Path.GetFileName(parentPath)}";
|
||||||
|
}
|
||||||
|
Logger.Error(str);*/
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
reader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadWebFile(string fullName, EndianBinaryReader reader)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(fullName);
|
||||||
|
Logger.Info("Loading " + fileName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var webFile = new WebFile(reader);
|
||||||
|
foreach (var file in webFile.fileList)
|
||||||
|
{
|
||||||
|
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
||||||
|
switch (CheckFileType(file.stream, out var fileReader))
|
||||||
|
{
|
||||||
|
case FileType.AssetsFile:
|
||||||
|
LoadAssetsFromMemory(dummyPath, fileReader, fullName);
|
||||||
|
break;
|
||||||
|
case FileType.BundleFile:
|
||||||
|
LoadBundleFile(dummyPath, fileReader, fullName);
|
||||||
|
break;
|
||||||
|
case FileType.WebFile:
|
||||||
|
LoadWebFile(dummyPath, fileReader);
|
||||||
|
break;
|
||||||
|
case FileType.ResourceFile:
|
||||||
|
resourceFileReaders.Add(file.fileName, fileReader);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//Logger.Error($"Unable to load web file {fileName}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
reader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
foreach (var assetsFile in assetsFileList)
|
||||||
|
{
|
||||||
|
assetsFile.Objects.Clear();
|
||||||
|
assetsFile.reader.Close();
|
||||||
|
}
|
||||||
|
assetsFileList.Clear();
|
||||||
|
|
||||||
|
foreach (var resourceFileReader in resourceFileReaders)
|
||||||
|
{
|
||||||
|
resourceFileReader.Value.Close();
|
||||||
|
}
|
||||||
|
resourceFileReaders.Clear();
|
||||||
|
|
||||||
|
assetsFileIndexCache.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadAssets()
|
||||||
|
{
|
||||||
|
Logger.Info("Read assets...");
|
||||||
|
|
||||||
|
var progressCount = assetsFileList.Sum(x => x.m_Objects.Count);
|
||||||
|
int i = 0;
|
||||||
|
Progress.Reset();
|
||||||
|
foreach (var assetsFile in assetsFileList)
|
||||||
|
{
|
||||||
|
foreach (var objectInfo in assetsFile.m_Objects)
|
||||||
|
{
|
||||||
|
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object obj;
|
||||||
|
switch (objectReader.type)
|
||||||
|
{
|
||||||
|
case ClassIDType.Animation:
|
||||||
|
obj = new Animation(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.AnimationClip:
|
||||||
|
obj = new AnimationClip(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Animator:
|
||||||
|
obj = new Animator(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.AnimatorController:
|
||||||
|
obj = new AnimatorController(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.AnimatorOverrideController:
|
||||||
|
obj = new AnimatorOverrideController(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.AssetBundle:
|
||||||
|
obj = new AssetBundle(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.AudioClip:
|
||||||
|
obj = new AudioClip(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Avatar:
|
||||||
|
obj = new Avatar(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Font:
|
||||||
|
obj = new Font(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.GameObject:
|
||||||
|
obj = new GameObject(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Material:
|
||||||
|
obj = new Material(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Mesh:
|
||||||
|
obj = new Mesh(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.MeshFilter:
|
||||||
|
obj = new MeshFilter(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.MeshRenderer:
|
||||||
|
obj = new MeshRenderer(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.MonoBehaviour:
|
||||||
|
obj = new MonoBehaviour(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.MonoScript:
|
||||||
|
obj = new MonoScript(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.MovieTexture:
|
||||||
|
obj = new MovieTexture(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.PlayerSettings:
|
||||||
|
obj = new PlayerSettings(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.RectTransform:
|
||||||
|
obj = new RectTransform(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Shader:
|
||||||
|
obj = new Shader(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.SkinnedMeshRenderer:
|
||||||
|
obj = new SkinnedMeshRenderer(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Sprite:
|
||||||
|
obj = new Sprite(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.SpriteAtlas:
|
||||||
|
obj = new SpriteAtlas(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.TextAsset:
|
||||||
|
obj = new TextAsset(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Texture2D:
|
||||||
|
obj = new Texture2D(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.Transform:
|
||||||
|
obj = new Transform(objectReader);
|
||||||
|
break;
|
||||||
|
case ClassIDType.VideoClip:
|
||||||
|
obj = new VideoClip(objectReader);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
obj = new Object(objectReader);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assetsFile.AddObject(obj);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
/*var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("Unable to load object")
|
||||||
|
.AppendLine($"Assets {assetsFile.fileName}")
|
||||||
|
.AppendLine($"Type {objectReader.type}")
|
||||||
|
.AppendLine($"PathID {objectInfo.m_PathID}")
|
||||||
|
.Append(e);
|
||||||
|
Logger.Error(sb.ToString());*/
|
||||||
|
}
|
||||||
|
|
||||||
|
Progress.Report(++i, progressCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessAssets()
|
||||||
|
{
|
||||||
|
Logger.Info("Process Assets...");
|
||||||
|
|
||||||
|
foreach (var assetsFile in assetsFileList)
|
||||||
|
{
|
||||||
|
foreach (var obj in assetsFile.Objects)
|
||||||
|
{
|
||||||
|
if (obj is GameObject m_GameObject)
|
||||||
|
{
|
||||||
|
foreach (var pptr in m_GameObject.m_Components)
|
||||||
|
{
|
||||||
|
if (pptr.TryGet(out var m_Component))
|
||||||
|
{
|
||||||
|
switch (m_Component)
|
||||||
|
{
|
||||||
|
case Transform m_Transform:
|
||||||
|
m_GameObject.m_Transform = m_Transform;
|
||||||
|
break;
|
||||||
|
case MeshRenderer m_MeshRenderer:
|
||||||
|
m_GameObject.m_MeshRenderer = m_MeshRenderer;
|
||||||
|
break;
|
||||||
|
case MeshFilter m_MeshFilter:
|
||||||
|
m_GameObject.m_MeshFilter = m_MeshFilter;
|
||||||
|
break;
|
||||||
|
case SkinnedMeshRenderer m_SkinnedMeshRenderer:
|
||||||
|
m_GameObject.m_SkinnedMeshRenderer = m_SkinnedMeshRenderer;
|
||||||
|
break;
|
||||||
|
case Animator m_Animator:
|
||||||
|
m_GameObject.m_Animator = m_Animator;
|
||||||
|
break;
|
||||||
|
case Animation m_Animation:
|
||||||
|
m_GameObject.m_Animation = m_Animation;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (obj is SpriteAtlas m_SpriteAtlas)
|
||||||
|
{
|
||||||
|
foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)
|
||||||
|
{
|
||||||
|
if (m_PackedSprite.TryGet(out var m_Sprite))
|
||||||
|
{
|
||||||
|
if (m_Sprite.m_SpriteAtlas.IsNull)
|
||||||
|
{
|
||||||
|
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
306
AssetStudio/BundleFile.cs
Normal file
306
AssetStudio/BundleFile.cs
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Lz4;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class BundleFile
|
||||||
|
{
|
||||||
|
public class Header
|
||||||
|
{
|
||||||
|
public string signature;
|
||||||
|
public uint version;
|
||||||
|
public string unityVersion;
|
||||||
|
public string unityRevision;
|
||||||
|
public long size;
|
||||||
|
public uint compressedBlocksInfoSize;
|
||||||
|
public uint uncompressedBlocksInfoSize;
|
||||||
|
public uint flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StorageBlock
|
||||||
|
{
|
||||||
|
public uint compressedSize;
|
||||||
|
public uint uncompressedSize;
|
||||||
|
public ushort flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Node
|
||||||
|
{
|
||||||
|
public long offset;
|
||||||
|
public long size;
|
||||||
|
public uint flags;
|
||||||
|
public string path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header m_Header;
|
||||||
|
private StorageBlock[] m_BlocksInfo;
|
||||||
|
private Node[] m_DirectoryInfo;
|
||||||
|
|
||||||
|
public StreamFile[] fileList;
|
||||||
|
|
||||||
|
public BundleFile(EndianBinaryReader reader, string path)
|
||||||
|
{
|
||||||
|
m_Header = new Header();
|
||||||
|
m_Header.signature = reader.ReadStringToNull();
|
||||||
|
switch (m_Header.signature)
|
||||||
|
{
|
||||||
|
case "UnityArchive":
|
||||||
|
break; //TODO
|
||||||
|
case "UnityWeb":
|
||||||
|
case "UnityRaw":
|
||||||
|
ReadHeaderAndBlocksInfo(reader);
|
||||||
|
using (var blocksStream = CreateBlocksStream(path))
|
||||||
|
{
|
||||||
|
ReadBlocksAndDirectory(reader, blocksStream);
|
||||||
|
ReadFiles(blocksStream, path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "UnityFS":
|
||||||
|
ReadHeader(reader);
|
||||||
|
ReadBlocksInfoAndDirectory(reader);
|
||||||
|
using (var blocksStream = CreateBlocksStream(path))
|
||||||
|
{
|
||||||
|
ReadBlocks(reader, blocksStream);
|
||||||
|
ReadFiles(blocksStream, path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
|
||||||
|
{
|
||||||
|
var isCompressed = m_Header.signature == "UnityWeb";
|
||||||
|
m_Header.version = reader.ReadUInt32();
|
||||||
|
m_Header.unityVersion = reader.ReadStringToNull();
|
||||||
|
m_Header.unityRevision = reader.ReadStringToNull();
|
||||||
|
if (m_Header.version >= 4)
|
||||||
|
{
|
||||||
|
var hash = reader.ReadBytes(16);
|
||||||
|
var crc = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
var minimumStreamedBytes = reader.ReadUInt32();
|
||||||
|
var headerSize = reader.ReadUInt32();
|
||||||
|
var numberOfLevelsToDownloadBeforeStreaming = reader.ReadUInt32();
|
||||||
|
var levelCount = reader.ReadInt32();
|
||||||
|
m_BlocksInfo = new StorageBlock[1];
|
||||||
|
for (int i = 0; i < levelCount; i++)
|
||||||
|
{
|
||||||
|
var storageBlock = new StorageBlock()
|
||||||
|
{
|
||||||
|
compressedSize = reader.ReadUInt32(),
|
||||||
|
uncompressedSize = reader.ReadUInt32(),
|
||||||
|
flags = (ushort)(isCompressed ? 1 : 0)
|
||||||
|
};
|
||||||
|
if (i == levelCount - 1)
|
||||||
|
{
|
||||||
|
m_BlocksInfo[0] = storageBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_Header.version >= 2)
|
||||||
|
{
|
||||||
|
var completeFileSize = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
if (m_Header.version >= 3)
|
||||||
|
{
|
||||||
|
var fileInfoHeaderSize = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
reader.Position = headerSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream CreateBlocksStream(string path)
|
||||||
|
{
|
||||||
|
Stream blocksStream;
|
||||||
|
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
|
||||||
|
if (uncompressedSizeSum >= int.MaxValue)
|
||||||
|
{
|
||||||
|
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
|
||||||
|
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
||||||
|
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blocksStream = new MemoryStream((int)uncompressedSizeSum);
|
||||||
|
}
|
||||||
|
return blocksStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
|
||||||
|
{
|
||||||
|
foreach (var blockInfo in m_BlocksInfo)
|
||||||
|
{
|
||||||
|
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
|
||||||
|
if (blockInfo.flags == 1)
|
||||||
|
{
|
||||||
|
using (var memoryStream = new MemoryStream(uncompressedBytes))
|
||||||
|
{
|
||||||
|
using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream))
|
||||||
|
{
|
||||||
|
uncompressedBytes = decompressStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blocksStream.Write(uncompressedBytes, 0, uncompressedBytes.Length);
|
||||||
|
}
|
||||||
|
blocksStream.Position = 0;
|
||||||
|
var blocksReader = new EndianBinaryReader(blocksStream);
|
||||||
|
var nodesCount = blocksReader.ReadInt32();
|
||||||
|
m_DirectoryInfo = new Node[nodesCount];
|
||||||
|
for (int i = 0; i < nodesCount; i++)
|
||||||
|
{
|
||||||
|
m_DirectoryInfo[i] = new Node
|
||||||
|
{
|
||||||
|
path = blocksReader.ReadStringToNull(),
|
||||||
|
offset = blocksReader.ReadUInt32(),
|
||||||
|
size = blocksReader.ReadUInt32()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadFiles(Stream blocksStream, string path)
|
||||||
|
{
|
||||||
|
fileList = new StreamFile[m_DirectoryInfo.Length];
|
||||||
|
for (int i = 0; i < m_DirectoryInfo.Length; i++)
|
||||||
|
{
|
||||||
|
var node = m_DirectoryInfo[i];
|
||||||
|
var file = new StreamFile();
|
||||||
|
fileList[i] = file;
|
||||||
|
file.fileName = Path.GetFileName(node.path);
|
||||||
|
if (node.size >= int.MaxValue)
|
||||||
|
{
|
||||||
|
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size);
|
||||||
|
file.stream = memoryMappedFile.CreateViewStream();*/
|
||||||
|
var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar;
|
||||||
|
Directory.CreateDirectory(extractPath);
|
||||||
|
file.stream = File.Create(extractPath + file.fileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file.stream = new MemoryStream((int)node.size);
|
||||||
|
}
|
||||||
|
blocksStream.Position = node.offset;
|
||||||
|
blocksStream.CopyTo(file.stream, node.size);
|
||||||
|
file.stream.Position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadHeader(EndianBinaryReader reader)
|
||||||
|
{
|
||||||
|
m_Header.version = reader.ReadUInt32();
|
||||||
|
m_Header.unityVersion = reader.ReadStringToNull();
|
||||||
|
m_Header.unityRevision = reader.ReadStringToNull();
|
||||||
|
m_Header.size = reader.ReadInt64();
|
||||||
|
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
|
||||||
|
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
|
||||||
|
m_Header.flags = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader)
|
||||||
|
{
|
||||||
|
byte[] blocksInfoBytes;
|
||||||
|
if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd
|
||||||
|
{
|
||||||
|
var position = reader.Position;
|
||||||
|
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
|
||||||
|
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||||
|
reader.Position = position;
|
||||||
|
}
|
||||||
|
else //0x40 kArchiveBlocksAndDirectoryInfoCombined
|
||||||
|
{
|
||||||
|
if (m_Header.version >= 7)
|
||||||
|
{
|
||||||
|
reader.AlignStream(16);
|
||||||
|
}
|
||||||
|
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||||
|
}
|
||||||
|
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
|
||||||
|
MemoryStream blocksInfoUncompresseddStream;
|
||||||
|
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
|
||||||
|
{
|
||||||
|
default: //None
|
||||||
|
{
|
||||||
|
blocksInfoUncompresseddStream = blocksInfoCompressedStream;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: //LZMA
|
||||||
|
{
|
||||||
|
blocksInfoUncompresseddStream = SevenZipHelper.StreamDecompress(blocksInfoCompressedStream);
|
||||||
|
blocksInfoCompressedStream.Close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: //LZ4
|
||||||
|
case 3: //LZ4HC
|
||||||
|
{
|
||||||
|
var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
|
||||||
|
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
|
||||||
|
{
|
||||||
|
decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length);
|
||||||
|
}
|
||||||
|
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
|
||||||
|
{
|
||||||
|
var uncompressedDataHash = blocksInfoReader.ReadBytes(16);
|
||||||
|
var blocksInfoCount = blocksInfoReader.ReadInt32();
|
||||||
|
m_BlocksInfo = new StorageBlock[blocksInfoCount];
|
||||||
|
for (int i = 0; i < blocksInfoCount; i++)
|
||||||
|
{
|
||||||
|
m_BlocksInfo[i] = new StorageBlock
|
||||||
|
{
|
||||||
|
uncompressedSize = blocksInfoReader.ReadUInt32(),
|
||||||
|
compressedSize = blocksInfoReader.ReadUInt32(),
|
||||||
|
flags = blocksInfoReader.ReadUInt16()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodesCount = blocksInfoReader.ReadInt32();
|
||||||
|
m_DirectoryInfo = new Node[nodesCount];
|
||||||
|
for (int i = 0; i < nodesCount; i++)
|
||||||
|
{
|
||||||
|
m_DirectoryInfo[i] = new Node
|
||||||
|
{
|
||||||
|
offset = blocksInfoReader.ReadInt64(),
|
||||||
|
size = blocksInfoReader.ReadInt64(),
|
||||||
|
flags = blocksInfoReader.ReadUInt32(),
|
||||||
|
path = blocksInfoReader.ReadStringToNull(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
|
||||||
|
{
|
||||||
|
foreach (var blockInfo in m_BlocksInfo)
|
||||||
|
{
|
||||||
|
switch (blockInfo.flags & 0x3F) //kStorageBlockCompressionTypeMask
|
||||||
|
{
|
||||||
|
default: //None
|
||||||
|
{
|
||||||
|
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: //LZMA
|
||||||
|
{
|
||||||
|
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: //LZ4
|
||||||
|
case 3: //LZ4HC
|
||||||
|
{
|
||||||
|
var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize));
|
||||||
|
using (var lz4Stream = new Lz4DecoderStream(compressedStream))
|
||||||
|
{
|
||||||
|
lz4Stream.CopyTo(blocksStream, blockInfo.uncompressedSize);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blocksStream.Position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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 PPtr<AnimationClip>[] m_Animations;
|
||||||
|
|
||||||
|
public Animation(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
var m_Animation = new PPtr<AnimationClip>(reader);
|
||||||
|
int numAnimations = reader.ReadInt32();
|
||||||
|
m_Animations = new PPtr<AnimationClip>[numAnimations];
|
||||||
|
for (int i = 0; i < numAnimations; i++)
|
||||||
|
{
|
||||||
|
m_Animations[i] = new PPtr<AnimationClip>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1001
AssetStudio/Classes/AnimationClip.cs
Normal file
1001
AssetStudio/Classes/AnimationClip.cs
Normal file
File diff suppressed because it is too large
Load Diff
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<Avatar> m_Avatar;
|
||||||
|
public PPtr<RuntimeAnimatorController> m_Controller;
|
||||||
|
public bool m_HasTransformHierarchy = true;
|
||||||
|
|
||||||
|
public Animator(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Avatar = new PPtr<Avatar>(reader);
|
||||||
|
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 5) //5.0 and up
|
||||||
|
{
|
||||||
|
var m_LinearVelocityBlending = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2018) //2018 and up
|
||||||
|
{
|
||||||
|
var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
605
AssetStudio/Classes/AnimatorController.cs
Normal file
605
AssetStudio/Classes/AnimatorController.cs
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class HumanPoseMask
|
||||||
|
{
|
||||||
|
public uint word0;
|
||||||
|
public uint word1;
|
||||||
|
public uint word2;
|
||||||
|
|
||||||
|
public HumanPoseMask(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
word0 = reader.ReadUInt32();
|
||||||
|
word1 = reader.ReadUInt32();
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 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)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
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();
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
|
||||||
|
{
|
||||||
|
m_DefaultWeight = reader.ReadSingle();
|
||||||
|
}
|
||||||
|
m_IKPass = reader.ReadBoolean();
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
|
||||||
|
{
|
||||||
|
m_SyncedLayerAffectsTiming = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
m_InterruptionSource = reader.ReadInt32();
|
||||||
|
m_OrderedInterruption = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Atomic = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||||
|
{
|
||||||
|
m_CanTransitionToSelf = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LeafInfoConstant
|
||||||
|
{
|
||||||
|
public uint[] m_IDArray;
|
||||||
|
public uint m_IndexOffset;
|
||||||
|
|
||||||
|
public LeafInfoConstant(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_IDArray = reader.ReadUInt32Array();
|
||||||
|
m_IndexOffset = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MotionNeighborList
|
||||||
|
{
|
||||||
|
public uint[] m_NeighborArray;
|
||||||
|
|
||||||
|
public MotionNeighborList(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_NeighborArray = reader.ReadUInt32Array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
m_ChildMagnitudeArray = reader.ReadSingleArray();
|
||||||
|
m_ChildPairVectorArray = reader.ReadVector2Array();
|
||||||
|
m_ChildPairAvgMagInvArray = reader.ReadSingleArray();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BlendDirectDataConstant
|
||||||
|
{
|
||||||
|
public uint[] m_ChildBlendEventIDArray;
|
||||||
|
public bool m_NormalizedBlendValues;
|
||||||
|
|
||||||
|
public BlendDirectDataConstant(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_ChildBlendEventIDArray = reader.ReadUInt32Array();
|
||||||
|
m_NormalizedBlendValues = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BlendTreeNodeConstant
|
||||||
|
{
|
||||||
|
public uint m_BlendType;
|
||||||
|
public uint m_BlendEventID;
|
||||||
|
public uint m_BlendEventYID;
|
||||||
|
public uint[] m_ChildIndices;
|
||||||
|
public float[] m_ChildThresholdArray;
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||||
|
{
|
||||||
|
m_BlendType = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
m_BlendEventID = reader.ReadUInt32();
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||||
|
{
|
||||||
|
m_BlendEventYID = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
m_ChildIndices = reader.ReadUInt32Array();
|
||||||
|
if (version[0] < 4 || (version[0] == 4 && version[1] < 1)) //4.1 down
|
||||||
|
{
|
||||||
|
m_ChildThresholdArray = reader.ReadSingleArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||||
|
{
|
||||||
|
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] == 4 && version[1] >= 5) //4.5 - 5.0
|
||||||
|
{
|
||||||
|
m_ClipIndex = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Duration = reader.ReadSingle();
|
||||||
|
|
||||||
|
if (version[0] > 4
|
||||||
|
|| (version[0] == 4 && version[1] > 1)
|
||||||
|
|| (version[0] == 4 && version[1] == 1 && version[2] >= 3)) //4.1.3 and up
|
||||||
|
{
|
||||||
|
m_CycleOffset = reader.ReadSingle();
|
||||||
|
m_Mirror = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BlendTreeConstant
|
||||||
|
{
|
||||||
|
public BlendTreeNodeConstant[] m_NodeArray;
|
||||||
|
public ValueArrayConstant m_BlendEventArrayConstant;
|
||||||
|
|
||||||
|
public BlendTreeConstant(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
int numNodes = reader.ReadInt32();
|
||||||
|
m_NodeArray = new BlendTreeNodeConstant[numNodes];
|
||||||
|
for (int i = 0; i < numNodes; i++)
|
||||||
|
{
|
||||||
|
m_NodeArray[i] = new BlendTreeNodeConstant(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
|
||||||
|
{
|
||||||
|
m_BlendEventArrayConstant = new ValueArrayConstant(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_BlendTreeConstantIndexArray = reader.ReadInt32Array();
|
||||||
|
|
||||||
|
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 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();
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||||
|
{
|
||||||
|
m_PathID = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
if (version[0] >= 5) //5.0 and up
|
||||||
|
{
|
||||||
|
m_FullPathID = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_TagID = reader.ReadUInt32();
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 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();
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||||
|
{
|
||||||
|
m_CycleOffset = reader.ReadSingle();
|
||||||
|
}
|
||||||
|
m_IKOnFeet = reader.ReadBoolean();
|
||||||
|
if (version[0] >= 5) //5.0 and up
|
||||||
|
{
|
||||||
|
m_WriteDefaultValues = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Loop = reader.ReadBoolean();
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||||
|
{
|
||||||
|
m_Mirror = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Vector4[] m_VectorValues;
|
||||||
|
public Vector3[] m_PositionValues;
|
||||||
|
public Vector4[] m_QuaternionValues;
|
||||||
|
public Vector3[] m_ScaleValues;
|
||||||
|
|
||||||
|
public ValueArray(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down
|
||||||
|
{
|
||||||
|
m_BoolValues = reader.ReadBooleanArray();
|
||||||
|
reader.AlignStream();
|
||||||
|
m_IntValues = reader.ReadInt32Array();
|
||||||
|
m_FloatValues = reader.ReadSingleArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
|
||||||
|
{
|
||||||
|
m_VectorValues = reader.ReadVector4Array();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int numPosValues = reader.ReadInt32();
|
||||||
|
m_PositionValues = new Vector3[numPosValues];
|
||||||
|
for (int i = 0; i < numPosValues; i++)
|
||||||
|
{
|
||||||
|
m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
|
||||||
|
}
|
||||||
|
|
||||||
|
m_QuaternionValues = reader.ReadVector4Array();
|
||||||
|
|
||||||
|
int numScaleValues = reader.ReadInt32();
|
||||||
|
m_ScaleValues = new Vector3[numScaleValues];
|
||||||
|
for (int i = 0; i < numScaleValues; i++)
|
||||||
|
{
|
||||||
|
m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
|
||||||
|
{
|
||||||
|
m_FloatValues = reader.ReadSingleArray();
|
||||||
|
m_IntValues = reader.ReadInt32Array();
|
||||||
|
m_BoolValues = reader.ReadBooleanArray();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 : RuntimeAnimatorController
|
||||||
|
{
|
||||||
|
public PPtr<AnimationClip>[] 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 KeyValuePair<uint, string>[tosSize];
|
||||||
|
for (int i = 0; i < tosSize; i++)
|
||||||
|
{
|
||||||
|
m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());
|
||||||
|
}
|
||||||
|
|
||||||
|
int numClips = reader.ReadInt32();
|
||||||
|
m_AnimationClips = new PPtr<AnimationClip>[numClips];
|
||||||
|
for (int i = 0; i < numClips; i++)
|
||||||
|
{
|
||||||
|
m_AnimationClips[i] = new PPtr<AnimationClip>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
AssetStudio/Classes/AnimatorOverrideController.cs
Normal file
37
AssetStudio/Classes/AnimatorOverrideController.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class AnimationClipOverride
|
||||||
|
{
|
||||||
|
public PPtr<AnimationClip> m_OriginalClip;
|
||||||
|
public PPtr<AnimationClip> m_OverrideClip;
|
||||||
|
|
||||||
|
public AnimationClipOverride(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_OriginalClip = new PPtr<AnimationClip>(reader);
|
||||||
|
m_OverrideClip = new PPtr<AnimationClip>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AnimatorOverrideController : RuntimeAnimatorController
|
||||||
|
{
|
||||||
|
public PPtr<RuntimeAnimatorController> m_Controller;
|
||||||
|
public AnimationClipOverride[] m_Clips;
|
||||||
|
|
||||||
|
public AnimatorOverrideController(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
|
||||||
|
|
||||||
|
int numOverrides = reader.ReadInt32();
|
||||||
|
m_Clips = new AnimationClipOverride[numOverrides];
|
||||||
|
for (int i = 0; i < numOverrides; i++)
|
||||||
|
{
|
||||||
|
m_Clips[i] = new AnimationClipOverride(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
AssetStudio/Classes/AssetBundle.cs
Normal file
44
AssetStudio/Classes/AssetBundle.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class AssetInfo
|
||||||
|
{
|
||||||
|
public int preloadIndex;
|
||||||
|
public int preloadSize;
|
||||||
|
public PPtr<Object> asset;
|
||||||
|
|
||||||
|
public AssetInfo(ObjectReader reader)
|
||||||
|
{
|
||||||
|
preloadIndex = reader.ReadInt32();
|
||||||
|
preloadSize = reader.ReadInt32();
|
||||||
|
asset = new PPtr<Object>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AssetBundle : NamedObject
|
||||||
|
{
|
||||||
|
public PPtr<Object>[] m_PreloadTable;
|
||||||
|
public KeyValuePair<string, AssetInfo>[] m_Container;
|
||||||
|
|
||||||
|
public AssetBundle(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
var m_PreloadTableSize = reader.ReadInt32();
|
||||||
|
m_PreloadTable = new PPtr<Object>[m_PreloadTableSize];
|
||||||
|
for (int i = 0; i < m_PreloadTableSize; i++)
|
||||||
|
{
|
||||||
|
m_PreloadTable[i] = new PPtr<Object>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_ContainerSize = reader.ReadInt32();
|
||||||
|
m_Container = new KeyValuePair<string, AssetInfo>[m_ContainerSize];
|
||||||
|
for (int i = 0; i < m_ContainerSize; i++)
|
||||||
|
{
|
||||||
|
m_Container[i] = new KeyValuePair<string, AssetInfo>(reader.ReadAlignedString(), new AssetInfo(reader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
124
AssetStudio/Classes/AudioClip.cs
Normal file
124
AssetStudio/Classes/AudioClip.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
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 ResourceReader m_AudioData;
|
||||||
|
|
||||||
|
public AudioClip(ObjectReader reader) : 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();
|
||||||
|
|
||||||
|
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 = assetsFile.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();
|
||||||
|
m_SubsoundIndex = reader.ReadInt32();
|
||||||
|
m_PreloadAudioData = reader.ReadBoolean();
|
||||||
|
m_LoadInBackground = reader.ReadBoolean();
|
||||||
|
m_Legacy3D = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
|
||||||
|
m_Source = reader.ReadAlignedString();
|
||||||
|
m_Offset = reader.ReadInt64();
|
||||||
|
m_Size = reader.ReadInt64();
|
||||||
|
m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceReader resourceReader;
|
||||||
|
if (!string.IsNullOrEmpty(m_Source))
|
||||||
|
{
|
||||||
|
resourceReader = new ResourceReader(m_Source, assetsFile, m_Offset, (int)m_Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
|
||||||
|
}
|
||||||
|
m_AudioData = resourceReader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
312
AssetStudio/Classes/Avatar.cs
Normal file
312
AssetStudio/Classes/Avatar.cs
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
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 Node[] m_Node;
|
||||||
|
public uint[] m_ID;
|
||||||
|
public Axes[] m_AxesArray;
|
||||||
|
|
||||||
|
|
||||||
|
public Skeleton(ObjectReader reader)
|
||||||
|
{
|
||||||
|
int numNodes = reader.ReadInt32();
|
||||||
|
m_Node = new Node[numNodes];
|
||||||
|
for (int i = 0; i < numNodes; i++)
|
||||||
|
{
|
||||||
|
m_Node[i] = new Node(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ID = reader.ReadUInt32Array();
|
||||||
|
|
||||||
|
int numAxes = reader.ReadInt32();
|
||||||
|
m_AxesArray = new Axes[numAxes];
|
||||||
|
for (int i = 0; i < numAxes; i++)
|
||||||
|
{
|
||||||
|
m_AxesArray[i] = new Axes(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SkeletonPose
|
||||||
|
{
|
||||||
|
public xform[] m_X;
|
||||||
|
|
||||||
|
public SkeletonPose(ObjectReader reader)
|
||||||
|
{
|
||||||
|
int numXforms = reader.ReadInt32();
|
||||||
|
m_X = new xform[numXforms];
|
||||||
|
for (int i = 0; i < numXforms; i++)
|
||||||
|
{
|
||||||
|
m_X[i] = new xform(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Hand
|
||||||
|
{
|
||||||
|
public int[] m_HandBoneIndex;
|
||||||
|
|
||||||
|
public Hand(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_HandBoneIndex = reader.ReadInt32Array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Handle[] m_Handles;
|
||||||
|
public Collider[] m_ColliderArray;
|
||||||
|
public int[] m_HumanBoneIndex;
|
||||||
|
public float[] m_HumanBoneMass;
|
||||||
|
public 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 Handle[numHandles];
|
||||||
|
for (int i = 0; i < numHandles; i++)
|
||||||
|
{
|
||||||
|
m_Handles[i] = new Handle(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numColliders = reader.ReadInt32();
|
||||||
|
m_ColliderArray = new Collider[numColliders];
|
||||||
|
for (int i = 0; i < numColliders; i++)
|
||||||
|
{
|
||||||
|
m_ColliderArray[i] = new Collider(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_HumanBoneIndex = reader.ReadInt32Array();
|
||||||
|
|
||||||
|
m_HumanBoneMass = reader.ReadSingleArray();
|
||||||
|
|
||||||
|
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||||
|
{
|
||||||
|
m_ColliderIndex = reader.ReadInt32Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
|
||||||
|
{
|
||||||
|
m_HasTDoF = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AvatarConstant
|
||||||
|
{
|
||||||
|
public Skeleton m_AvatarSkeleton;
|
||||||
|
public SkeletonPose m_AvatarSkeletonPose;
|
||||||
|
public SkeletonPose m_DefaultPose;
|
||||||
|
public uint[] m_SkeletonNameIDArray;
|
||||||
|
public Human m_Human;
|
||||||
|
public int[] m_HumanSkeletonIndexArray;
|
||||||
|
public int[] m_HumanSkeletonReverseIndexArray;
|
||||||
|
public int m_RootMotionBoneIndex;
|
||||||
|
public xform m_RootMotionBoneX;
|
||||||
|
public Skeleton m_RootMotionSkeleton;
|
||||||
|
public SkeletonPose m_RootMotionSkeletonPose;
|
||||||
|
public 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);
|
||||||
|
|
||||||
|
m_SkeletonNameIDArray = reader.ReadUInt32Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Human = new Human(reader);
|
||||||
|
|
||||||
|
m_HumanSkeletonIndexArray = reader.ReadInt32Array();
|
||||||
|
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||||
|
{
|
||||||
|
m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
m_RootMotionSkeletonIndexArray = reader.ReadInt32Array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class Avatar : NamedObject
|
||||||
|
{
|
||||||
|
public uint m_AvatarSize;
|
||||||
|
public AvatarConstant m_Avatar;
|
||||||
|
public 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 KeyValuePair<uint, string>[numTOS];
|
||||||
|
for (int i = 0; i < numTOS; i++)
|
||||||
|
{
|
||||||
|
m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());
|
||||||
|
}
|
||||||
|
|
||||||
|
//HumanDescription m_HumanDescription 2019 and up
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FindBonePath(uint hash)
|
||||||
|
{
|
||||||
|
return m_TOS.FirstOrDefault(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
AssetStudio/Classes/BuildSettings.cs
Normal file
24
AssetStudio/Classes/BuildSettings.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
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)
|
||||||
|
{
|
||||||
|
var levels = reader.ReadStringArray();
|
||||||
|
|
||||||
|
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<GameObject> m_GameObject;
|
||||||
|
|
||||||
|
protected Component(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_GameObject = new PPtr<GameObject>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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 = new PPtr<EditorExtension>(reader);
|
||||||
|
var m_PrefabInternal = new PPtr<Object>(reader); //PPtr<Prefab>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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 = new PPtr<Material>(reader);
|
||||||
|
var m_FontSize = reader.ReadSingle();
|
||||||
|
var m_Texture = new PPtr<Texture>(reader);
|
||||||
|
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();
|
||||||
|
var m_DefaultMaterial = new PPtr<Material>(reader);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_Texture = new PPtr<Texture>(reader);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
else { float m_PixelScale = reader.ReadSingle(); }
|
||||||
|
|
||||||
|
int m_FontData_size = reader.ReadInt32();
|
||||||
|
if (m_FontData_size > 0)
|
||||||
|
{
|
||||||
|
m_FontData = reader.ReadBytes(m_FontData_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
AssetStudio/Classes/GameObject.cs
Normal file
37
AssetStudio/Classes/GameObject.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public sealed class GameObject : EditorExtension
|
||||||
|
{
|
||||||
|
public PPtr<Component>[] m_Components;
|
||||||
|
public string m_Name;
|
||||||
|
|
||||||
|
public Transform m_Transform;
|
||||||
|
public MeshRenderer m_MeshRenderer;
|
||||||
|
public MeshFilter m_MeshFilter;
|
||||||
|
public SkinnedMeshRenderer m_SkinnedMeshRenderer;
|
||||||
|
public Animator m_Animator;
|
||||||
|
public Animation m_Animation;
|
||||||
|
|
||||||
|
public GameObject(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
int m_Component_size = reader.ReadInt32();
|
||||||
|
m_Components = new PPtr<Component>[m_Component_size];
|
||||||
|
for (int i = 0; i < m_Component_size; i++)
|
||||||
|
{
|
||||||
|
if ((version[0] == 5 && version[1] < 5) || version[0] < 5) //5.5 down
|
||||||
|
{
|
||||||
|
int first = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
m_Components[i] = new PPtr<Component>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_Layer = reader.ReadInt32();
|
||||||
|
m_Name = reader.ReadAlignedString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
AssetStudio/Classes/Material.cs
Normal file
100
AssetStudio/Classes/Material.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class UnityTexEnv
|
||||||
|
{
|
||||||
|
public PPtr<Texture> m_Texture;
|
||||||
|
public Vector2 m_Scale;
|
||||||
|
public Vector2 m_Offset;
|
||||||
|
|
||||||
|
public UnityTexEnv(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_Texture = new PPtr<Texture>(reader);
|
||||||
|
m_Scale = reader.ReadVector2();
|
||||||
|
m_Offset = reader.ReadVector2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UnityPropertySheet
|
||||||
|
{
|
||||||
|
public KeyValuePair<string, UnityTexEnv>[] m_TexEnvs;
|
||||||
|
public KeyValuePair<string, float>[] m_Floats;
|
||||||
|
public KeyValuePair<string, Color>[] m_Colors;
|
||||||
|
|
||||||
|
public UnityPropertySheet(ObjectReader reader)
|
||||||
|
{
|
||||||
|
int m_TexEnvsSize = reader.ReadInt32();
|
||||||
|
m_TexEnvs = new KeyValuePair<string, UnityTexEnv>[m_TexEnvsSize];
|
||||||
|
for (int i = 0; i < m_TexEnvsSize; i++)
|
||||||
|
{
|
||||||
|
m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_FloatsSize = reader.ReadInt32();
|
||||||
|
m_Floats = new KeyValuePair<string, float>[m_FloatsSize];
|
||||||
|
for (int i = 0; i < m_FloatsSize; i++)
|
||||||
|
{
|
||||||
|
m_Floats[i] = new KeyValuePair<string, float>(reader.ReadAlignedString(), reader.ReadSingle());
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_ColorsSize = reader.ReadInt32();
|
||||||
|
m_Colors = new KeyValuePair<string, Color>[m_ColorsSize];
|
||||||
|
for (int i = 0; i < m_ColorsSize; i++)
|
||||||
|
{
|
||||||
|
m_Colors[i] = new KeyValuePair<string, Color>(reader.ReadAlignedString(), reader.ReadColor4());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class Material : NamedObject
|
||||||
|
{
|
||||||
|
public PPtr<Shader> m_Shader;
|
||||||
|
public UnityPropertySheet m_SavedProperties;
|
||||||
|
|
||||||
|
public Material(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Shader = new PPtr<Shader>(reader);
|
||||||
|
|
||||||
|
if (version[0] == 4 && version[1] >= 1) //4.x
|
||||||
|
{
|
||||||
|
var m_ShaderKeywords = reader.ReadStringArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 5) //5.0 and up
|
||||||
|
{
|
||||||
|
var m_ShaderKeywords = reader.ReadAlignedString();
|
||||||
|
var m_LightmapFlags = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||||
|
{
|
||||||
|
var m_EnableInstancingVariants = reader.ReadBoolean();
|
||||||
|
//var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||||
|
{
|
||||||
|
var m_CustomRenderQueue = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
|
||||||
|
{
|
||||||
|
var stringTagMapSize = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < stringTagMapSize; i++)
|
||||||
|
{
|
||||||
|
var first = reader.ReadAlignedString();
|
||||||
|
var second = reader.ReadAlignedString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||||
|
{
|
||||||
|
var disabledShaderPasses = reader.ReadStringArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_SavedProperties = new UnityPropertySheet(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1382
AssetStudio/Classes/Mesh.cs
Normal file
1382
AssetStudio/Classes/Mesh.cs
Normal file
File diff suppressed because it is too large
Load Diff
17
AssetStudio/Classes/MeshFilter.cs
Normal file
17
AssetStudio/Classes/MeshFilter.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public sealed class MeshFilter : Component
|
||||||
|
{
|
||||||
|
public PPtr<Mesh> m_Mesh;
|
||||||
|
|
||||||
|
public MeshFilter(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Mesh = new PPtr<Mesh>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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<MonoScript> m_Script;
|
||||||
|
public string m_Name;
|
||||||
|
|
||||||
|
public MonoBehaviour(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Script = new PPtr<MonoScript>(reader);
|
||||||
|
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 PPtr<AudioClip> m_AudioClip;
|
||||||
|
|
||||||
|
public MovieTexture(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
var m_Loop = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
m_AudioClip = new PPtr<AudioClip>(reader);
|
||||||
|
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;
|
||||||
|
|
||||||
|
protected NamedObject(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Name = reader.ReadAlignedString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
AssetStudio/Classes/Object.cs
Normal file
62
AssetStudio/Classes/Object.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class Object
|
||||||
|
{
|
||||||
|
public SerializedFile assetsFile;
|
||||||
|
public ObjectReader reader;
|
||||||
|
public long m_PathID;
|
||||||
|
public int[] version;
|
||||||
|
protected BuildType buildType;
|
||||||
|
public BuildTarget platform;
|
||||||
|
public ClassIDType type;
|
||||||
|
public SerializedType serializedType;
|
||||||
|
public uint byteSize;
|
||||||
|
|
||||||
|
public Object(ObjectReader reader)
|
||||||
|
{
|
||||||
|
this.reader = reader;
|
||||||
|
reader.Reset();
|
||||||
|
assetsFile = reader.assetsFile;
|
||||||
|
type = reader.type;
|
||||||
|
m_PathID = reader.m_PathID;
|
||||||
|
version = reader.version;
|
||||||
|
buildType = reader.buildType;
|
||||||
|
platform = reader.platform;
|
||||||
|
serializedType = reader.serializedType;
|
||||||
|
byteSize = reader.byteSize;
|
||||||
|
|
||||||
|
if (platform == BuildTarget.NoTarget)
|
||||||
|
{
|
||||||
|
var m_ObjectHideFlags = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool HasStructMember(string name)
|
||||||
|
{
|
||||||
|
return serializedType?.m_Nodes != null && serializedType.m_Nodes.Any(x => x.m_Name == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Dump()
|
||||||
|
{
|
||||||
|
reader.Reset();
|
||||||
|
if (serializedType?.m_Nodes != null)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
TypeTreeHelper.ReadTypeString(sb, serializedType.m_Nodes, reader);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetRawData()
|
||||||
|
{
|
||||||
|
reader.Reset();
|
||||||
|
return reader.ReadBytes((int)byteSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
131
AssetStudio/Classes/PPtr.cs
Normal file
131
AssetStudio/Classes/PPtr.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public sealed class PPtr<T> where T : Object
|
||||||
|
{
|
||||||
|
public int m_FileID;
|
||||||
|
public long m_PathID;
|
||||||
|
|
||||||
|
private SerializedFile assetsFile;
|
||||||
|
private int index = -2; //-2 - Prepare, -1 - Missing
|
||||||
|
|
||||||
|
public PPtr(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_FileID = reader.ReadInt32();
|
||||||
|
m_PathID = reader.m_Version < 14 ? reader.ReadInt32() : reader.ReadInt64();
|
||||||
|
assetsFile = reader.assetsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
||||||
|
{
|
||||||
|
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
assetsFileIndexCache.Add(name, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
result = assetsFileList[index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGet(out T result)
|
||||||
|
{
|
||||||
|
if (TryGetAssetsFile(out var sourceFile))
|
||||||
|
{
|
||||||
|
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||||
|
{
|
||||||
|
if (obj is T variable)
|
||||||
|
{
|
||||||
|
result = variable;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGet<T2>(out T2 result) where T2 : Object
|
||||||
|
{
|
||||||
|
if (TryGetAssetsFile(out var sourceFile))
|
||||||
|
{
|
||||||
|
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||||
|
{
|
||||||
|
if (obj is T2 variable)
|
||||||
|
{
|
||||||
|
result = variable;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Set(T m_Object)
|
||||||
|
{
|
||||||
|
var name = m_Object.assetsFile.fileName;
|
||||||
|
if (string.Equals(assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
m_FileID = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_FileID = assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (m_FileID == -1)
|
||||||
|
{
|
||||||
|
assetsFile.m_Externals.Add(new FileIdentifier
|
||||||
|
{
|
||||||
|
fileName = m_Object.assetsFile.fileName
|
||||||
|
});
|
||||||
|
m_FileID = assetsFile.m_Externals.Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_FileID += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var assetsManager = assetsFile.assetsManager;
|
||||||
|
var assetsFileList = assetsManager.assetsFileList;
|
||||||
|
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
|
||||||
|
|
||||||
|
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
||||||
|
{
|
||||||
|
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
assetsFileIndexCache.Add(name, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_PathID = m_Object.m_PathID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsNull => m_PathID == 0 || m_FileID < 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
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();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
148
AssetStudio/Classes/Renderer.cs
Normal file
148
AssetStudio/Classes/Renderer.cs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class StaticBatchInfo
|
||||||
|
{
|
||||||
|
public ushort firstSubMesh;
|
||||||
|
public ushort subMeshCount;
|
||||||
|
|
||||||
|
public StaticBatchInfo(ObjectReader reader)
|
||||||
|
{
|
||||||
|
firstSubMesh = reader.ReadUInt16();
|
||||||
|
subMeshCount = reader.ReadUInt16();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Renderer : Component
|
||||||
|
{
|
||||||
|
public PPtr<Material>[] m_Materials;
|
||||||
|
public StaticBatchInfo m_StaticBatchInfo;
|
||||||
|
public uint[] m_SubsetIndices;
|
||||||
|
|
||||||
|
protected Renderer(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
if (version[0] < 5) //5.0 down
|
||||||
|
{
|
||||||
|
var m_Enabled = reader.ReadBoolean();
|
||||||
|
var m_CastShadows = reader.ReadBoolean();
|
||||||
|
var m_ReceiveShadows = reader.ReadBoolean();
|
||||||
|
var m_LightmapIndex = reader.ReadByte();
|
||||||
|
}
|
||||||
|
else //5.0 and up
|
||||||
|
{
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
|
||||||
|
{
|
||||||
|
var m_Enabled = reader.ReadBoolean();
|
||||||
|
var m_CastShadows = reader.ReadByte();
|
||||||
|
var m_ReceiveShadows = reader.ReadByte();
|
||||||
|
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||||
|
{
|
||||||
|
var m_DynamicOccludee = reader.ReadByte();
|
||||||
|
}
|
||||||
|
var m_MotionVectors = reader.ReadByte();
|
||||||
|
var m_LightProbeUsage = reader.ReadByte();
|
||||||
|
var m_ReflectionProbeUsage = reader.ReadByte();
|
||||||
|
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||||
|
{
|
||||||
|
var m_RayTracingMode = reader.ReadByte();
|
||||||
|
}
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var m_Enabled = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
var m_CastShadows = reader.ReadByte();
|
||||||
|
var m_ReceiveShadows = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2018) //2018 and up
|
||||||
|
{
|
||||||
|
var m_RenderingLayerMask = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
|
||||||
|
{
|
||||||
|
var m_RendererPriority = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_LightmapIndex = reader.ReadUInt16();
|
||||||
|
var m_LightmapIndexDynamic = reader.ReadUInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 3) //3.0 and up
|
||||||
|
{
|
||||||
|
var m_LightmapTilingOffset = reader.ReadVector4();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 5) //5.0 and up
|
||||||
|
{
|
||||||
|
var m_LightmapTilingOffsetDynamic = reader.ReadVector4();
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_MaterialsSize = reader.ReadInt32();
|
||||||
|
m_Materials = new PPtr<Material>[m_MaterialsSize];
|
||||||
|
for (int i = 0; i < m_MaterialsSize; i++)
|
||||||
|
{
|
||||||
|
m_Materials[i] = new PPtr<Material>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] < 3) //3.0 down
|
||||||
|
{
|
||||||
|
var m_LightmapTilingOffset = reader.ReadVector4();
|
||||||
|
}
|
||||||
|
else //3.0 and up
|
||||||
|
{
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
|
||||||
|
{
|
||||||
|
m_StaticBatchInfo = new StaticBatchInfo(reader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_SubsetIndices = reader.ReadUInt32Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_StaticBatchRoot = new PPtr<Transform>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
|
||||||
|
{
|
||||||
|
var m_ProbeAnchor = new PPtr<Transform>(reader);
|
||||||
|
var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);
|
||||||
|
}
|
||||||
|
else if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 - 5.3
|
||||||
|
{
|
||||||
|
var m_UseLightProbes = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
|
||||||
|
if (version[0] >= 5)//5.0 and up
|
||||||
|
{
|
||||||
|
var m_ReflectionProbeUsage = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_LightProbeAnchor = new PPtr<Transform>(reader); //5.0 and up m_ProbeAnchor
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||||
|
{
|
||||||
|
if (version[0] == 4 && version[1] == 3) //4.3
|
||||||
|
{
|
||||||
|
var m_SortingLayer = reader.ReadInt16();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var m_SortingLayerID = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
//SInt16 m_SortingLayer 5.6 and up
|
||||||
|
var m_SortingOrder = reader.ReadInt16();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
AssetStudio/Classes/RuntimeAnimatorController.cs
Normal file
15
AssetStudio/Classes/RuntimeAnimatorController.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public abstract class RuntimeAnimatorController : NamedObject
|
||||||
|
{
|
||||||
|
protected RuntimeAnimatorController(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
794
AssetStudio/Classes/Shader.cs
Normal file
794
AssetStudio/Classes/Shader.cs
Normal file
@@ -0,0 +1,794 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class StructParameter
|
||||||
|
{
|
||||||
|
public MatrixParameter[] m_MatrixParams;
|
||||||
|
public 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 VectorParameter[numVectorParams];
|
||||||
|
for (int i = 0; i < numVectorParams; i++)
|
||||||
|
{
|
||||||
|
m_VectorParams[i] = new VectorParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numMatrixParams = reader.ReadInt32();
|
||||||
|
m_MatrixParams = new MatrixParameter[numMatrixParams];
|
||||||
|
for (int i = 0; i < numMatrixParams; i++)
|
||||||
|
{
|
||||||
|
m_MatrixParams[i] = 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 string[] m_Attributes;
|
||||||
|
public SerializedPropertyType m_Type;
|
||||||
|
public uint m_Flags;
|
||||||
|
public float[] m_DefValue;
|
||||||
|
public SerializedTextureProperty m_DefTexture;
|
||||||
|
|
||||||
|
public SerializedProperty(BinaryReader reader)
|
||||||
|
{
|
||||||
|
m_Name = reader.ReadAlignedString();
|
||||||
|
m_Description = reader.ReadAlignedString();
|
||||||
|
m_Attributes = reader.ReadStringArray();
|
||||||
|
m_Type = (SerializedPropertyType)reader.ReadInt32();
|
||||||
|
m_Flags = reader.ReadUInt32();
|
||||||
|
m_DefValue = reader.ReadSingleArray(4);
|
||||||
|
m_DefTexture = new SerializedTextureProperty(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SerializedProperties
|
||||||
|
{
|
||||||
|
public SerializedProperty[] m_Props;
|
||||||
|
|
||||||
|
public SerializedProperties(BinaryReader reader)
|
||||||
|
{
|
||||||
|
int numProps = reader.ReadInt32();
|
||||||
|
m_Props = new SerializedProperty[numProps];
|
||||||
|
for (int i = 0; i < numProps; i++)
|
||||||
|
{
|
||||||
|
m_Props[i] = 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
|
||||||
|
};
|
||||||
|
|
||||||
|
public class SerializedShaderState
|
||||||
|
{
|
||||||
|
public string m_Name;
|
||||||
|
public SerializedShaderRTBlendState[] rtBlend;
|
||||||
|
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();
|
||||||
|
rtBlend = new SerializedShaderRTBlendState[8];
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
rtBlend[i] = new SerializedShaderRTBlendState(reader);
|
||||||
|
}
|
||||||
|
rtSeparateBlend = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShaderBindChannel
|
||||||
|
{
|
||||||
|
public sbyte source;
|
||||||
|
public sbyte target;
|
||||||
|
|
||||||
|
public ShaderBindChannel(BinaryReader reader)
|
||||||
|
{
|
||||||
|
source = reader.ReadSByte();
|
||||||
|
target = reader.ReadSByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ParserBindChannels
|
||||||
|
{
|
||||||
|
public ShaderBindChannel[] m_Channels;
|
||||||
|
public uint m_SourceMap;
|
||||||
|
|
||||||
|
public ParserBindChannels(BinaryReader reader)
|
||||||
|
{
|
||||||
|
int numChannels = reader.ReadInt32();
|
||||||
|
m_Channels = new ShaderBindChannel[numChannels];
|
||||||
|
for (int i = 0; i < numChannels; i++)
|
||||||
|
{
|
||||||
|
m_Channels[i] = new ShaderBindChannel(reader);
|
||||||
|
}
|
||||||
|
reader.AlignStream();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 MatrixParameter[] m_MatrixParams;
|
||||||
|
public VectorParameter[] m_VectorParams;
|
||||||
|
public 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 MatrixParameter[numMatrixParams];
|
||||||
|
for (int i = 0; i < numMatrixParams; i++)
|
||||||
|
{
|
||||||
|
m_MatrixParams[i] = new MatrixParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numVectorParams = reader.ReadInt32();
|
||||||
|
m_VectorParams = new VectorParameter[numVectorParams];
|
||||||
|
for (int i = 0; i < numVectorParams; i++)
|
||||||
|
{
|
||||||
|
m_VectorParams[i] = new VectorParameter(reader);
|
||||||
|
}
|
||||||
|
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||||
|
{
|
||||||
|
int numStructParams = reader.ReadInt32();
|
||||||
|
m_StructParams = new StructParameter[numStructParams];
|
||||||
|
for (int i = 0; i < numStructParams; i++)
|
||||||
|
{
|
||||||
|
m_StructParams[i] = 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 ushort[] m_KeywordIndices;
|
||||||
|
public sbyte m_ShaderHardwareTier;
|
||||||
|
public ShaderGpuProgramType m_GpuProgramType;
|
||||||
|
public VectorParameter[] m_VectorParams;
|
||||||
|
public MatrixParameter[] m_MatrixParams;
|
||||||
|
public TextureParameter[] m_TextureParams;
|
||||||
|
public BufferBinding[] m_BufferParams;
|
||||||
|
public ConstantBuffer[] m_ConstantBuffers;
|
||||||
|
public BufferBinding[] m_ConstantBufferBindings;
|
||||||
|
public UAVParameter[] m_UAVParams;
|
||||||
|
public SamplerParameter[] m_Samplers;
|
||||||
|
|
||||||
|
public SerializedSubProgram(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
m_BlobIndex = reader.ReadUInt32();
|
||||||
|
m_Channels = new ParserBindChannels(reader);
|
||||||
|
|
||||||
|
if (version[0] >= 2019) //2019 and up
|
||||||
|
{
|
||||||
|
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
var m_LocalKeywordIndices = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_KeywordIndices = reader.ReadUInt16Array();
|
||||||
|
if (version[0] >= 2017) //2017 and up
|
||||||
|
{
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ShaderHardwareTier = reader.ReadSByte();
|
||||||
|
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
||||||
|
reader.AlignStream();
|
||||||
|
|
||||||
|
int numVectorParams = reader.ReadInt32();
|
||||||
|
m_VectorParams = new VectorParameter[numVectorParams];
|
||||||
|
for (int i = 0; i < numVectorParams; i++)
|
||||||
|
{
|
||||||
|
m_VectorParams[i] = new VectorParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numMatrixParams = reader.ReadInt32();
|
||||||
|
m_MatrixParams = new MatrixParameter[numMatrixParams];
|
||||||
|
for (int i = 0; i < numMatrixParams; i++)
|
||||||
|
{
|
||||||
|
m_MatrixParams[i] = new MatrixParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numTextureParams = reader.ReadInt32();
|
||||||
|
m_TextureParams = new TextureParameter[numTextureParams];
|
||||||
|
for (int i = 0; i < numTextureParams; i++)
|
||||||
|
{
|
||||||
|
m_TextureParams[i] = new TextureParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numBufferParams = reader.ReadInt32();
|
||||||
|
m_BufferParams = new BufferBinding[numBufferParams];
|
||||||
|
for (int i = 0; i < numBufferParams; i++)
|
||||||
|
{
|
||||||
|
m_BufferParams[i] = new BufferBinding(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numConstantBuffers = reader.ReadInt32();
|
||||||
|
m_ConstantBuffers = new ConstantBuffer[numConstantBuffers];
|
||||||
|
for (int i = 0; i < numConstantBuffers; i++)
|
||||||
|
{
|
||||||
|
m_ConstantBuffers[i] = new ConstantBuffer(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numConstantBufferBindings = reader.ReadInt32();
|
||||||
|
m_ConstantBufferBindings = new BufferBinding[numConstantBufferBindings];
|
||||||
|
for (int i = 0; i < numConstantBufferBindings; i++)
|
||||||
|
{
|
||||||
|
m_ConstantBufferBindings[i] = new BufferBinding(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numUAVParams = reader.ReadInt32();
|
||||||
|
m_UAVParams = new UAVParameter[numUAVParams];
|
||||||
|
for (int i = 0; i < numUAVParams; i++)
|
||||||
|
{
|
||||||
|
m_UAVParams[i] = new UAVParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2017) //2017 and up
|
||||||
|
{
|
||||||
|
int numSamplers = reader.ReadInt32();
|
||||||
|
m_Samplers = new SamplerParameter[numSamplers];
|
||||||
|
for (int i = 0; i < numSamplers; i++)
|
||||||
|
{
|
||||||
|
m_Samplers[i] = 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 SerializedSubProgram[] m_SubPrograms;
|
||||||
|
|
||||||
|
public SerializedProgram(ObjectReader reader)
|
||||||
|
{
|
||||||
|
int numSubPrograms = reader.ReadInt32();
|
||||||
|
m_SubPrograms = new SerializedSubProgram[numSubPrograms];
|
||||||
|
for (int i = 0; i < numSubPrograms; i++)
|
||||||
|
{
|
||||||
|
m_SubPrograms[i] = new SerializedSubProgram(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PassType
|
||||||
|
{
|
||||||
|
kPassTypeNormal = 0,
|
||||||
|
kPassTypeUse = 1,
|
||||||
|
kPassTypeGrab = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
public class SerializedPass
|
||||||
|
{
|
||||||
|
public 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 SerializedProgram progRayTracing;
|
||||||
|
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 KeyValuePair<string, int>[numIndices];
|
||||||
|
for (int i = 0; i < numIndices; i++)
|
||||||
|
{
|
||||||
|
m_NameIndices[i] = 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);
|
||||||
|
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||||
|
{
|
||||||
|
progRayTracing = new SerializedProgram(reader);
|
||||||
|
}
|
||||||
|
m_HasInstancingVariant = reader.ReadBoolean();
|
||||||
|
if (version[0] >= 2018) //2018 and up
|
||||||
|
{
|
||||||
|
var m_HasProceduralInstancingVariant = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
reader.AlignStream();
|
||||||
|
m_UseName = reader.ReadAlignedString();
|
||||||
|
m_Name = reader.ReadAlignedString();
|
||||||
|
m_TextureName = reader.ReadAlignedString();
|
||||||
|
m_Tags = new SerializedTagMap(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SerializedTagMap
|
||||||
|
{
|
||||||
|
public KeyValuePair<string, string>[] tags;
|
||||||
|
|
||||||
|
public SerializedTagMap(BinaryReader reader)
|
||||||
|
{
|
||||||
|
int numTags = reader.ReadInt32();
|
||||||
|
tags = new KeyValuePair<string, string>[numTags];
|
||||||
|
for (int i = 0; i < numTags; i++)
|
||||||
|
{
|
||||||
|
tags[i] = new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SerializedSubShader
|
||||||
|
{
|
||||||
|
public SerializedPass[] m_Passes;
|
||||||
|
public SerializedTagMap m_Tags;
|
||||||
|
public int m_LOD;
|
||||||
|
|
||||||
|
public SerializedSubShader(ObjectReader reader)
|
||||||
|
{
|
||||||
|
int numPasses = reader.ReadInt32();
|
||||||
|
m_Passes = new SerializedPass[numPasses];
|
||||||
|
for (int i = 0; i < numPasses; i++)
|
||||||
|
{
|
||||||
|
m_Passes[i] = 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 SerializedSubShader[] m_SubShaders;
|
||||||
|
public string m_Name;
|
||||||
|
public string m_CustomEditorName;
|
||||||
|
public string m_FallbackName;
|
||||||
|
public SerializedShaderDependency[] m_Dependencies;
|
||||||
|
public bool m_DisableNoSubshadersMessage;
|
||||||
|
|
||||||
|
public SerializedShader(ObjectReader reader)
|
||||||
|
{
|
||||||
|
m_PropInfo = new SerializedProperties(reader);
|
||||||
|
|
||||||
|
int numSubShaders = reader.ReadInt32();
|
||||||
|
m_SubShaders = new SerializedSubShader[numSubShaders];
|
||||||
|
for (int i = 0; i < numSubShaders; i++)
|
||||||
|
{
|
||||||
|
m_SubShaders[i] = new SerializedSubShader(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Name = reader.ReadAlignedString();
|
||||||
|
m_CustomEditorName = reader.ReadAlignedString();
|
||||||
|
m_FallbackName = reader.ReadAlignedString();
|
||||||
|
|
||||||
|
int numDependencies = reader.ReadInt32();
|
||||||
|
m_Dependencies = new SerializedShaderDependency[numDependencies];
|
||||||
|
for (int i = 0; i < numDependencies; i++)
|
||||||
|
{
|
||||||
|
m_Dependencies[i] = new SerializedShaderDependency(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_DisableNoSubshadersMessage = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ShaderCompilerPlatform
|
||||||
|
{
|
||||||
|
kShaderCompPlatformNone = -1,
|
||||||
|
kShaderCompPlatformGL = 0,
|
||||||
|
kShaderCompPlatformD3D9 = 1,
|
||||||
|
kShaderCompPlatformXbox360 = 2,
|
||||||
|
kShaderCompPlatformPS3 = 3,
|
||||||
|
kShaderCompPlatformD3D11 = 4,
|
||||||
|
kShaderCompPlatformGLES20 = 5,
|
||||||
|
kShaderCompPlatformNaCl = 6,
|
||||||
|
kShaderCompPlatformFlash = 7,
|
||||||
|
kShaderCompPlatformD3D11_9x = 8,
|
||||||
|
kShaderCompPlatformGLES3Plus = 9,
|
||||||
|
kShaderCompPlatformPSP2 = 10,
|
||||||
|
kShaderCompPlatformPS4 = 11,
|
||||||
|
kShaderCompPlatformXboxOne = 12,
|
||||||
|
kShaderCompPlatformPSM = 13,
|
||||||
|
kShaderCompPlatformMetal = 14,
|
||||||
|
kShaderCompPlatformOpenGLCore = 15,
|
||||||
|
kShaderCompPlatformN3DS = 16,
|
||||||
|
kShaderCompPlatformWiiU = 17,
|
||||||
|
kShaderCompPlatformVulkan = 18,
|
||||||
|
kShaderCompPlatformSwitch = 19,
|
||||||
|
kShaderCompPlatformXboxOneD3D12 = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
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 ShaderCompilerPlatform[] platforms;
|
||||||
|
public uint[] offsets;
|
||||||
|
public uint[] compressedLengths;
|
||||||
|
public 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);
|
||||||
|
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
|
||||||
|
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||||
|
{
|
||||||
|
offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||||
|
compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||||
|
decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offsets = reader.ReadUInt32Array();
|
||||||
|
compressedLengths = reader.ReadUInt32Array();
|
||||||
|
decompressedLengths = reader.ReadUInt32Array();
|
||||||
|
}
|
||||||
|
compressedBlob = reader.ReadBytes(reader.ReadInt32());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Script = reader.ReadBytes(reader.ReadInt32());
|
||||||
|
reader.AlignStream();
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
AssetStudio/Classes/SkinnedMeshRenderer.cs
Normal file
40
AssetStudio/Classes/SkinnedMeshRenderer.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public sealed class SkinnedMeshRenderer : Renderer
|
||||||
|
{
|
||||||
|
public PPtr<Mesh> m_Mesh;
|
||||||
|
public PPtr<Transform>[] m_Bones;
|
||||||
|
public 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();
|
||||||
|
|
||||||
|
if (version[0] == 2 && version[1] < 6) //2.6 down
|
||||||
|
{
|
||||||
|
var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Mesh = new PPtr<Mesh>(reader);
|
||||||
|
|
||||||
|
m_Bones = new PPtr<Transform>[reader.ReadInt32()];
|
||||||
|
for (int b = 0; b < m_Bones.Length; b++)
|
||||||
|
{
|
||||||
|
m_Bones[b] = new PPtr<Transform>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||||
|
{
|
||||||
|
m_BlendShapeWeights = reader.ReadSingleArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
245
AssetStudio/Classes/Sprite.cs
Normal file
245
AssetStudio/Classes/Sprite.cs
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class SecondarySpriteTexture
|
||||||
|
{
|
||||||
|
public PPtr<Texture2D> texture;
|
||||||
|
public string name;
|
||||||
|
|
||||||
|
public SecondarySpriteTexture(ObjectReader reader)
|
||||||
|
{
|
||||||
|
texture = new PPtr<Texture2D>(reader);
|
||||||
|
name = reader.ReadStringToNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SpritePackingRotation
|
||||||
|
{
|
||||||
|
kSPRNone = 0,
|
||||||
|
kSPRFlipHorizontal = 1,
|
||||||
|
kSPRFlipVertical = 2,
|
||||||
|
kSPRRotate180 = 3,
|
||||||
|
kSPRRotate90 = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum SpritePackingMode
|
||||||
|
{
|
||||||
|
kSPMTight = 0,
|
||||||
|
kSPMRectangle
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum SpriteMeshType
|
||||||
|
{
|
||||||
|
kSpriteMeshTypeFullRect,
|
||||||
|
kSpriteMeshTypeTight
|
||||||
|
};
|
||||||
|
|
||||||
|
public class SpriteSettings
|
||||||
|
{
|
||||||
|
public uint settingsRaw;
|
||||||
|
|
||||||
|
public uint packed;
|
||||||
|
public SpritePackingMode packingMode;
|
||||||
|
public SpritePackingRotation packingRotation;
|
||||||
|
public SpriteMeshType meshType;
|
||||||
|
|
||||||
|
public SpriteSettings(BinaryReader reader)
|
||||||
|
{
|
||||||
|
settingsRaw = reader.ReadUInt32();
|
||||||
|
|
||||||
|
packed = settingsRaw & 1; //1
|
||||||
|
packingMode = (SpritePackingMode)((settingsRaw >> 1) & 1); //1
|
||||||
|
packingRotation = (SpritePackingRotation)((settingsRaw >> 2) & 0xf); //4
|
||||||
|
meshType = (SpriteMeshType)((settingsRaw >> 6) & 1); //1
|
||||||
|
//reserved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SpriteVertex
|
||||||
|
{
|
||||||
|
public Vector3 pos;
|
||||||
|
public Vector2 uv;
|
||||||
|
|
||||||
|
public SpriteVertex(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
pos = reader.ReadVector3();
|
||||||
|
if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down
|
||||||
|
{
|
||||||
|
uv = reader.ReadVector2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SpriteRenderData
|
||||||
|
{
|
||||||
|
public PPtr<Texture2D> texture;
|
||||||
|
public PPtr<Texture2D> alphaTexture;
|
||||||
|
public SecondarySpriteTexture[] secondaryTextures;
|
||||||
|
public SubMesh[] m_SubMeshes;
|
||||||
|
public byte[] m_IndexBuffer;
|
||||||
|
public VertexData m_VertexData;
|
||||||
|
public SpriteVertex[] vertices;
|
||||||
|
public ushort[] indices;
|
||||||
|
public Matrix4x4[] m_Bindpose;
|
||||||
|
public BoneWeights4[] m_SourceSkin;
|
||||||
|
public RectangleF textureRect;
|
||||||
|
public Vector2 textureRectOffset;
|
||||||
|
public Vector2 atlasRectOffset;
|
||||||
|
public SpriteSettings settingsRaw;
|
||||||
|
public Vector4 uvTransform;
|
||||||
|
public float downscaleMultiplier;
|
||||||
|
|
||||||
|
public SpriteRenderData(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
texture = new PPtr<Texture2D>(reader);
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
|
||||||
|
{
|
||||||
|
alphaTexture = new PPtr<Texture2D>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2019) //2019 and up
|
||||||
|
{
|
||||||
|
var secondaryTexturesSize = reader.ReadInt32();
|
||||||
|
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
|
||||||
|
for (int i = 0; i < secondaryTexturesSize; i++)
|
||||||
|
{
|
||||||
|
secondaryTextures[i] = new SecondarySpriteTexture(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||||
|
{
|
||||||
|
var m_SubMeshesSize = reader.ReadInt32();
|
||||||
|
m_SubMeshes = new SubMesh[m_SubMeshesSize];
|
||||||
|
for (int i = 0; i < m_SubMeshesSize; i++)
|
||||||
|
{
|
||||||
|
m_SubMeshes[i] = new SubMesh(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IndexBuffer = reader.ReadBytes(reader.ReadInt32());
|
||||||
|
reader.AlignStream();
|
||||||
|
|
||||||
|
m_VertexData = new VertexData(reader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var verticesSize = reader.ReadInt32();
|
||||||
|
vertices = new SpriteVertex[verticesSize];
|
||||||
|
for (int i = 0; i < verticesSize; i++)
|
||||||
|
{
|
||||||
|
vertices[i] = new SpriteVertex(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
indices = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2018) //2018 and up
|
||||||
|
{
|
||||||
|
m_Bindpose = reader.ReadMatrixArray();
|
||||||
|
|
||||||
|
if (version[0] == 2018 && version[1] < 2) //2018.2 down
|
||||||
|
{
|
||||||
|
var m_SourceSkinSize = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < m_SourceSkinSize; i++)
|
||||||
|
{
|
||||||
|
m_SourceSkin[i] = new BoneWeights4(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textureRect = reader.ReadRectangleF();
|
||||||
|
textureRectOffset = reader.ReadVector2();
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||||
|
{
|
||||||
|
atlasRectOffset = reader.ReadVector2();
|
||||||
|
}
|
||||||
|
|
||||||
|
settingsRaw = new SpriteSettings(reader);
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||||
|
{
|
||||||
|
uvTransform = reader.ReadVector4();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2017) //2017 and up
|
||||||
|
{
|
||||||
|
downscaleMultiplier = reader.ReadSingle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class Sprite : NamedObject
|
||||||
|
{
|
||||||
|
public RectangleF m_Rect;
|
||||||
|
public Vector2 m_Offset;
|
||||||
|
public Vector4 m_Border;
|
||||||
|
public float m_PixelsToUnits;
|
||||||
|
public Vector2 m_Pivot;
|
||||||
|
public uint m_Extrude;
|
||||||
|
public bool m_IsPolygon;
|
||||||
|
public KeyValuePair<Guid, long> m_RenderDataKey;
|
||||||
|
public string[] m_AtlasTags;
|
||||||
|
public PPtr<SpriteAtlas> m_SpriteAtlas;
|
||||||
|
public SpriteRenderData m_RD;
|
||||||
|
public Vector2[][] m_PhysicsShape;
|
||||||
|
|
||||||
|
public Sprite(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Rect = reader.ReadRectangleF();
|
||||||
|
m_Offset = reader.ReadVector2();
|
||||||
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||||
|
{
|
||||||
|
m_Border = reader.ReadVector4();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_PixelsToUnits = reader.ReadSingle();
|
||||||
|
if (version[0] > 5
|
||||||
|
|| (version[0] == 5 && version[1] > 4)
|
||||||
|
|| (version[0] == 5 && version[1] == 4 && version[2] >= 2)
|
||||||
|
|| (version[0] == 5 && version[1] == 4 && version[2] == 1 && buildType.IsPatch && version[3] >= 3)) //5.4.1p3 and up
|
||||||
|
{
|
||||||
|
m_Pivot = reader.ReadVector2();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Extrude = reader.ReadUInt32();
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
|
||||||
|
{
|
||||||
|
m_IsPolygon = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2017) //2017 and up
|
||||||
|
{
|
||||||
|
var first = new Guid(reader.ReadBytes(16));
|
||||||
|
var second = reader.ReadInt64();
|
||||||
|
m_RenderDataKey = new KeyValuePair<Guid, long>(first, second);
|
||||||
|
|
||||||
|
m_AtlasTags = reader.ReadStringArray();
|
||||||
|
|
||||||
|
m_SpriteAtlas = new PPtr<SpriteAtlas>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_RD = new SpriteRenderData(reader);
|
||||||
|
|
||||||
|
if (version[0] >= 2017) //2017 and up
|
||||||
|
{
|
||||||
|
var m_PhysicsShapeSize = reader.ReadInt32();
|
||||||
|
m_PhysicsShape = new Vector2[m_PhysicsShapeSize][];
|
||||||
|
for (int i = 0; i < m_PhysicsShapeSize; i++)
|
||||||
|
{
|
||||||
|
m_PhysicsShape[i] = reader.ReadVector2Array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//vector m_Bones 2018 and up
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
AssetStudio/Classes/SpriteAtlas.cs
Normal file
63
AssetStudio/Classes/SpriteAtlas.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class SpriteAtlasData
|
||||||
|
{
|
||||||
|
public PPtr<Texture2D> texture;
|
||||||
|
public PPtr<Texture2D> 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 = new PPtr<Texture2D>(reader);
|
||||||
|
alphaTexture = new PPtr<Texture2D>(reader);
|
||||||
|
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 PPtr<Sprite>[] m_PackedSprites;
|
||||||
|
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
|
||||||
|
|
||||||
|
public SpriteAtlas(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
var m_PackedSpritesSize = reader.ReadInt32();
|
||||||
|
m_PackedSprites = new PPtr<Sprite>[m_PackedSpritesSize];
|
||||||
|
for (int i = 0; i < m_PackedSpritesSize; i++)
|
||||||
|
{
|
||||||
|
m_PackedSprites[i] = new PPtr<Sprite>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_PackedSpriteNamesToIndex = reader.ReadStringArray();
|
||||||
|
|
||||||
|
var m_RenderDataMapSize = reader.ReadInt32();
|
||||||
|
m_RenderDataMap = new Dictionary<KeyValuePair<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 KeyValuePair<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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
175
AssetStudio/Classes/Texture2D.cs
Normal file
175
AssetStudio/Classes/Texture2D.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class StreamingInfo
|
||||||
|
{
|
||||||
|
public uint offset;
|
||||||
|
public uint size;
|
||||||
|
public string path;
|
||||||
|
|
||||||
|
public StreamingInfo(ObjectReader reader)
|
||||||
|
{
|
||||||
|
offset = reader.ReadUInt32();
|
||||||
|
size = reader.ReadUInt32();
|
||||||
|
path = reader.ReadAlignedString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GLTextureSettings
|
||||||
|
{
|
||||||
|
public int m_FilterMode;
|
||||||
|
public int m_Aniso;
|
||||||
|
public float m_MipBias;
|
||||||
|
public int m_WrapMode;
|
||||||
|
|
||||||
|
public GLTextureSettings(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
m_FilterMode = reader.ReadInt32();
|
||||||
|
m_Aniso = reader.ReadInt32();
|
||||||
|
m_MipBias = reader.ReadSingle();
|
||||||
|
if (version[0] >= 2017)//2017.x and up
|
||||||
|
{
|
||||||
|
m_WrapMode = reader.ReadInt32(); //m_WrapU
|
||||||
|
int m_WrapV = reader.ReadInt32();
|
||||||
|
int m_WrapW = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_WrapMode = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class Texture2D : Texture
|
||||||
|
{
|
||||||
|
public int m_Width;
|
||||||
|
public int m_Height;
|
||||||
|
public TextureFormat m_TextureFormat;
|
||||||
|
public bool m_MipMap;
|
||||||
|
public int m_MipCount;
|
||||||
|
public GLTextureSettings m_TextureSettings;
|
||||||
|
public ResourceReader image_data;
|
||||||
|
public StreamingInfo m_StreamData;
|
||||||
|
|
||||||
|
public Texture2D(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_Width = reader.ReadInt32();
|
||||||
|
m_Height = reader.ReadInt32();
|
||||||
|
var m_CompleteImageSize = reader.ReadInt32();
|
||||||
|
m_TextureFormat = (TextureFormat)reader.ReadInt32();
|
||||||
|
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
|
||||||
|
{
|
||||||
|
m_MipMap = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_MipCount = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
var m_IsReadable = reader.ReadBoolean(); //2.6.0 and up
|
||||||
|
var m_ReadAllowed = reader.ReadBoolean(); //3.0.0 - 5.4
|
||||||
|
//bool m_StreamingMipmaps 2018.2 and up
|
||||||
|
reader.AlignStream();
|
||||||
|
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||||
|
{
|
||||||
|
var m_StreamingMipmapsPriority = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
var m_ImageCount = reader.ReadInt32();
|
||||||
|
var m_TextureDimension = reader.ReadInt32();
|
||||||
|
m_TextureSettings = new GLTextureSettings(reader);
|
||||||
|
if (version[0] >= 3) //3.0 and up
|
||||||
|
{
|
||||||
|
var m_LightmapFormat = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5.0 and up
|
||||||
|
{
|
||||||
|
var m_ColorSpace = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
var image_data_size = reader.ReadInt32();
|
||||||
|
if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
|
||||||
|
{
|
||||||
|
m_StreamData = new StreamingInfo(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceReader resourceReader;
|
||||||
|
if (!string.IsNullOrEmpty(m_StreamData?.path))
|
||||||
|
{
|
||||||
|
resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, (int)m_StreamData.size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
|
||||||
|
}
|
||||||
|
image_data = resourceReader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
ASTC_HDR_4x4,
|
||||||
|
ASTC_HDR_5x5,
|
||||||
|
ASTC_HDR_6x6,
|
||||||
|
ASTC_HDR_8x8,
|
||||||
|
ASTC_HDR_10x10,
|
||||||
|
ASTC_HDR_12x12,
|
||||||
|
}
|
||||||
|
}
|
||||||
31
AssetStudio/Classes/Transform.cs
Normal file
31
AssetStudio/Classes/Transform.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class Transform : Component
|
||||||
|
{
|
||||||
|
public Quaternion m_LocalRotation;
|
||||||
|
public Vector3 m_LocalPosition;
|
||||||
|
public Vector3 m_LocalScale;
|
||||||
|
public PPtr<Transform>[] m_Children;
|
||||||
|
public PPtr<Transform> m_Father;
|
||||||
|
|
||||||
|
public Transform(ObjectReader reader) : base(reader)
|
||||||
|
{
|
||||||
|
m_LocalRotation = reader.ReadQuaternion();
|
||||||
|
m_LocalPosition = reader.ReadVector3();
|
||||||
|
m_LocalScale = reader.ReadVector3();
|
||||||
|
|
||||||
|
int m_ChildrenCount = reader.ReadInt32();
|
||||||
|
m_Children = new PPtr<Transform>[m_ChildrenCount];
|
||||||
|
for (int i = 0; i < m_ChildrenCount; i++)
|
||||||
|
{
|
||||||
|
m_Children[i] = new PPtr<Transform>(reader);
|
||||||
|
}
|
||||||
|
m_Father = new PPtr<Transform>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
AssetStudio/Classes/VideoClip.cs
Normal file
53
AssetStudio/Classes/VideoClip.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public sealed class VideoClip : NamedObject
|
||||||
|
{
|
||||||
|
public ResourceReader m_VideoData;
|
||||||
|
public string m_OriginalPath;
|
||||||
|
public string m_Source;
|
||||||
|
public ulong m_Size;
|
||||||
|
|
||||||
|
public VideoClip(ObjectReader reader) : 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 || (version[0] == 2017 && version[1] >= 2)) //2017.2 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();
|
||||||
|
var m_AudioChannelCount = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
var m_AudioSampleRate = reader.ReadUInt32Array();
|
||||||
|
var m_AudioLanguage = reader.ReadStringArray();
|
||||||
|
//StreamedResource m_ExternalResources
|
||||||
|
m_Source = reader.ReadAlignedString();
|
||||||
|
var m_Offset = reader.ReadUInt64();
|
||||||
|
m_Size = reader.ReadUInt64();
|
||||||
|
var m_HasSplitAlpha = reader.ReadBoolean();
|
||||||
|
|
||||||
|
ResourceReader resourceReader;
|
||||||
|
if (!string.IsNullOrEmpty(m_Source))
|
||||||
|
{
|
||||||
|
resourceReader = new ResourceReader(m_Source, assetsFile, (long)m_Offset, (int)m_Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
|
||||||
|
}
|
||||||
|
m_VideoData = resourceReader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
119
AssetStudio/CommonString.cs
Normal file
119
AssetStudio/CommonString.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public static class CommonString
|
||||||
|
{
|
||||||
|
public static readonly Dictionary<uint, string> StringBuffer = new Dictionary<uint, 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"},
|
||||||
|
{1093, "m_CorrespondingSourceObject"},
|
||||||
|
{1121, "m_PrefabInstance"},
|
||||||
|
{1138, "m_PrefabAsset"},
|
||||||
|
{1152, "FileSize"}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
165
AssetStudio/Extensions/BinaryReaderExtensions.cs
Normal file
165
AssetStudio/Extensions/BinaryReaderExtensions.cs
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public static class BinaryReaderExtensions
|
||||||
|
{
|
||||||
|
public static void AlignStream(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
reader.AlignStream(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, int maxLength = 32767)
|
||||||
|
{
|
||||||
|
var bytes = new List<byte>();
|
||||||
|
int count = 0;
|
||||||
|
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
|
||||||
|
{
|
||||||
|
var b = reader.ReadByte();
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bytes.Add(b);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color ReadColor4(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix4x4 ReadMatrix(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return new Matrix4x4(reader.ReadSingleArray(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static T[] ReadArray<T>(Func<T> del, int length)
|
||||||
|
{
|
||||||
|
var array = new T[length];
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
array[i] = del();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool[] ReadBooleanArray(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadBoolean, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ushort[] ReadUInt16Array(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadUInt16, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] ReadInt32Array(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadInt32, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] ReadInt32Array(this BinaryReader reader, int length)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadInt32, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint[] ReadUInt32Array(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadUInt32, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint[][] ReadUInt32ArrayArray(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadUInt32Array, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint[] ReadUInt32Array(this BinaryReader reader, int length)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadUInt32, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float[] ReadSingleArray(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadSingle, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float[] ReadSingleArray(this BinaryReader reader, int length)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadSingle, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] ReadStringArray(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadAlignedString, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2[] ReadVector2Array(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadVector2, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4[] ReadVector4Array(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadVector4, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix4x4[] ReadMatrixArray(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
return ReadArray(reader.ReadMatrix, reader.ReadInt32());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
AssetStudio/Extensions/BinaryWriterExtensions.cs
Normal file
27
AssetStudio/Extensions/BinaryWriterExtensions.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public static class BinaryWriterExtensions
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
323
AssetStudio/IImported.cs
Normal file
323
AssetStudio/IImported.cs
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public interface IImported
|
||||||
|
{
|
||||||
|
ImportedFrame RootFrame { get; }
|
||||||
|
List<ImportedMesh> MeshList { get; }
|
||||||
|
List<ImportedMaterial> MaterialList { get; }
|
||||||
|
List<ImportedTexture> TextureList { get; }
|
||||||
|
List<ImportedKeyframedAnimation> AnimationList { get; }
|
||||||
|
List<ImportedMorph> MorphList { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedFrame
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public Vector3 LocalRotation { get; set; }
|
||||||
|
public Vector3 LocalPosition { get; set; }
|
||||||
|
public Vector3 LocalScale { get; set; }
|
||||||
|
public ImportedFrame Parent { get; set; }
|
||||||
|
|
||||||
|
private List<ImportedFrame> children;
|
||||||
|
|
||||||
|
public ImportedFrame this[int i] => children[i];
|
||||||
|
|
||||||
|
public int Count => children.Count;
|
||||||
|
|
||||||
|
public string Path
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var frame = this;
|
||||||
|
var path = frame.Name;
|
||||||
|
while (frame.Parent != null)
|
||||||
|
{
|
||||||
|
frame = frame.Parent;
|
||||||
|
path = frame.Name + "/" + path;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportedFrame(int childrenCount = 0)
|
||||||
|
{
|
||||||
|
children = new List<ImportedFrame>(childrenCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddChild(ImportedFrame obj)
|
||||||
|
{
|
||||||
|
children.Add(obj);
|
||||||
|
obj.Parent?.Remove(obj);
|
||||||
|
obj.Parent = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(ImportedFrame frame)
|
||||||
|
{
|
||||||
|
children.Remove(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportedFrame FindFrameByPath(string path)
|
||||||
|
{
|
||||||
|
var name = path.Substring(path.LastIndexOf('/') + 1);
|
||||||
|
foreach (var frame in FindChilds(name))
|
||||||
|
{
|
||||||
|
if (frame.Path.EndsWith(path, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportedFrame FindFrame(string name)
|
||||||
|
{
|
||||||
|
if (Name == name)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
var frame = child.FindFrame(name);
|
||||||
|
if (frame != null)
|
||||||
|
{
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportedFrame FindChild(string name, bool recursive = true)
|
||||||
|
{
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
if (recursive)
|
||||||
|
{
|
||||||
|
var frame = child.FindFrame(name);
|
||||||
|
if (frame != null)
|
||||||
|
{
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (child.Name == name)
|
||||||
|
{
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ImportedFrame> FindChilds(string name)
|
||||||
|
{
|
||||||
|
if (Name == name)
|
||||||
|
{
|
||||||
|
yield return this;
|
||||||
|
}
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
foreach (var item in child.FindChilds(name))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedMesh
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public List<ImportedSubmesh> SubmeshList { get; set; }
|
||||||
|
public List<ImportedBone> BoneList { get; set; }
|
||||||
|
public bool hasNormal { get; set; }
|
||||||
|
public bool[] hasUV { get; set; }
|
||||||
|
public bool hasTangent { get; set; }
|
||||||
|
public bool hasColor { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedSubmesh
|
||||||
|
{
|
||||||
|
public List<ImportedVertex> VertexList { get; set; }
|
||||||
|
public List<ImportedFace> FaceList { get; set; }
|
||||||
|
public string Material { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedVertex
|
||||||
|
{
|
||||||
|
public Vector3 Vertex { get; set; }
|
||||||
|
public Vector3 Normal { get; set; }
|
||||||
|
public float[][] UV { get; set; }
|
||||||
|
public Vector4 Tangent { get; set; }
|
||||||
|
public Color Color { get; set; }
|
||||||
|
public float[] Weights { get; set; }
|
||||||
|
public int[] BoneIndices { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedFace
|
||||||
|
{
|
||||||
|
public int[] VertexIndices { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedBone
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public Matrix4x4 Matrix { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedMaterial
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public Color Diffuse { get; set; }
|
||||||
|
public Color Ambient { get; set; }
|
||||||
|
public Color Specular { get; set; }
|
||||||
|
public Color Emissive { get; set; }
|
||||||
|
public Color Reflection { get; set; }
|
||||||
|
public float Shininess { get; set; }
|
||||||
|
public float Transparency { get; set; }
|
||||||
|
public List<ImportedMaterialTexture> Textures { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedMaterialTexture
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Dest { get; set; }
|
||||||
|
public Vector2 Offset { get; set; }
|
||||||
|
public Vector2 Scale { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedTexture
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
|
||||||
|
public ImportedTexture(MemoryStream stream, string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Data = stream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedKeyframedAnimation
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public float SampleRate { get; set; }
|
||||||
|
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
|
||||||
|
|
||||||
|
public ImportedAnimationKeyframedTrack FindTrack(string path)
|
||||||
|
{
|
||||||
|
var track = TrackList.Find(x => x.Path == path);
|
||||||
|
if (track == null)
|
||||||
|
{
|
||||||
|
track = new ImportedAnimationKeyframedTrack { Path = path };
|
||||||
|
TrackList.Add(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedAnimationKeyframedTrack
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
|
||||||
|
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
|
||||||
|
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
|
||||||
|
public ImportedBlendShape BlendShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedKeyframe<T>
|
||||||
|
{
|
||||||
|
public float time { get; set; }
|
||||||
|
public T value { get; set; }
|
||||||
|
|
||||||
|
public ImportedKeyframe(float time, T value)
|
||||||
|
{
|
||||||
|
this.time = time;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedBlendShape
|
||||||
|
{
|
||||||
|
public string ChannelName;
|
||||||
|
public List<ImportedKeyframe<float>> Keyframes = new List<ImportedKeyframe<float>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedMorph
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public List<ImportedMorphChannel> Channels { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedMorphChannel
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedMorphKeyframe
|
||||||
|
{
|
||||||
|
public bool hasNormals { get; set; }
|
||||||
|
public bool hasTangents { get; set; }
|
||||||
|
public float Weight { get; set; }
|
||||||
|
public List<ImportedMorphVertex> VertexList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportedMorphVertex
|
||||||
|
{
|
||||||
|
public uint Index { get; set; }
|
||||||
|
public ImportedVertex Vertex { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ImportedHelpers
|
||||||
|
{
|
||||||
|
public static ImportedMesh FindMesh(string path, List<ImportedMesh> importedMeshList)
|
||||||
|
{
|
||||||
|
foreach (var mesh in importedMeshList)
|
||||||
|
{
|
||||||
|
if (mesh.Path == path)
|
||||||
|
{
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImportedMaterial FindMaterial(string name, List<ImportedMaterial> importedMats)
|
||||||
|
{
|
||||||
|
foreach (var mat in importedMats)
|
||||||
|
{
|
||||||
|
if (mat.Name == name)
|
||||||
|
{
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImportedTexture FindTexture(string name, List<ImportedTexture> importedTextureList)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var tex in importedTextureList)
|
||||||
|
{
|
||||||
|
if (tex.Name == name)
|
||||||
|
{
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
AssetStudio/ILogger.cs
Normal file
26
AssetStudio/ILogger.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public enum LoggerEvent
|
||||||
|
{
|
||||||
|
Verbose,
|
||||||
|
Debug,
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ILogger
|
||||||
|
{
|
||||||
|
void Log(LoggerEvent loggerEvent, string message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DummyLogger : ILogger
|
||||||
|
{
|
||||||
|
public void Log(LoggerEvent loggerEvent, string message) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
17
AssetStudio/IProgress.cs
Normal file
17
AssetStudio/IProgress.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public interface IProgress
|
||||||
|
{
|
||||||
|
void Report(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DummyProgress : IProgress
|
||||||
|
{
|
||||||
|
public void Report(int value) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
112
AssetStudio/ImportHelper.cs
Normal file
112
AssetStudio/ImportHelper.cs
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public enum FileType
|
||||||
|
{
|
||||||
|
AssetsFile,
|
||||||
|
BundleFile,
|
||||||
|
WebFile,
|
||||||
|
ResourceFile
|
||||||
|
}
|
||||||
|
|
||||||
|
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(20);
|
||||||
|
reader.Position = 0;
|
||||||
|
switch (signature)
|
||||||
|
{
|
||||||
|
case "UnityWeb":
|
||||||
|
case "UnityRaw":
|
||||||
|
case "UnityArchive":
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (SerializedFile.IsSerializedFile(reader))
|
||||||
|
{
|
||||||
|
return FileType.AssetsFile;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FileType.ResourceFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
AssetStudio/LocalSerializedObjectIdentifier.cs
Normal file
13
AssetStudio/LocalSerializedObjectIdentifier.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class LocalSerializedObjectIdentifier
|
||||||
|
{
|
||||||
|
public int localSerializedFileIndex;
|
||||||
|
public long localIdentifierInFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
AssetStudio/Logger.cs
Normal file
18
AssetStudio/Logger.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public static class Logger
|
||||||
|
{
|
||||||
|
public static ILogger Default = new DummyLogger();
|
||||||
|
|
||||||
|
public static void Verbose(string message) => Default.Log(LoggerEvent.Verbose, message);
|
||||||
|
public static void Debug(string message) => Default.Log(LoggerEvent.Debug, message);
|
||||||
|
public static void Info(string message) => Default.Log(LoggerEvent.Info, message);
|
||||||
|
public static void Warning(string message) => Default.Log(LoggerEvent.Warning, message);
|
||||||
|
public static void Error(string message) => Default.Log(LoggerEvent.Error, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
540
AssetStudio/Lz4DecoderStream.cs
Normal file
540
AssetStudio/Lz4DecoderStream.cs
Normal file
@@ -0,0 +1,540 @@
|
|||||||
|
#define CHECK_ARGS
|
||||||
|
#define CHECK_EOF
|
||||||
|
//#define LOCAL_SHADOW
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Lz4
|
||||||
|
{
|
||||||
|
public class Lz4DecoderStream : Stream
|
||||||
|
{
|
||||||
|
public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
|
||||||
|
{
|
||||||
|
Reset(input, inputLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Reset(Stream input, long inputLength = long.MaxValue)
|
||||||
|
{
|
||||||
|
this.inputLength = inputLength;
|
||||||
|
this.input = input;
|
||||||
|
|
||||||
|
phase = DecodePhase.ReadToken;
|
||||||
|
|
||||||
|
decodeBufferPos = 0;
|
||||||
|
|
||||||
|
litLen = 0;
|
||||||
|
matLen = 0;
|
||||||
|
matDst = 0;
|
||||||
|
|
||||||
|
inBufPos = DecBufLen;
|
||||||
|
inBufEnd = DecBufLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (disposing && input != null)
|
||||||
|
{
|
||||||
|
input.Close();
|
||||||
|
}
|
||||||
|
input = null;
|
||||||
|
decodeBuffer = null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long inputLength;
|
||||||
|
private Stream input;
|
||||||
|
|
||||||
|
//because we might not be able to match back across invocations,
|
||||||
|
//we have to keep the last window's worth of bytes around for reuse
|
||||||
|
//we use a circular buffer for this - every time we write into this
|
||||||
|
//buffer, we also write the same into our output buffer
|
||||||
|
|
||||||
|
private const int DecBufLen = 0x10000;
|
||||||
|
private const int DecBufMask = 0xFFFF;
|
||||||
|
|
||||||
|
private const int InBufLen = 128;
|
||||||
|
|
||||||
|
private byte[] decodeBuffer = new byte[DecBufLen + InBufLen];
|
||||||
|
private int decodeBufferPos, inBufPos, inBufEnd;
|
||||||
|
|
||||||
|
//we keep track of which phase we're in so that we can jump right back
|
||||||
|
//into the correct part of decoding
|
||||||
|
|
||||||
|
private DecodePhase phase;
|
||||||
|
|
||||||
|
private enum DecodePhase
|
||||||
|
{
|
||||||
|
ReadToken,
|
||||||
|
ReadExLiteralLength,
|
||||||
|
CopyLiteral,
|
||||||
|
ReadOffset,
|
||||||
|
ReadExMatchLength,
|
||||||
|
CopyMatch,
|
||||||
|
}
|
||||||
|
|
||||||
|
//state within interruptable phases and across phase boundaries is
|
||||||
|
//kept here - again, so that we can punt out and restart freely
|
||||||
|
|
||||||
|
private int litLen, matLen, matDst;
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
#if CHECK_ARGS
|
||||||
|
if (buffer == null)
|
||||||
|
throw new ArgumentNullException("buffer");
|
||||||
|
if (offset < 0 || count < 0 || buffer.Length - count < offset)
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|
||||||
|
if (input == null)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
#endif
|
||||||
|
int nRead, nToRead = count;
|
||||||
|
|
||||||
|
var decBuf = decodeBuffer;
|
||||||
|
|
||||||
|
//the stringy gotos are obnoxious, but their purpose is to
|
||||||
|
//make it *blindingly* obvious how the state machine transitions
|
||||||
|
//back and forth as it reads - remember, we can yield out of
|
||||||
|
//this routine in several places, and we must be able to re-enter
|
||||||
|
//and pick up where we left off!
|
||||||
|
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
var phase = this.phase;
|
||||||
|
var inBufPos = this.inBufPos;
|
||||||
|
var inBufEnd = this.inBufEnd;
|
||||||
|
#endif
|
||||||
|
switch (phase)
|
||||||
|
{
|
||||||
|
case DecodePhase.ReadToken:
|
||||||
|
goto readToken;
|
||||||
|
|
||||||
|
case DecodePhase.ReadExLiteralLength:
|
||||||
|
goto readExLiteralLength;
|
||||||
|
|
||||||
|
case DecodePhase.CopyLiteral:
|
||||||
|
goto copyLiteral;
|
||||||
|
|
||||||
|
case DecodePhase.ReadOffset:
|
||||||
|
goto readOffset;
|
||||||
|
|
||||||
|
case DecodePhase.ReadExMatchLength:
|
||||||
|
goto readExMatchLength;
|
||||||
|
|
||||||
|
case DecodePhase.CopyMatch:
|
||||||
|
goto copyMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
readToken:
|
||||||
|
int tok;
|
||||||
|
if (inBufPos < inBufEnd)
|
||||||
|
{
|
||||||
|
tok = decBuf[inBufPos++];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
this.inBufPos = inBufPos;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tok = ReadByteCore();
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
inBufPos = this.inBufPos;
|
||||||
|
inBufEnd = this.inBufEnd;
|
||||||
|
#endif
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (tok == -1)
|
||||||
|
goto finish;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
litLen = tok >> 4;
|
||||||
|
matLen = (tok & 0xF) + 4;
|
||||||
|
|
||||||
|
switch (litLen)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
phase = DecodePhase.ReadOffset;
|
||||||
|
goto readOffset;
|
||||||
|
|
||||||
|
case 0xF:
|
||||||
|
phase = DecodePhase.ReadExLiteralLength;
|
||||||
|
goto readExLiteralLength;
|
||||||
|
|
||||||
|
default:
|
||||||
|
phase = DecodePhase.CopyLiteral;
|
||||||
|
goto copyLiteral;
|
||||||
|
}
|
||||||
|
|
||||||
|
readExLiteralLength:
|
||||||
|
int exLitLen;
|
||||||
|
if (inBufPos < inBufEnd)
|
||||||
|
{
|
||||||
|
exLitLen = decBuf[inBufPos++];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
this.inBufPos = inBufPos;
|
||||||
|
#endif
|
||||||
|
exLitLen = ReadByteCore();
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
inBufPos = this.inBufPos;
|
||||||
|
inBufEnd = this.inBufEnd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (exLitLen == -1)
|
||||||
|
goto finish;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
litLen += exLitLen;
|
||||||
|
if (exLitLen == 255)
|
||||||
|
goto readExLiteralLength;
|
||||||
|
|
||||||
|
phase = DecodePhase.CopyLiteral;
|
||||||
|
goto copyLiteral;
|
||||||
|
|
||||||
|
copyLiteral:
|
||||||
|
int nReadLit = litLen < nToRead ? litLen : nToRead;
|
||||||
|
if (nReadLit != 0)
|
||||||
|
{
|
||||||
|
if (inBufPos + nReadLit <= inBufEnd)
|
||||||
|
{
|
||||||
|
int ofs = offset;
|
||||||
|
|
||||||
|
for (int c = nReadLit; c-- != 0;)
|
||||||
|
buffer[ofs++] = decBuf[inBufPos++];
|
||||||
|
|
||||||
|
nRead = nReadLit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
this.inBufPos = inBufPos;
|
||||||
|
#endif
|
||||||
|
nRead = ReadCore(buffer, offset, nReadLit);
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
inBufPos = this.inBufPos;
|
||||||
|
inBufEnd = this.inBufEnd;
|
||||||
|
#endif
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (nRead == 0)
|
||||||
|
goto finish;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += nRead;
|
||||||
|
nToRead -= nRead;
|
||||||
|
|
||||||
|
litLen -= nRead;
|
||||||
|
|
||||||
|
if (litLen != 0)
|
||||||
|
goto copyLiteral;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nToRead == 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
phase = DecodePhase.ReadOffset;
|
||||||
|
goto readOffset;
|
||||||
|
|
||||||
|
readOffset:
|
||||||
|
if (inBufPos + 1 < inBufEnd)
|
||||||
|
{
|
||||||
|
matDst = (decBuf[inBufPos + 1] << 8) | decBuf[inBufPos];
|
||||||
|
inBufPos += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
this.inBufPos = inBufPos;
|
||||||
|
#endif
|
||||||
|
matDst = ReadOffsetCore();
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
inBufPos = this.inBufPos;
|
||||||
|
inBufEnd = this.inBufEnd;
|
||||||
|
#endif
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (matDst == -1)
|
||||||
|
goto finish;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matLen == 15 + 4)
|
||||||
|
{
|
||||||
|
phase = DecodePhase.ReadExMatchLength;
|
||||||
|
goto readExMatchLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phase = DecodePhase.CopyMatch;
|
||||||
|
goto copyMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
readExMatchLength:
|
||||||
|
int exMatLen;
|
||||||
|
if (inBufPos < inBufEnd)
|
||||||
|
{
|
||||||
|
exMatLen = decBuf[inBufPos++];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
this.inBufPos = inBufPos;
|
||||||
|
#endif
|
||||||
|
exMatLen = ReadByteCore();
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
inBufPos = this.inBufPos;
|
||||||
|
inBufEnd = this.inBufEnd;
|
||||||
|
#endif
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (exMatLen == -1)
|
||||||
|
goto finish;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
matLen += exMatLen;
|
||||||
|
if (exMatLen == 255)
|
||||||
|
goto readExMatchLength;
|
||||||
|
|
||||||
|
phase = DecodePhase.CopyMatch;
|
||||||
|
goto copyMatch;
|
||||||
|
|
||||||
|
copyMatch:
|
||||||
|
int nCpyMat = matLen < nToRead ? matLen : nToRead;
|
||||||
|
if (nCpyMat != 0)
|
||||||
|
{
|
||||||
|
nRead = count - nToRead;
|
||||||
|
|
||||||
|
int bufDst = matDst - nRead;
|
||||||
|
if (bufDst > 0)
|
||||||
|
{
|
||||||
|
//offset is fairly far back, we need to pull from the buffer
|
||||||
|
|
||||||
|
int bufSrc = decodeBufferPos - bufDst;
|
||||||
|
if (bufSrc < 0)
|
||||||
|
bufSrc += DecBufLen;
|
||||||
|
int bufCnt = bufDst < nCpyMat ? bufDst : nCpyMat;
|
||||||
|
|
||||||
|
for (int c = bufCnt; c-- != 0;)
|
||||||
|
buffer[offset++] = decBuf[bufSrc++ & DecBufMask];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bufDst = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sOfs = offset - matDst;
|
||||||
|
for (int i = bufDst; i < nCpyMat; i++)
|
||||||
|
buffer[offset++] = buffer[sOfs++];
|
||||||
|
|
||||||
|
nToRead -= nCpyMat;
|
||||||
|
matLen -= nCpyMat;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nToRead == 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
phase = DecodePhase.ReadToken;
|
||||||
|
goto readToken;
|
||||||
|
|
||||||
|
finish:
|
||||||
|
nRead = count - nToRead;
|
||||||
|
|
||||||
|
int nToBuf = nRead < DecBufLen ? nRead : DecBufLen;
|
||||||
|
int repPos = offset - nToBuf;
|
||||||
|
|
||||||
|
if (nToBuf == DecBufLen)
|
||||||
|
{
|
||||||
|
Buffer.BlockCopy(buffer, repPos, decBuf, 0, DecBufLen);
|
||||||
|
decodeBufferPos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int decPos = decodeBufferPos;
|
||||||
|
|
||||||
|
while (nToBuf-- != 0)
|
||||||
|
decBuf[decPos++ & DecBufMask] = buffer[repPos++];
|
||||||
|
|
||||||
|
decodeBufferPos = decPos & DecBufMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LOCAL_SHADOW
|
||||||
|
this.phase = phase;
|
||||||
|
this.inBufPos = inBufPos;
|
||||||
|
#endif
|
||||||
|
return nRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ReadByteCore()
|
||||||
|
{
|
||||||
|
var buf = decodeBuffer;
|
||||||
|
|
||||||
|
if (inBufPos == inBufEnd)
|
||||||
|
{
|
||||||
|
int nRead = input.Read(buf, DecBufLen,
|
||||||
|
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||||
|
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (nRead == 0)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inputLength -= nRead;
|
||||||
|
|
||||||
|
inBufPos = DecBufLen;
|
||||||
|
inBufEnd = DecBufLen + nRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf[inBufPos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ReadOffsetCore()
|
||||||
|
{
|
||||||
|
var buf = decodeBuffer;
|
||||||
|
|
||||||
|
if (inBufPos == inBufEnd)
|
||||||
|
{
|
||||||
|
int nRead = input.Read(buf, DecBufLen,
|
||||||
|
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||||
|
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (nRead == 0)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inputLength -= nRead;
|
||||||
|
|
||||||
|
inBufPos = DecBufLen;
|
||||||
|
inBufEnd = DecBufLen + nRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inBufEnd - inBufPos == 1)
|
||||||
|
{
|
||||||
|
buf[DecBufLen] = buf[inBufPos];
|
||||||
|
|
||||||
|
int nRead = input.Read(buf, DecBufLen + 1,
|
||||||
|
InBufLen - 1 < inputLength ? InBufLen - 1 : (int)inputLength);
|
||||||
|
|
||||||
|
#if CHECK_EOF
|
||||||
|
if (nRead == 0)
|
||||||
|
{
|
||||||
|
inBufPos = DecBufLen;
|
||||||
|
inBufEnd = DecBufLen + 1;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inputLength -= nRead;
|
||||||
|
|
||||||
|
inBufPos = DecBufLen;
|
||||||
|
inBufEnd = DecBufLen + nRead + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = (buf[inBufPos + 1] << 8) | buf[inBufPos];
|
||||||
|
inBufPos += 2;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ReadCore(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
int nToRead = count;
|
||||||
|
|
||||||
|
var buf = decodeBuffer;
|
||||||
|
int inBufLen = inBufEnd - inBufPos;
|
||||||
|
|
||||||
|
int fromBuf = nToRead < inBufLen ? nToRead : inBufLen;
|
||||||
|
if (fromBuf != 0)
|
||||||
|
{
|
||||||
|
var bufPos = inBufPos;
|
||||||
|
|
||||||
|
for (int c = fromBuf; c-- != 0;)
|
||||||
|
buffer[offset++] = buf[bufPos++];
|
||||||
|
|
||||||
|
inBufPos = bufPos;
|
||||||
|
nToRead -= fromBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nToRead != 0)
|
||||||
|
{
|
||||||
|
int nRead;
|
||||||
|
|
||||||
|
if (nToRead >= InBufLen)
|
||||||
|
{
|
||||||
|
nRead = input.Read(buffer, offset,
|
||||||
|
nToRead < inputLength ? nToRead : (int)inputLength);
|
||||||
|
nToRead -= nRead;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nRead = input.Read(buf, DecBufLen,
|
||||||
|
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||||
|
|
||||||
|
inBufPos = DecBufLen;
|
||||||
|
inBufEnd = DecBufLen + nRead;
|
||||||
|
|
||||||
|
fromBuf = nToRead < nRead ? nToRead : nRead;
|
||||||
|
|
||||||
|
var bufPos = inBufPos;
|
||||||
|
|
||||||
|
for (int c = fromBuf; c-- != 0;)
|
||||||
|
buffer[offset++] = buf[bufPos++];
|
||||||
|
|
||||||
|
inBufPos = bufPos;
|
||||||
|
nToRead -= fromBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputLength -= nRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count - nToRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Stream internals
|
||||||
|
|
||||||
|
public override bool CanRead => true;
|
||||||
|
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Length => throw new NotSupportedException();
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get => throw new NotSupportedException();
|
||||||
|
set => throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
84
AssetStudio/Math/Color.cs
Normal file
84
AssetStudio/Math/Color.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
|
public struct Color : IEquatable<Color>
|
||||||
|
{
|
||||||
|
public float R;
|
||||||
|
public float G;
|
||||||
|
public float B;
|
||||||
|
public float A;
|
||||||
|
|
||||||
|
public Color(float r, float g, float b, float a)
|
||||||
|
{
|
||||||
|
R = r;
|
||||||
|
G = g;
|
||||||
|
B = b;
|
||||||
|
A = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ((Vector4)this).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (!(other is Color))
|
||||||
|
return false;
|
||||||
|
return Equals((Color)other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Color other)
|
||||||
|
{
|
||||||
|
return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color operator +(Color a, Color b)
|
||||||
|
{
|
||||||
|
return new Color(a.R + b.R, a.G + b.G, a.B + b.B, a.A + b.A);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color operator -(Color a, Color b)
|
||||||
|
{
|
||||||
|
return new Color(a.R - b.R, a.G - b.G, a.B - b.B, a.A - b.A);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color operator *(Color a, Color b)
|
||||||
|
{
|
||||||
|
return new Color(a.R * b.R, a.G * b.G, a.B * b.B, a.A * b.A);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color operator *(Color a, float b)
|
||||||
|
{
|
||||||
|
return new Color(a.R * b, a.G * b, a.B * b, a.A * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color operator *(float b, Color a)
|
||||||
|
{
|
||||||
|
return new Color(a.R * b, a.G * b, a.B * b, a.A * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color operator /(Color a, float b)
|
||||||
|
{
|
||||||
|
return new Color(a.R / b, a.G / b, a.B / b, a.A / b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Color lhs, Color rhs)
|
||||||
|
{
|
||||||
|
return (Vector4)lhs == (Vector4)rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Color lhs, Color rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Vector4(Color c)
|
||||||
|
{
|
||||||
|
return new Vector4(c.R, c.G, c.B, c.A);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
888
AssetStudio/Math/Half.cs
Normal file
888
AssetStudio/Math/Half.cs
Normal file
@@ -0,0 +1,888 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace System
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a half-precision floating point number.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Note:
|
||||||
|
/// Half is not fast enought and precision is also very bad,
|
||||||
|
/// so is should not be used for matemathical computation (use Single instead).
|
||||||
|
/// The main advantage of Half type is lower memory cost: two bytes per number.
|
||||||
|
/// Half is typically used in graphical applications.
|
||||||
|
///
|
||||||
|
/// Note:
|
||||||
|
/// All functions, where is used conversion half->float/float->half,
|
||||||
|
/// are approx. ten times slower than float->double/double->float, i.e. ~3ns on 2GHz CPU.
|
||||||
|
///
|
||||||
|
/// References:
|
||||||
|
/// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
|
||||||
|
/// - IEEE 754 revision, link: http://grouper.ieee.org/groups/754/
|
||||||
|
/// </remarks>
|
||||||
|
[Serializable]
|
||||||
|
public struct Half : IComparable, IFormattable, IConvertible, IComparable<Half>, IEquatable<Half>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Internal representation of the half-precision floating-point number.
|
||||||
|
/// </summary>
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||||
|
internal ushort value;
|
||||||
|
|
||||||
|
#region Constants
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the smallest positive System.Half value greater than zero. This field is constant.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Half Epsilon = Half.ToHalf(0x0001);
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the largest possible value of System.Half. This field is constant.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Half MaxValue = Half.ToHalf(0x7bff);
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the smallest possible value of System.Half. This field is constant.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Half MinValue = Half.ToHalf(0xfbff);
|
||||||
|
/// <summary>
|
||||||
|
/// Represents not a number (NaN). This field is constant.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Half NaN = Half.ToHalf(0xfe00);
|
||||||
|
/// <summary>
|
||||||
|
/// Represents negative infinity. This field is constant.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Half NegativeInfinity = Half.ToHalf(0xfc00);
|
||||||
|
/// <summary>
|
||||||
|
/// Represents positive infinity. This field is constant.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Half PositiveInfinity = Half.ToHalf(0x7c00);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of System.Half to the value of the specified single-precision floating-point number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
|
public Half(float value) { this = HalfHelper.SingleToHalf(value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of System.Half to the value of the specified 32-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
|
public Half(int value) : this((float)value) { }
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of System.Half to the value of the specified 64-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
|
public Half(long value) : this((float)value) { }
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of System.Half to the value of the specified double-precision floating-point number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
|
public Half(double value) : this((float)value) { }
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of System.Half to the value of the specified decimal number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
|
public Half(decimal value) : this((float)value) { }
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of System.Half to the value of the specified 32-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
|
public Half(uint value) : this((float)value) { }
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of System.Half to the value of the specified 64-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to represent as a System.Half.</param>
|
||||||
|
public Half(ulong value) : this((float)value) { }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Numeric operators
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the result of multiplying the specified System.Half value by negative one.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">A System.Half.</param>
|
||||||
|
/// <returns>A System.Half with the value of half, but the opposite sign. -or- Zero, if half is zero.</returns>
|
||||||
|
public static Half Negate(Half half) { return -half; }
|
||||||
|
/// <summary>
|
||||||
|
/// Adds two specified System.Half values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>A System.Half value that is the sum of half1 and half2.</returns>
|
||||||
|
public static Half Add(Half half1, Half half2) { return half1 + half2; }
|
||||||
|
/// <summary>
|
||||||
|
/// Subtracts one specified System.Half value from another.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half (the minuend).</param>
|
||||||
|
/// <param name="half2">A System.Half (the subtrahend).</param>
|
||||||
|
/// <returns>The System.Half result of subtracting half2 from half1.</returns>
|
||||||
|
public static Half Subtract(Half half1, Half half2) { return half1 - half2; }
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplies two specified System.Half values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half (the multiplicand).</param>
|
||||||
|
/// <param name="half2">A System.Half (the multiplier).</param>
|
||||||
|
/// <returns>A System.Half that is the result of multiplying half1 and half2.</returns>
|
||||||
|
public static Half Multiply(Half half1, Half half2) { return half1 * half2; }
|
||||||
|
/// <summary>
|
||||||
|
/// Divides two specified System.Half values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half (the dividend).</param>
|
||||||
|
/// <param name="half2">A System.Half (the divisor).</param>
|
||||||
|
/// <returns>The System.Half that is the result of dividing half1 by half2.</returns>
|
||||||
|
/// <exception cref="System.DivideByZeroException">half2 is zero.</exception>
|
||||||
|
public static Half Divide(Half half1, Half half2) { return half1 / half2; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value of the System.Half operand (the sign of the operand is unchanged).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">The System.Half operand.</param>
|
||||||
|
/// <returns>The value of the operand, half.</returns>
|
||||||
|
public static Half operator +(Half half) { return half; }
|
||||||
|
/// <summary>
|
||||||
|
/// Negates the value of the specified System.Half operand.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">The System.Half operand.</param>
|
||||||
|
/// <returns>The result of half multiplied by negative one (-1).</returns>
|
||||||
|
public static Half operator -(Half half) { return HalfHelper.Negate(half); }
|
||||||
|
/// <summary>
|
||||||
|
/// Increments the System.Half operand by 1.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">The System.Half operand.</param>
|
||||||
|
/// <returns>The value of half incremented by 1.</returns>
|
||||||
|
public static Half operator ++(Half half) { return (Half)(half + 1f); }
|
||||||
|
/// <summary>
|
||||||
|
/// Decrements the System.Half operand by one.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">The System.Half operand.</param>
|
||||||
|
/// <returns>The value of half decremented by 1.</returns>
|
||||||
|
public static Half operator --(Half half) { return (Half)(half - 1f); }
|
||||||
|
/// <summary>
|
||||||
|
/// Adds two specified System.Half values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>The System.Half result of adding half1 and half2.</returns>
|
||||||
|
public static Half operator +(Half half1, Half half2) { return (Half)((float)half1 + (float)half2); }
|
||||||
|
/// <summary>
|
||||||
|
/// Subtracts two specified System.Half values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>The System.Half result of subtracting half1 and half2.</returns>
|
||||||
|
public static Half operator -(Half half1, Half half2) { return (Half)((float)half1 - (float)half2); }
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplies two specified System.Half values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>The System.Half result of multiplying half1 by half2.</returns>
|
||||||
|
public static Half operator *(Half half1, Half half2) { return (Half)((float)half1 * (float)half2); }
|
||||||
|
/// <summary>
|
||||||
|
/// Divides two specified System.Half values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half (the dividend).</param>
|
||||||
|
/// <param name="half2">A System.Half (the divisor).</param>
|
||||||
|
/// <returns>The System.Half result of half1 by half2.</returns>
|
||||||
|
public static Half operator /(Half half1, Half half2) { return (Half)((float)half1 / (float)half2); }
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether two instances of System.Half are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>true if half1 and half2 are equal; otherwise, false.</returns>
|
||||||
|
public static bool operator ==(Half half1, Half half2) { return (!IsNaN(half1) && (half1.value == half2.value)); }
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether two instances of System.Half are not equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>true if half1 and half2 are not equal; otherwise, false.</returns>
|
||||||
|
public static bool operator !=(Half half1, Half half2) { return !(half1.value == half2.value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether a specified System.Half is less than another specified System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>true if half1 is less than half1; otherwise, false.</returns>
|
||||||
|
public static bool operator <(Half half1, Half half2) { return (float)half1 < (float)half2; }
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether a specified System.Half is greater than another specified System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>true if half1 is greater than half2; otherwise, false.</returns>
|
||||||
|
public static bool operator >(Half half1, Half half2) { return (float)half1 > (float)half2; }
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether a specified System.Half is less than or equal to another specified System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>true if half1 is less than or equal to half2; otherwise, false.</returns>
|
||||||
|
public static bool operator <=(Half half1, Half half2) { return (half1 == half2) || (half1 < half2); }
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether a specified System.Half is greater than or equal to another specified System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half1">A System.Half.</param>
|
||||||
|
/// <param name="half2">A System.Half.</param>
|
||||||
|
/// <returns>true if half1 is greater than or equal to half2; otherwise, false.</returns>
|
||||||
|
public static bool operator >=(Half half1, Half half2) { return (half1 == half2) || (half1 > half2); }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Type casting operators
|
||||||
|
/// <summary>
|
||||||
|
/// Converts an 8-bit unsigned integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">An 8-bit unsigned integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 8-bit unsigned integer.</returns>
|
||||||
|
public static implicit operator Half(byte value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a 16-bit signed integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A 16-bit signed integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 16-bit signed integer.</returns>
|
||||||
|
public static implicit operator Half(short value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a Unicode character to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A Unicode character.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted Unicode character.</returns>
|
||||||
|
public static implicit operator Half(char value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a 32-bit signed integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A 32-bit signed integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 32-bit signed integer.</returns>
|
||||||
|
public static implicit operator Half(int value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a 64-bit signed integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A 64-bit signed integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 64-bit signed integer.</returns>
|
||||||
|
public static implicit operator Half(long value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a single-precision floating-point number to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A single-precision floating-point number.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted single-precision floating point number.</returns>
|
||||||
|
public static explicit operator Half(float value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a double-precision floating-point number to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A double-precision floating-point number.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted double-precision floating point number.</returns>
|
||||||
|
public static explicit operator Half(double value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a decimal number to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">decimal number</param>
|
||||||
|
/// <returns>A System.Half that represents the converted decimal number.</returns>
|
||||||
|
public static explicit operator Half(decimal value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to an 8-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>An 8-bit unsigned integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator byte(Half value) { return (byte)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a Unicode character.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A Unicode character that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator char(Half value) { return (char)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a 16-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A 16-bit signed integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator short(Half value) { return (short)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a 32-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A 32-bit signed integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator int(Half value) { return (int)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a 64-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A 64-bit signed integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator long(Half value) { return (long)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a single-precision floating-point number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A single-precision floating-point number that represents the converted System.Half.</returns>
|
||||||
|
public static implicit operator float(Half value) { return (float)HalfHelper.HalfToSingle(value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a double-precision floating-point number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A double-precision floating-point number that represents the converted System.Half.</returns>
|
||||||
|
public static implicit operator double(Half value) { return (double)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a decimal number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A decimal number that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator decimal(Half value) { return (decimal)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts an 8-bit signed integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">An 8-bit signed integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 8-bit signed integer.</returns>
|
||||||
|
public static implicit operator Half(sbyte value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a 16-bit unsigned integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A 16-bit unsigned integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 16-bit unsigned integer.</returns>
|
||||||
|
public static implicit operator Half(ushort value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a 32-bit unsigned integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A 32-bit unsigned integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 32-bit unsigned integer.</returns>
|
||||||
|
public static implicit operator Half(uint value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a 64-bit unsigned integer to a System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A 64-bit unsigned integer.</param>
|
||||||
|
/// <returns>A System.Half that represents the converted 64-bit unsigned integer.</returns>
|
||||||
|
public static implicit operator Half(ulong value) { return new Half((float)value); }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to an 8-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>An 8-bit signed integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator sbyte(Half value) { return (sbyte)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a 16-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A 16-bit unsigned integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator ushort(Half value) { return (ushort)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a 32-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A 32-bit unsigned integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator uint(Half value) { return (uint)(float)value; }
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a System.Half to a 64-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half to convert.</param>
|
||||||
|
/// <returns>A 64-bit unsigned integer that represents the converted System.Half.</returns>
|
||||||
|
public static explicit operator ulong(Half value) { return (ulong)(float)value; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares this instance to a specified System.Half object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">A System.Half object.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A signed number indicating the relative values of this instance and value.
|
||||||
|
/// Return Value Meaning Less than zero This instance is less than value. Zero
|
||||||
|
/// This instance is equal to value. Greater than zero This instance is greater than value.
|
||||||
|
/// </returns>
|
||||||
|
public int CompareTo(Half other)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (this < other)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
else if (this > other)
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
else if (this != other)
|
||||||
|
{
|
||||||
|
if (!IsNaN(this))
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
else if (!IsNaN(other))
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Compares this instance to a specified System.Object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">An System.Object or null.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A signed number indicating the relative values of this instance and value.
|
||||||
|
/// Return Value Meaning Less than zero This instance is less than value. Zero
|
||||||
|
/// This instance is equal to value. Greater than zero This instance is greater
|
||||||
|
/// than value. -or- value is null.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="System.ArgumentException">value is not a System.Half</exception>
|
||||||
|
public int CompareTo(object obj)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (obj is Half)
|
||||||
|
{
|
||||||
|
result = CompareTo((Half)obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Object must be of type Half.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether this instance and a specified System.Half object represent the same value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">A System.Half object to compare to this instance.</param>
|
||||||
|
/// <returns>true if value is equal to this instance; otherwise, false.</returns>
|
||||||
|
public bool Equals(Half other)
|
||||||
|
{
|
||||||
|
return ((other == this) || (IsNaN(other) && IsNaN(this)));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether this instance and a specified System.Object
|
||||||
|
/// represent the same type and value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">An System.Object.</param>
|
||||||
|
/// <returns>true if value is a System.Half and equal to this instance; otherwise, false.</returns>
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (obj is Half)
|
||||||
|
{
|
||||||
|
Half half = (Half)obj;
|
||||||
|
if ((half == this) || (IsNaN(half) && IsNaN(this)))
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the hash code for this instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return value.GetHashCode();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the System.TypeCode for value type System.Half.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The enumerated constant (TypeCode)255.</returns>
|
||||||
|
public TypeCode GetTypeCode()
|
||||||
|
{
|
||||||
|
return (TypeCode)255;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region BitConverter & Math methods for Half
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the specified half-precision floating point value as an array of bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The number to convert.</param>
|
||||||
|
/// <returns>An array of bytes with length 2.</returns>
|
||||||
|
public static byte[] GetBytes(Half value)
|
||||||
|
{
|
||||||
|
return BitConverter.GetBytes(value.value);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the value of a specified instance of System.Half to its equivalent binary representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A System.Half value.</param>
|
||||||
|
/// <returns>A 16-bit unsigned integer that contain the binary representation of value.</returns>
|
||||||
|
public static ushort GetBits(Half value)
|
||||||
|
{
|
||||||
|
return value.value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a half-precision floating point number converted from two bytes
|
||||||
|
/// at a specified position in a byte array.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">An array of bytes.</param>
|
||||||
|
/// <param name="startIndex">The starting position within value.</param>
|
||||||
|
/// <returns>A half-precision floating point number formed by two bytes beginning at startIndex.</returns>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// startIndex is greater than or equal to the length of value minus 1, and is
|
||||||
|
/// less than or equal to the length of value minus 1.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception>
|
||||||
|
public static Half ToHalf(byte[] value, int startIndex)
|
||||||
|
{
|
||||||
|
return Half.ToHalf((ushort)BitConverter.ToInt16(value, startIndex));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a half-precision floating point number converted from its binary representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bits">Binary representation of System.Half value</param>
|
||||||
|
/// <returns>A half-precision floating point number formed by its binary representation.</returns>
|
||||||
|
public static Half ToHalf(ushort bits)
|
||||||
|
{
|
||||||
|
return new Half { value = bits };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating the sign of a half-precision floating-point number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A signed number.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A number indicating the sign of value. Number Description -1 value is less
|
||||||
|
/// than zero. 0 value is equal to zero. 1 value is greater than zero.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="System.ArithmeticException">value is equal to System.Half.NaN.</exception>
|
||||||
|
public static int Sign(Half value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (value > 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
throw new ArithmeticException("Function does not accept floating point Not-a-Number values.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the absolute value of a half-precision floating-point number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">A number in the range System.Half.MinValue ≤ value ≤ System.Half.MaxValue.</param>
|
||||||
|
/// <returns>A half-precision floating-point number, x, such that 0 ≤ x ≤System.Half.MaxValue.</returns>
|
||||||
|
public static Half Abs(Half value)
|
||||||
|
{
|
||||||
|
return HalfHelper.Abs(value);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the larger of two half-precision floating-point numbers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value1">The first of two half-precision floating-point numbers to compare.</param>
|
||||||
|
/// <param name="value2">The second of two half-precision floating-point numbers to compare.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Parameter value1 or value2, whichever is larger. If value1, or value2, or both val1
|
||||||
|
/// and value2 are equal to System.Half.NaN, System.Half.NaN is returned.
|
||||||
|
/// </returns>
|
||||||
|
public static Half Max(Half value1, Half value2)
|
||||||
|
{
|
||||||
|
return (value1 < value2) ? value2 : value1;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the smaller of two half-precision floating-point numbers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value1">The first of two half-precision floating-point numbers to compare.</param>
|
||||||
|
/// <param name="value2">The second of two half-precision floating-point numbers to compare.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Parameter value1 or value2, whichever is smaller. If value1, or value2, or both val1
|
||||||
|
/// and value2 are equal to System.Half.NaN, System.Half.NaN is returned.
|
||||||
|
/// </returns>
|
||||||
|
public static Half Min(Half value1, Half value2)
|
||||||
|
{
|
||||||
|
return (value1 < value2) ? value1 : value2;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified number evaluates to not a number (System.Half.NaN).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">A half-precision floating-point number.</param>
|
||||||
|
/// <returns>true if value evaluates to not a number (System.Half.NaN); otherwise, false.</returns>
|
||||||
|
public static bool IsNaN(Half half)
|
||||||
|
{
|
||||||
|
return HalfHelper.IsNaN(half);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified number evaluates to negative or positive infinity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">A half-precision floating-point number.</param>
|
||||||
|
/// <returns>true if half evaluates to System.Half.PositiveInfinity or System.Half.NegativeInfinity; otherwise, false.</returns>
|
||||||
|
public static bool IsInfinity(Half half)
|
||||||
|
{
|
||||||
|
return HalfHelper.IsInfinity(half);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified number evaluates to negative infinity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">A half-precision floating-point number.</param>
|
||||||
|
/// <returns>true if half evaluates to System.Half.NegativeInfinity; otherwise, false.</returns>
|
||||||
|
public static bool IsNegativeInfinity(Half half)
|
||||||
|
{
|
||||||
|
return HalfHelper.IsNegativeInfinity(half);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified number evaluates to positive infinity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="half">A half-precision floating-point number.</param>
|
||||||
|
/// <returns>true if half evaluates to System.Half.PositiveInfinity; otherwise, false.</returns>
|
||||||
|
public static bool IsPositiveInfinity(Half half)
|
||||||
|
{
|
||||||
|
return HalfHelper.IsPositiveInfinity(half);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region String operations (Parse and ToString)
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a number to its System.Half equivalent.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string representation of the number to convert.</param>
|
||||||
|
/// <returns>The System.Half number equivalent to the number contained in value.</returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||||
|
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
|
||||||
|
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
|
||||||
|
public static Half Parse(string value)
|
||||||
|
{
|
||||||
|
return (Half)float.Parse(value, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a number to its System.Half equivalent
|
||||||
|
/// using the specified culture-specific format information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string representation of the number to convert.</param>
|
||||||
|
/// <param name="provider">An System.IFormatProvider that supplies culture-specific parsing information about value.</param>
|
||||||
|
/// <returns>The System.Half number equivalent to the number contained in s as specified by provider.</returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||||
|
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
|
||||||
|
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
|
||||||
|
public static Half Parse(string value, IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return (Half)float.Parse(value, provider);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a number in a specified style to its System.Half equivalent.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string representation of the number to convert.</param>
|
||||||
|
/// <param name="style">
|
||||||
|
/// A bitwise combination of System.Globalization.NumberStyles values that indicates
|
||||||
|
/// the style elements that can be present in value. A typical value to specify is
|
||||||
|
/// System.Globalization.NumberStyles.Number.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The System.Half number equivalent to the number contained in s as specified by style.</returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// style is not a System.Globalization.NumberStyles value. -or- style is the
|
||||||
|
/// System.Globalization.NumberStyles.AllowHexSpecifier value.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
|
||||||
|
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
|
||||||
|
public static Half Parse(string value, NumberStyles style)
|
||||||
|
{
|
||||||
|
return (Half)float.Parse(value, style, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a number to its System.Half equivalent
|
||||||
|
/// using the specified style and culture-specific format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string representation of the number to convert.</param>
|
||||||
|
/// <param name="style">
|
||||||
|
/// A bitwise combination of System.Globalization.NumberStyles values that indicates
|
||||||
|
/// the style elements that can be present in value. A typical value to specify is
|
||||||
|
/// System.Globalization.NumberStyles.Number.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="provider">An System.IFormatProvider object that supplies culture-specific information about the format of value.</param>
|
||||||
|
/// <returns>The System.Half number equivalent to the number contained in s as specified by style and provider.</returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value is null.</exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// style is not a System.Globalization.NumberStyles value. -or- style is the
|
||||||
|
/// System.Globalization.NumberStyles.AllowHexSpecifier value.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
|
||||||
|
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
|
||||||
|
public static Half Parse(string value, NumberStyles style, IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return (Half)float.Parse(value, style, provider);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a number to its System.Half equivalent.
|
||||||
|
/// A return value indicates whether the conversion succeeded or failed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string representation of the number to convert.</param>
|
||||||
|
/// <param name="result">
|
||||||
|
/// When this method returns, contains the System.Half number that is equivalent
|
||||||
|
/// to the numeric value contained in value, if the conversion succeeded, or is zero
|
||||||
|
/// if the conversion failed. The conversion fails if the s parameter is null,
|
||||||
|
/// is not a number in a valid format, or represents a number less than System.Half.MinValue
|
||||||
|
/// or greater than System.Half.MaxValue. This parameter is passed uninitialized.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>true if s was converted successfully; otherwise, false.</returns>
|
||||||
|
public static bool TryParse(string value, out Half result)
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
if (float.TryParse(value, out f))
|
||||||
|
{
|
||||||
|
result = (Half)f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = new Half();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a number to its System.Half equivalent
|
||||||
|
/// using the specified style and culture-specific format. A return value indicates
|
||||||
|
/// whether the conversion succeeded or failed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The string representation of the number to convert.</param>
|
||||||
|
/// <param name="style">
|
||||||
|
/// A bitwise combination of System.Globalization.NumberStyles values that indicates
|
||||||
|
/// the permitted format of value. A typical value to specify is System.Globalization.NumberStyles.Number.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="provider">An System.IFormatProvider object that supplies culture-specific parsing information about value.</param>
|
||||||
|
/// <param name="result">
|
||||||
|
/// When this method returns, contains the System.Half number that is equivalent
|
||||||
|
/// to the numeric value contained in value, if the conversion succeeded, or is zero
|
||||||
|
/// if the conversion failed. The conversion fails if the s parameter is null,
|
||||||
|
/// is not in a format compliant with style, or represents a number less than
|
||||||
|
/// System.Half.MinValue or greater than System.Half.MaxValue. This parameter is passed uninitialized.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>true if s was converted successfully; otherwise, false.</returns>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// style is not a System.Globalization.NumberStyles value. -or- style
|
||||||
|
/// is the System.Globalization.NumberStyles.AllowHexSpecifier value.
|
||||||
|
/// </exception>
|
||||||
|
public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out Half result)
|
||||||
|
{
|
||||||
|
bool parseResult = false;
|
||||||
|
float f;
|
||||||
|
if (float.TryParse(value, style, provider, out f))
|
||||||
|
{
|
||||||
|
result = (Half)f;
|
||||||
|
parseResult = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = new Half();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseResult;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the numeric value of this instance to its equivalent string representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string that represents the value of this instance.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return ((float)this).ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the numeric value of this instance to its equivalent string representation
|
||||||
|
/// using the specified culture-specific format information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="formatProvider">An System.IFormatProvider that supplies culture-specific formatting information.</param>
|
||||||
|
/// <returns>The string representation of the value of this instance as specified by provider.</returns>
|
||||||
|
public string ToString(IFormatProvider formatProvider)
|
||||||
|
{
|
||||||
|
return ((float)this).ToString(formatProvider);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the numeric value of this instance to its equivalent string representation, using the specified format.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">A numeric format string.</param>
|
||||||
|
/// <returns>The string representation of the value of this instance as specified by format.</returns>
|
||||||
|
public string ToString(string format)
|
||||||
|
{
|
||||||
|
return ((float)this).ToString(format, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the numeric value of this instance to its equivalent string representation
|
||||||
|
/// using the specified format and culture-specific format information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">A numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An System.IFormatProvider that supplies culture-specific formatting information.</param>
|
||||||
|
/// <returns>The string representation of the value of this instance as specified by format and provider.</returns>
|
||||||
|
/// <exception cref="System.FormatException">format is invalid.</exception>
|
||||||
|
public string ToString(string format, IFormatProvider formatProvider)
|
||||||
|
{
|
||||||
|
return ((float)this).ToString(format, formatProvider);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IConvertible Members
|
||||||
|
float IConvertible.ToSingle(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return (float)this;
|
||||||
|
}
|
||||||
|
TypeCode IConvertible.GetTypeCode()
|
||||||
|
{
|
||||||
|
return GetTypeCode();
|
||||||
|
}
|
||||||
|
bool IConvertible.ToBoolean(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToBoolean((float)this);
|
||||||
|
}
|
||||||
|
byte IConvertible.ToByte(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToByte((float)this);
|
||||||
|
}
|
||||||
|
char IConvertible.ToChar(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, "Invalid cast from '{0}' to '{1}'.", "Half", "Char"));
|
||||||
|
}
|
||||||
|
DateTime IConvertible.ToDateTime(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, "Invalid cast from '{0}' to '{1}'.", "Half", "DateTime"));
|
||||||
|
}
|
||||||
|
decimal IConvertible.ToDecimal(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToDecimal((float)this);
|
||||||
|
}
|
||||||
|
double IConvertible.ToDouble(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToDouble((float)this);
|
||||||
|
}
|
||||||
|
short IConvertible.ToInt16(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToInt16((float)this);
|
||||||
|
}
|
||||||
|
int IConvertible.ToInt32(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32((float)this);
|
||||||
|
}
|
||||||
|
long IConvertible.ToInt64(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToInt64((float)this);
|
||||||
|
}
|
||||||
|
sbyte IConvertible.ToSByte(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToSByte((float)this);
|
||||||
|
}
|
||||||
|
string IConvertible.ToString(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToString((float)this, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return (((float)this) as IConvertible).ToType(conversionType, provider);
|
||||||
|
}
|
||||||
|
ushort IConvertible.ToUInt16(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt16((float)this);
|
||||||
|
}
|
||||||
|
uint IConvertible.ToUInt32(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt32((float)this);
|
||||||
|
}
|
||||||
|
ulong IConvertible.ToUInt64(IFormatProvider provider)
|
||||||
|
{
|
||||||
|
return Convert.ToUInt64((float)this);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
211
AssetStudio/Math/HalfHelper.cs
Normal file
211
AssetStudio/Math/HalfHelper.cs
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace System
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class for Half conversions and some low level operations.
|
||||||
|
/// This class is internally used in the Half class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// References:
|
||||||
|
/// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
|
||||||
|
/// </remarks>
|
||||||
|
[ComVisible(false)]
|
||||||
|
internal static class HalfHelper
|
||||||
|
{
|
||||||
|
private static uint[] mantissaTable = GenerateMantissaTable();
|
||||||
|
private static uint[] exponentTable = GenerateExponentTable();
|
||||||
|
private static ushort[] offsetTable = GenerateOffsetTable();
|
||||||
|
private static ushort[] baseTable = GenerateBaseTable();
|
||||||
|
private static sbyte[] shiftTable = GenerateShiftTable();
|
||||||
|
|
||||||
|
// Transforms the subnormal representation to a normalized one.
|
||||||
|
private static uint ConvertMantissa(int i)
|
||||||
|
{
|
||||||
|
uint m = (uint)(i << 13); // Zero pad mantissa bits
|
||||||
|
uint e = 0; // Zero exponent
|
||||||
|
|
||||||
|
// While not normalized
|
||||||
|
while ((m & 0x00800000) == 0)
|
||||||
|
{
|
||||||
|
e -= 0x00800000; // Decrement exponent (1<<23)
|
||||||
|
m <<= 1; // Shift mantissa
|
||||||
|
}
|
||||||
|
m &= unchecked((uint)~0x00800000); // Clear leading 1 bit
|
||||||
|
e += 0x38800000; // Adjust bias ((127-14)<<23)
|
||||||
|
return m | e; // Return combined number
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint[] GenerateMantissaTable()
|
||||||
|
{
|
||||||
|
uint[] mantissaTable = new uint[2048];
|
||||||
|
mantissaTable[0] = 0;
|
||||||
|
for (int i = 1; i < 1024; i++)
|
||||||
|
{
|
||||||
|
mantissaTable[i] = ConvertMantissa(i);
|
||||||
|
}
|
||||||
|
for (int i = 1024; i < 2048; i++)
|
||||||
|
{
|
||||||
|
mantissaTable[i] = (uint)(0x38000000 + ((i - 1024) << 13));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mantissaTable;
|
||||||
|
}
|
||||||
|
private static uint[] GenerateExponentTable()
|
||||||
|
{
|
||||||
|
uint[] exponentTable = new uint[64];
|
||||||
|
exponentTable[0] = 0;
|
||||||
|
for (int i = 1; i < 31; i++)
|
||||||
|
{
|
||||||
|
exponentTable[i] = (uint)(i << 23);
|
||||||
|
}
|
||||||
|
exponentTable[31] = 0x47800000;
|
||||||
|
exponentTable[32] = 0x80000000;
|
||||||
|
for (int i = 33; i < 63; i++)
|
||||||
|
{
|
||||||
|
exponentTable[i] = (uint)(0x80000000 + ((i - 32) << 23));
|
||||||
|
}
|
||||||
|
exponentTable[63] = 0xc7800000;
|
||||||
|
|
||||||
|
return exponentTable;
|
||||||
|
}
|
||||||
|
private static ushort[] GenerateOffsetTable()
|
||||||
|
{
|
||||||
|
ushort[] offsetTable = new ushort[64];
|
||||||
|
offsetTable[0] = 0;
|
||||||
|
for (int i = 1; i < 32; i++)
|
||||||
|
{
|
||||||
|
offsetTable[i] = 1024;
|
||||||
|
}
|
||||||
|
offsetTable[32] = 0;
|
||||||
|
for (int i = 33; i < 64; i++)
|
||||||
|
{
|
||||||
|
offsetTable[i] = 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsetTable;
|
||||||
|
}
|
||||||
|
private static ushort[] GenerateBaseTable()
|
||||||
|
{
|
||||||
|
ushort[] baseTable = new ushort[512];
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
sbyte e = (sbyte)(127 - i);
|
||||||
|
if (e > 24)
|
||||||
|
{ // Very small numbers map to zero
|
||||||
|
baseTable[i | 0x000] = 0x0000;
|
||||||
|
baseTable[i | 0x100] = 0x8000;
|
||||||
|
}
|
||||||
|
else if (e > 14)
|
||||||
|
{ // Small numbers map to denorms
|
||||||
|
baseTable[i | 0x000] = (ushort)(0x0400 >> (18 + e));
|
||||||
|
baseTable[i | 0x100] = (ushort)((0x0400 >> (18 + e)) | 0x8000);
|
||||||
|
}
|
||||||
|
else if (e >= -15)
|
||||||
|
{ // Normal numbers just lose precision
|
||||||
|
baseTable[i | 0x000] = (ushort)((15 - e) << 10);
|
||||||
|
baseTable[i | 0x100] = (ushort)(((15 - e) << 10) | 0x8000);
|
||||||
|
}
|
||||||
|
else if (e > -128)
|
||||||
|
{ // Large numbers map to Infinity
|
||||||
|
baseTable[i | 0x000] = 0x7c00;
|
||||||
|
baseTable[i | 0x100] = 0xfc00;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Infinity and NaN's stay Infinity and NaN's
|
||||||
|
baseTable[i | 0x000] = 0x7c00;
|
||||||
|
baseTable[i | 0x100] = 0xfc00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseTable;
|
||||||
|
}
|
||||||
|
private static sbyte[] GenerateShiftTable()
|
||||||
|
{
|
||||||
|
sbyte[] shiftTable = new sbyte[512];
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
sbyte e = (sbyte)(127 - i);
|
||||||
|
if (e > 24)
|
||||||
|
{ // Very small numbers map to zero
|
||||||
|
shiftTable[i | 0x000] = 24;
|
||||||
|
shiftTable[i | 0x100] = 24;
|
||||||
|
}
|
||||||
|
else if (e > 14)
|
||||||
|
{ // Small numbers map to denorms
|
||||||
|
shiftTable[i | 0x000] = (sbyte)(e - 1);
|
||||||
|
shiftTable[i | 0x100] = (sbyte)(e - 1);
|
||||||
|
}
|
||||||
|
else if (e >= -15)
|
||||||
|
{ // Normal numbers just lose precision
|
||||||
|
shiftTable[i | 0x000] = 13;
|
||||||
|
shiftTable[i | 0x100] = 13;
|
||||||
|
}
|
||||||
|
else if (e > -128)
|
||||||
|
{ // Large numbers map to Infinity
|
||||||
|
shiftTable[i | 0x000] = 24;
|
||||||
|
shiftTable[i | 0x100] = 24;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Infinity and NaN's stay Infinity and NaN's
|
||||||
|
shiftTable[i | 0x000] = 13;
|
||||||
|
shiftTable[i | 0x100] = 13;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shiftTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public static unsafe float HalfToSingle(Half half)
|
||||||
|
{
|
||||||
|
uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
|
||||||
|
return *((float*)&result);
|
||||||
|
}
|
||||||
|
public static unsafe Half SingleToHalf(float single)
|
||||||
|
{
|
||||||
|
uint value = *((uint*)&single);
|
||||||
|
|
||||||
|
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
|
||||||
|
return Half.ToHalf(result);
|
||||||
|
}*/
|
||||||
|
public static float HalfToSingle(Half half)
|
||||||
|
{
|
||||||
|
uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
|
||||||
|
byte[] uintBytes = BitConverter.GetBytes(result);
|
||||||
|
return BitConverter.ToSingle(uintBytes, 0);
|
||||||
|
}
|
||||||
|
public static Half SingleToHalf(float single)
|
||||||
|
{
|
||||||
|
byte[] singleBytes = BitConverter.GetBytes(single);
|
||||||
|
uint value = BitConverter.ToUInt32(singleBytes, 0);
|
||||||
|
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
|
||||||
|
return Half.ToHalf(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Half Negate(Half half)
|
||||||
|
{
|
||||||
|
return Half.ToHalf((ushort)(half.value ^ 0x8000));
|
||||||
|
}
|
||||||
|
public static Half Abs(Half half)
|
||||||
|
{
|
||||||
|
return Half.ToHalf((ushort)(half.value & 0x7fff));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsNaN(Half half)
|
||||||
|
{
|
||||||
|
return ((half.value & 0x7fff) > 0x7c00);
|
||||||
|
}
|
||||||
|
public static bool IsInfinity(Half half)
|
||||||
|
{
|
||||||
|
return ((half.value & 0x7fff) == 0x7c00);
|
||||||
|
}
|
||||||
|
public static bool IsPositiveInfinity(Half half)
|
||||||
|
{
|
||||||
|
return (half.value == 0x7c00);
|
||||||
|
}
|
||||||
|
public static bool IsNegativeInfinity(Half half)
|
||||||
|
{
|
||||||
|
return (half.value == 0xfc00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
241
AssetStudio/Math/Matrix4x4.cs
Normal file
241
AssetStudio/Math/Matrix4x4.cs
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
|
public struct Matrix4x4 : IEquatable<Matrix4x4>
|
||||||
|
{
|
||||||
|
public float M00;
|
||||||
|
public float M10;
|
||||||
|
public float M20;
|
||||||
|
public float M30;
|
||||||
|
|
||||||
|
public float M01;
|
||||||
|
public float M11;
|
||||||
|
public float M21;
|
||||||
|
public float M31;
|
||||||
|
|
||||||
|
public float M02;
|
||||||
|
public float M12;
|
||||||
|
public float M22;
|
||||||
|
public float M32;
|
||||||
|
|
||||||
|
public float M03;
|
||||||
|
public float M13;
|
||||||
|
public float M23;
|
||||||
|
public float M33;
|
||||||
|
|
||||||
|
public Matrix4x4(float[] values)
|
||||||
|
{
|
||||||
|
if (values == null)
|
||||||
|
throw new ArgumentNullException(nameof(values));
|
||||||
|
if (values.Length != 16)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(values), "There must be sixteen and only sixteen input values for Matrix.");
|
||||||
|
|
||||||
|
M00 = values[0];
|
||||||
|
M10 = values[1];
|
||||||
|
M20 = values[2];
|
||||||
|
M30 = values[3];
|
||||||
|
|
||||||
|
M01 = values[4];
|
||||||
|
M11 = values[5];
|
||||||
|
M21 = values[6];
|
||||||
|
M31 = values[7];
|
||||||
|
|
||||||
|
M02 = values[8];
|
||||||
|
M12 = values[9];
|
||||||
|
M22 = values[10];
|
||||||
|
M32 = values[11];
|
||||||
|
|
||||||
|
M03 = values[12];
|
||||||
|
M13 = values[13];
|
||||||
|
M23 = values[14];
|
||||||
|
M33 = values[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int row, int column]
|
||||||
|
{
|
||||||
|
get => this[row + column * 4];
|
||||||
|
|
||||||
|
set => this[row + column * 4] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return M00;
|
||||||
|
case 1: return M10;
|
||||||
|
case 2: return M20;
|
||||||
|
case 3: return M30;
|
||||||
|
case 4: return M01;
|
||||||
|
case 5: return M11;
|
||||||
|
case 6: return M21;
|
||||||
|
case 7: return M31;
|
||||||
|
case 8: return M02;
|
||||||
|
case 9: return M12;
|
||||||
|
case 10: return M22;
|
||||||
|
case 11: return M32;
|
||||||
|
case 12: return M03;
|
||||||
|
case 13: return M13;
|
||||||
|
case 14: return M23;
|
||||||
|
case 15: return M33;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Matrix4x4 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: M00 = value; break;
|
||||||
|
case 1: M10 = value; break;
|
||||||
|
case 2: M20 = value; break;
|
||||||
|
case 3: M30 = value; break;
|
||||||
|
case 4: M01 = value; break;
|
||||||
|
case 5: M11 = value; break;
|
||||||
|
case 6: M21 = value; break;
|
||||||
|
case 7: M31 = value; break;
|
||||||
|
case 8: M02 = value; break;
|
||||||
|
case 9: M12 = value; break;
|
||||||
|
case 10: M22 = value; break;
|
||||||
|
case 11: M32 = value; break;
|
||||||
|
case 12: M03 = value; break;
|
||||||
|
case 13: M13 = value; break;
|
||||||
|
case 14: M23 = value; break;
|
||||||
|
case 15: M33 = value; break;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Matrix4x4 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return GetColumn(0).GetHashCode() ^ (GetColumn(1).GetHashCode() << 2) ^ (GetColumn(2).GetHashCode() >> 2) ^ (GetColumn(3).GetHashCode() >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (!(other is Matrix4x4))
|
||||||
|
return false;
|
||||||
|
return Equals((Matrix4x4)other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Matrix4x4 other)
|
||||||
|
{
|
||||||
|
return GetColumn(0).Equals(other.GetColumn(0))
|
||||||
|
&& GetColumn(1).Equals(other.GetColumn(1))
|
||||||
|
&& GetColumn(2).Equals(other.GetColumn(2))
|
||||||
|
&& GetColumn(3).Equals(other.GetColumn(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 GetColumn(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return new Vector4(M00, M10, M20, M30);
|
||||||
|
case 1: return new Vector4(M01, M11, M21, M31);
|
||||||
|
case 2: return new Vector4(M02, M12, M22, M32);
|
||||||
|
case 3: return new Vector4(M03, M13, M23, M33);
|
||||||
|
default: throw new IndexOutOfRangeException("Invalid column index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 GetRow(int index)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return new Vector4(M00, M01, M02, M03);
|
||||||
|
case 1: return new Vector4(M10, M11, M12, M13);
|
||||||
|
case 2: return new Vector4(M20, M21, M22, M23);
|
||||||
|
case 3: return new Vector4(M30, M31, M32, M33);
|
||||||
|
default: throw new IndexOutOfRangeException("Invalid row index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix4x4 operator *(Matrix4x4 lhs, Matrix4x4 rhs)
|
||||||
|
{
|
||||||
|
Matrix4x4 res;
|
||||||
|
res.M00 = lhs.M00 * rhs.M00 + lhs.M01 * rhs.M10 + lhs.M02 * rhs.M20 + lhs.M03 * rhs.M30;
|
||||||
|
res.M01 = lhs.M00 * rhs.M01 + lhs.M01 * rhs.M11 + lhs.M02 * rhs.M21 + lhs.M03 * rhs.M31;
|
||||||
|
res.M02 = lhs.M00 * rhs.M02 + lhs.M01 * rhs.M12 + lhs.M02 * rhs.M22 + lhs.M03 * rhs.M32;
|
||||||
|
res.M03 = lhs.M00 * rhs.M03 + lhs.M01 * rhs.M13 + lhs.M02 * rhs.M23 + lhs.M03 * rhs.M33;
|
||||||
|
|
||||||
|
res.M10 = lhs.M10 * rhs.M00 + lhs.M11 * rhs.M10 + lhs.M12 * rhs.M20 + lhs.M13 * rhs.M30;
|
||||||
|
res.M11 = lhs.M10 * rhs.M01 + lhs.M11 * rhs.M11 + lhs.M12 * rhs.M21 + lhs.M13 * rhs.M31;
|
||||||
|
res.M12 = lhs.M10 * rhs.M02 + lhs.M11 * rhs.M12 + lhs.M12 * rhs.M22 + lhs.M13 * rhs.M32;
|
||||||
|
res.M13 = lhs.M10 * rhs.M03 + lhs.M11 * rhs.M13 + lhs.M12 * rhs.M23 + lhs.M13 * rhs.M33;
|
||||||
|
|
||||||
|
res.M20 = lhs.M20 * rhs.M00 + lhs.M21 * rhs.M10 + lhs.M22 * rhs.M20 + lhs.M23 * rhs.M30;
|
||||||
|
res.M21 = lhs.M20 * rhs.M01 + lhs.M21 * rhs.M11 + lhs.M22 * rhs.M21 + lhs.M23 * rhs.M31;
|
||||||
|
res.M22 = lhs.M20 * rhs.M02 + lhs.M21 * rhs.M12 + lhs.M22 * rhs.M22 + lhs.M23 * rhs.M32;
|
||||||
|
res.M23 = lhs.M20 * rhs.M03 + lhs.M21 * rhs.M13 + lhs.M22 * rhs.M23 + lhs.M23 * rhs.M33;
|
||||||
|
|
||||||
|
res.M30 = lhs.M30 * rhs.M00 + lhs.M31 * rhs.M10 + lhs.M32 * rhs.M20 + lhs.M33 * rhs.M30;
|
||||||
|
res.M31 = lhs.M30 * rhs.M01 + lhs.M31 * rhs.M11 + lhs.M32 * rhs.M21 + lhs.M33 * rhs.M31;
|
||||||
|
res.M32 = lhs.M30 * rhs.M02 + lhs.M31 * rhs.M12 + lhs.M32 * rhs.M22 + lhs.M33 * rhs.M32;
|
||||||
|
res.M33 = lhs.M30 * rhs.M03 + lhs.M31 * rhs.M13 + lhs.M32 * rhs.M23 + lhs.M33 * rhs.M33;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Matrix4x4 lhs, Matrix4x4 rhs)
|
||||||
|
{
|
||||||
|
return lhs.GetColumn(0) == rhs.GetColumn(0)
|
||||||
|
&& lhs.GetColumn(1) == rhs.GetColumn(1)
|
||||||
|
&& lhs.GetColumn(2) == rhs.GetColumn(2)
|
||||||
|
&& lhs.GetColumn(3) == rhs.GetColumn(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Matrix4x4 lhs, Matrix4x4 rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix4x4 Scale(Vector3 vector)
|
||||||
|
{
|
||||||
|
Matrix4x4 m;
|
||||||
|
m.M00 = vector.X; m.M01 = 0F; m.M02 = 0F; m.M03 = 0F;
|
||||||
|
m.M10 = 0F; m.M11 = vector.Y; m.M12 = 0F; m.M13 = 0F;
|
||||||
|
m.M20 = 0F; m.M21 = 0F; m.M22 = vector.Z; m.M23 = 0F;
|
||||||
|
m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix4x4 Translate(Vector3 vector)
|
||||||
|
{
|
||||||
|
Matrix4x4 m;
|
||||||
|
m.M00 = 1F; m.M01 = 0F; m.M02 = 0F; m.M03 = vector.X;
|
||||||
|
m.M10 = 0F; m.M11 = 1F; m.M12 = 0F; m.M13 = vector.Y;
|
||||||
|
m.M20 = 0F; m.M21 = 0F; m.M22 = 1F; m.M23 = vector.Z;
|
||||||
|
m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix4x4 Rotate(Quaternion q)
|
||||||
|
{
|
||||||
|
float x = q.X * 2.0F;
|
||||||
|
float y = q.Y * 2.0F;
|
||||||
|
float z = q.Z * 2.0F;
|
||||||
|
float xx = q.X * x;
|
||||||
|
float yy = q.Y * y;
|
||||||
|
float zz = q.Z * z;
|
||||||
|
float xy = q.X * y;
|
||||||
|
float xz = q.X * z;
|
||||||
|
float yz = q.Y * z;
|
||||||
|
float wx = q.W * x;
|
||||||
|
float wy = q.W * y;
|
||||||
|
float wz = q.W * z;
|
||||||
|
|
||||||
|
Matrix4x4 m;
|
||||||
|
m.M00 = 1.0f - (yy + zz); m.M10 = xy + wz; m.M20 = xz - wy; m.M30 = 0.0F;
|
||||||
|
m.M01 = xy - wz; m.M11 = 1.0f - (xx + zz); m.M21 = yz + wx; m.M31 = 0.0F;
|
||||||
|
m.M02 = xz + wy; m.M12 = yz - wx; m.M22 = 1.0f - (xx + yy); m.M32 = 0.0F;
|
||||||
|
m.M03 = 0.0F; m.M13 = 0.0F; m.M23 = 0.0F; m.M33 = 1.0F;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
AssetStudio/Math/Quaternion.cs
Normal file
88
AssetStudio/Math/Quaternion.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
|
public struct Quaternion : IEquatable<Quaternion>
|
||||||
|
{
|
||||||
|
public float X;
|
||||||
|
public float Y;
|
||||||
|
public float Z;
|
||||||
|
public float W;
|
||||||
|
|
||||||
|
public Quaternion(float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
W = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return X;
|
||||||
|
case 1: return Y;
|
||||||
|
case 2: return Z;
|
||||||
|
case 3: return W;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: X = value; break;
|
||||||
|
case 1: Y = value; break;
|
||||||
|
case 2: Z = value; break;
|
||||||
|
case 3: W = value; break;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (!(other is Quaternion))
|
||||||
|
return false;
|
||||||
|
return Equals((Quaternion)other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Quaternion other)
|
||||||
|
{
|
||||||
|
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Dot(Quaternion a, Quaternion b)
|
||||||
|
{
|
||||||
|
return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsEqualUsingDot(float dot)
|
||||||
|
{
|
||||||
|
return dot > 1.0f - kEpsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Quaternion lhs, Quaternion rhs)
|
||||||
|
{
|
||||||
|
return IsEqualUsingDot(Dot(lhs, rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Quaternion lhs, Quaternion rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float kEpsilon = 0.000001F;
|
||||||
|
}
|
||||||
|
}
|
||||||
148
AssetStudio/Math/Vector2.cs
Normal file
148
AssetStudio/Math/Vector2.cs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
|
public struct Vector2 : IEquatable<Vector2>
|
||||||
|
{
|
||||||
|
public float X;
|
||||||
|
public float Y;
|
||||||
|
|
||||||
|
public Vector2(float x, float y)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return X;
|
||||||
|
case 1: return Y;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: X = value; break;
|
||||||
|
case 1: Y = value; break;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return X.GetHashCode() ^ (Y.GetHashCode() << 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (!(other is Vector2))
|
||||||
|
return false;
|
||||||
|
return Equals((Vector2)other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Vector2 other)
|
||||||
|
{
|
||||||
|
return X.Equals(other.X) && Y.Equals(other.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Normalize()
|
||||||
|
{
|
||||||
|
var length = Length();
|
||||||
|
if (length > kEpsilon)
|
||||||
|
{
|
||||||
|
var invNorm = 1.0f / length;
|
||||||
|
X *= invNorm;
|
||||||
|
Y *= invNorm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X = 0;
|
||||||
|
Y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Length()
|
||||||
|
{
|
||||||
|
return (float)Math.Sqrt(LengthSquared());
|
||||||
|
}
|
||||||
|
|
||||||
|
public float LengthSquared()
|
||||||
|
{
|
||||||
|
return X * X + Y * Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 Zero => new Vector2();
|
||||||
|
|
||||||
|
public static Vector2 operator +(Vector2 a, Vector2 b)
|
||||||
|
{
|
||||||
|
return new Vector2(a.X + b.X, a.Y + b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 operator -(Vector2 a, Vector2 b)
|
||||||
|
{
|
||||||
|
return new Vector2(a.X - b.X, a.Y - b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 operator *(Vector2 a, Vector2 b)
|
||||||
|
{
|
||||||
|
return new Vector2(a.X * b.X, a.Y * b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 operator /(Vector2 a, Vector2 b)
|
||||||
|
{
|
||||||
|
return new Vector2(a.X / b.X, a.Y / b.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 operator -(Vector2 a)
|
||||||
|
{
|
||||||
|
return new Vector2(-a.X, -a.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 operator *(Vector2 a, float d)
|
||||||
|
{
|
||||||
|
return new Vector2(a.X * d, a.Y * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 operator *(float d, Vector2 a)
|
||||||
|
{
|
||||||
|
return new Vector2(a.X * d, a.Y * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 operator /(Vector2 a, float d)
|
||||||
|
{
|
||||||
|
return new Vector2(a.X / d, a.Y / d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Vector3(Vector2 v)
|
||||||
|
{
|
||||||
|
return new Vector3(v.X, v.Y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Vector4(Vector2 v)
|
||||||
|
{
|
||||||
|
return new Vector4(v.X, v.Y, 0.0F, 0.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float kEpsilon = 0.00001F;
|
||||||
|
}
|
||||||
|
}
|
||||||
146
AssetStudio/Math/Vector3.cs
Normal file
146
AssetStudio/Math/Vector3.cs
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
|
public struct Vector3 : IEquatable<Vector3>
|
||||||
|
{
|
||||||
|
public float X;
|
||||||
|
public float Y;
|
||||||
|
public float Z;
|
||||||
|
|
||||||
|
public Vector3(float x, float y, float z)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return X;
|
||||||
|
case 1: return Y;
|
||||||
|
case 2: return Z;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: X = value; break;
|
||||||
|
case 1: Y = value; break;
|
||||||
|
case 2: Z = value; break;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (!(other is Vector3))
|
||||||
|
return false;
|
||||||
|
return Equals((Vector3)other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Vector3 other)
|
||||||
|
{
|
||||||
|
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Normalize()
|
||||||
|
{
|
||||||
|
var length = Length();
|
||||||
|
if (length > kEpsilon)
|
||||||
|
{
|
||||||
|
var invNorm = 1.0f / length;
|
||||||
|
X *= invNorm;
|
||||||
|
Y *= invNorm;
|
||||||
|
Z *= invNorm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X = 0;
|
||||||
|
Y = 0;
|
||||||
|
Z = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Length()
|
||||||
|
{
|
||||||
|
return (float)Math.Sqrt(LengthSquared());
|
||||||
|
}
|
||||||
|
|
||||||
|
public float LengthSquared()
|
||||||
|
{
|
||||||
|
return X * X + Y * Y + Z * Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 Zero => new Vector3();
|
||||||
|
|
||||||
|
public static Vector3 One => new Vector3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
public static Vector3 operator +(Vector3 a, Vector3 b)
|
||||||
|
{
|
||||||
|
return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 operator -(Vector3 a, Vector3 b)
|
||||||
|
{
|
||||||
|
return new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 operator -(Vector3 a)
|
||||||
|
{
|
||||||
|
return new Vector3(-a.X, -a.Y, -a.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 operator *(Vector3 a, float d)
|
||||||
|
{
|
||||||
|
return new Vector3(a.X * d, a.Y * d, a.Z * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 operator *(float d, Vector3 a)
|
||||||
|
{
|
||||||
|
return new Vector3(a.X * d, a.Y * d, a.Z * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 operator /(Vector3 a, float d)
|
||||||
|
{
|
||||||
|
return new Vector3(a.X / d, a.Y / d, a.Z / d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Vector2(Vector3 v)
|
||||||
|
{
|
||||||
|
return new Vector2(v.X, v.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Vector4(Vector3 v)
|
||||||
|
{
|
||||||
|
return new Vector4(v.X, v.Y, v.Z, 0.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float kEpsilon = 0.00001F;
|
||||||
|
}
|
||||||
|
}
|
||||||
163
AssetStudio/Math/Vector4.cs
Normal file
163
AssetStudio/Math/Vector4.cs
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
|
public struct Vector4 : IEquatable<Vector4>
|
||||||
|
{
|
||||||
|
public float X;
|
||||||
|
public float Y;
|
||||||
|
public float Z;
|
||||||
|
public float W;
|
||||||
|
|
||||||
|
public Vector4(float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
W = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4(Vector3 value, float w)
|
||||||
|
{
|
||||||
|
X = value.X;
|
||||||
|
Y = value.Y;
|
||||||
|
Z = value.Z;
|
||||||
|
W = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: return X;
|
||||||
|
case 1: return Y;
|
||||||
|
case 2: return Z;
|
||||||
|
case 3: return W;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0: X = value; break;
|
||||||
|
case 1: Y = value; break;
|
||||||
|
case 2: Z = value; break;
|
||||||
|
case 3: W = value; break;
|
||||||
|
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (!(other is Vector4))
|
||||||
|
return false;
|
||||||
|
return Equals((Vector4)other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Vector4 other)
|
||||||
|
{
|
||||||
|
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Normalize()
|
||||||
|
{
|
||||||
|
var length = Length();
|
||||||
|
if (length > kEpsilon)
|
||||||
|
{
|
||||||
|
var invNorm = 1.0f / length;
|
||||||
|
X *= invNorm;
|
||||||
|
Y *= invNorm;
|
||||||
|
Z *= invNorm;
|
||||||
|
W *= invNorm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X = 0;
|
||||||
|
Y = 0;
|
||||||
|
Z = 0;
|
||||||
|
W = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Length()
|
||||||
|
{
|
||||||
|
return (float)Math.Sqrt(LengthSquared());
|
||||||
|
}
|
||||||
|
|
||||||
|
public float LengthSquared()
|
||||||
|
{
|
||||||
|
return X * X + Y * Y + Z * Z + W * W;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4 Zero => new Vector4();
|
||||||
|
|
||||||
|
public static Vector4 operator +(Vector4 a, Vector4 b)
|
||||||
|
{
|
||||||
|
return new Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4 operator -(Vector4 a, Vector4 b)
|
||||||
|
{
|
||||||
|
return new Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4 operator -(Vector4 a)
|
||||||
|
{
|
||||||
|
return new Vector4(-a.X, -a.Y, -a.Z, -a.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4 operator *(Vector4 a, float d)
|
||||||
|
{
|
||||||
|
return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4 operator *(float d, Vector4 a)
|
||||||
|
{
|
||||||
|
return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4 operator /(Vector4 a, float d)
|
||||||
|
{
|
||||||
|
return new Vector4(a.X / d, a.Y / d, a.Z / d, a.W / d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Vector4 lhs, Vector4 rhs)
|
||||||
|
{
|
||||||
|
return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Vector4 lhs, Vector4 rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Vector2(Vector4 v)
|
||||||
|
{
|
||||||
|
return new Vector2(v.X, v.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Vector3(Vector4 v)
|
||||||
|
{
|
||||||
|
return new Vector3(v.X, v.Y, v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Color(Vector4 v)
|
||||||
|
{
|
||||||
|
return new Color(v.X, v.Y, v.Z, v.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float kEpsilon = 0.00001F;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
AssetStudio/ObjectInfo.cs
Normal file
18
AssetStudio/ObjectInfo.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class ObjectInfo
|
||||||
|
{
|
||||||
|
public long byteStart;
|
||||||
|
public uint byteSize;
|
||||||
|
public int typeID;
|
||||||
|
public int classID;
|
||||||
|
|
||||||
|
public long m_PathID;
|
||||||
|
public SerializedType serializedType;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
AssetStudio/ObjectReader.cs
Normal file
47
AssetStudio/ObjectReader.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class ObjectReader : EndianBinaryReader
|
||||||
|
{
|
||||||
|
public SerializedFile assetsFile;
|
||||||
|
public long m_PathID;
|
||||||
|
public long byteStart;
|
||||||
|
public uint byteSize;
|
||||||
|
public ClassIDType type;
|
||||||
|
public SerializedType serializedType;
|
||||||
|
public BuildTarget platform;
|
||||||
|
public uint m_Version;
|
||||||
|
|
||||||
|
public int[] version => assetsFile.version;
|
||||||
|
public BuildType buildType => assetsFile.buildType;
|
||||||
|
|
||||||
|
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.endian)
|
||||||
|
{
|
||||||
|
this.assetsFile = assetsFile;
|
||||||
|
m_PathID = objectInfo.m_PathID;
|
||||||
|
byteStart = objectInfo.byteStart;
|
||||||
|
byteSize = objectInfo.byteSize;
|
||||||
|
if (Enum.IsDefined(typeof(ClassIDType), objectInfo.classID))
|
||||||
|
{
|
||||||
|
type = (ClassIDType)objectInfo.classID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = ClassIDType.UnknownType;
|
||||||
|
}
|
||||||
|
serializedType = objectInfo.serializedType;
|
||||||
|
platform = assetsFile.m_TargetPlatform;
|
||||||
|
m_Version = assetsFile.header.m_Version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Position = byteStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
AssetStudio/Progress.cs
Normal file
29
AssetStudio/Progress.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public static class Progress
|
||||||
|
{
|
||||||
|
public static IProgress Default = new DummyProgress();
|
||||||
|
private static int preValue;
|
||||||
|
|
||||||
|
public static void Reset()
|
||||||
|
{
|
||||||
|
preValue = 0;
|
||||||
|
Default.Report(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Report(int current, int total)
|
||||||
|
{
|
||||||
|
var value = (int)(current * 100f / total);
|
||||||
|
Report(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Report(int value)
|
||||||
|
{
|
||||||
|
if (value > preValue)
|
||||||
|
{
|
||||||
|
preValue = value;
|
||||||
|
Default.Report(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
AssetStudio/Properties/AssemblyInfo.cs
Normal file
36
AssetStudio/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// 有关程序集的一般信息由以下
|
||||||
|
// 控制。更改这些特性值可修改
|
||||||
|
// 与程序集关联的信息。
|
||||||
|
[assembly: AssemblyTitle("AssetStudio")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("AssetStudio")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||||
|
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||||
|
//请将此类型的 ComVisible 特性设置为 true。
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||||
|
[assembly: Guid("7662f8c2-7bfd-442e-a948-a43b4f7eb06e")]
|
||||||
|
|
||||||
|
// 程序集的版本信息由下列四个值组成:
|
||||||
|
//
|
||||||
|
// 主版本
|
||||||
|
// 次版本
|
||||||
|
// 生成号
|
||||||
|
// 修订号
|
||||||
|
//
|
||||||
|
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||||
|
//通过使用 "*",如下所示:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("0.14.38.5")]
|
||||||
|
[assembly: AssemblyFileVersion("0.14.38.5")]
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user