824 Commits

Author SHA1 Message Date
VaDiM
6b66ec7467 Fix rendering of some packed sprites. Close #104 2025-10-15 22:23:42 +03:00
VaDiM
0021cf221e Some minor improvements 2025-10-11 14:28:05 +03:00
VaDiM
c07dc59f51 Improve support for Unity 6000.2+ assets 2025-10-10 04:11:27 +03:00
VaDiM
d1bf0c5a37 Add option to extract raw byte array from MonoBehaviour assets 2025-10-07 01:07:48 +03:00
VaDiM
6d5b633d55 Some minor fixes 2025-10-07 01:07:14 +03:00
VaDiM
6c3ff89dbf Improve lzma progress report 2025-09-12 19:57:36 +03:00
VaDiM
763f188afb Fix memory allocation for uncompressed bundles inside a multiBundle 2025-09-08 03:06:03 +03:00
VaDiM
553f0d94f3 Some fixes for Live2D export
- [CLI] Replaced "--l2d-force-bezier" with "--l2d-smooth-motions"
2025-09-06 03:50:55 +03:00
VaDiM
80e6a1d074 Update README.md 2025-09-04 23:10:34 +03:00
VaDiM
6de33d0437 Update to v0.19 & update dependencies 2025-09-04 20:07:22 +03:00
VaDiM
7ce8b8c8ae [CLI] Some minor fixes 2025-09-04 17:54:55 +03:00
VaDiM
2d449ff4cd Fix support for meshes with omitted weight values. Close #21 2025-09-03 13:12:59 +03:00
VaDiM
1d65096001 [CLI] Add more info to the "Info" mode 2025-09-01 23:38:05 +03:00
VaDiM
355c99c034 [CLI] Fix deleting of temp files 2025-09-01 22:19:48 +03:00
VaDiM
963cd6546b Improve mesh loading 2025-09-01 16:32:46 +03:00
VaDiM
ae3b5169df Some other fixes 2025-08-27 05:23:50 +03:00
VaDiM
521e2f3bbc Improve Tuanjie support 2025-08-27 05:22:46 +03:00
VaDiM
f0a69025fe Update asset export logic
- Disabled saving files with a unique id if they already exist. A unique id will only be added to files with identical names during export.
- Added an option to overwrite exisisting files.
- Fixed support of multiple model export using "Export selected objects (split)" option. (#43)
2025-08-19 20:51:38 +03:00
VaDiM
52b0a21181 Some fixes for bundle reader 2025-08-11 01:27:02 +03:00
VaDiM
be11fdf14f [GUI] Some fixes for animation export
- Disabled animation converting if animation export is disabled in the options
- Fixed a bug with ignoring animation selection order when exporting models with selected animationClips via the “Model” tab
2025-08-11 01:25:42 +03:00
VaDiM
054906a426 More spans 2025-08-11 01:25:42 +03:00
VaDiM
35324083e1 [CLI] Add flag to always decompress bundles to disk 2025-08-03 14:26:49 +03:00
VaDiM
36bd3c8342 [GUI] Rework some import options
- Added feature to load and export import options to a file (import options include unity version).
- Added option to always decompress bundles to disk. (Related issue: #58 )
2025-08-03 00:08:00 +03:00
VaDiM
c20c07b5f2 Update bundle reader
- Replaced creation of a duplicated file/memory stream with OffsetStream.
- Added separate processing of uncompressed bundles (including streamed bundles). They will be read directly from disk.
- Added progress report on LZMA decompression process.
2025-07-24 19:07:24 +03:00
VaDiM
efca2a7557 Add support for bundles with obfuscated unity version 2025-07-24 15:59:38 +03:00
VaDiM
6b41a36c7d Fix parsing of MovieTexture and MonoScript assets 2025-07-24 15:59:37 +03:00
VaDiM
35b24990c6 Allocation-safe asset reading
Try to not pre-allocate memory during asset reading
2025-07-24 04:06:33 +03:00
VaDiM
925f5c12a3 Update FileReader & EndianSpanReader 2025-07-24 04:04:03 +03:00
VaDiM
9c64f7f56d Fix parsing of Tuanjie Renderer assets 2025-07-24 04:04:03 +03:00
VaDiM
3c6b65f724 Update BuildTarget.cs 2025-07-22 03:00:56 +03:00
VaDiM
34819608c5 Fixes for zip file reading
- Fixed path for split files
- Fixed assetsFile loading from an archive
2025-07-22 03:00:56 +03:00
VaDiM
6f8f1a5a8a Use System.Half 2025-07-13 20:40:34 +03:00
VaDiM
f0029520fb Fix for TypeTreeHelper
ref: b71a7620a3
2025-07-13 01:56:09 +03:00
VaDiM
7b7eac62d8 Fixes for Live2D export
- Fixed export of live2d models from assets without containers.
- Improved method of binding model-related assets.
2025-06-27 00:41:58 +03:00
VaDiM
3a25ed9ccd [CLI] Update "current options" structure 2025-06-12 01:41:33 +03:00
VaDiM
785eeb8665 [CLI] Add name filtering support for Live2D export mode 2025-06-12 01:41:33 +03:00
VaDiM
fd50054edf [CLI] Add regex support for splitObject export mode 2025-06-12 01:41:33 +03:00
VaDiM
a1ee61c542 Some minor fixes 2025-06-10 02:06:24 +03:00
VaDiM
12799da395 [CLI] Add Animator export 2025-06-07 23:45:49 +03:00
VaDiM
60426a4b9a Improve support of Tuanjie assets 2025-06-07 23:40:49 +03:00
VaDiM
3ea01ec9bc Display animation count when exporting fbx models 2025-05-29 05:11:21 +03:00
VaDiM
7da68aedff [CLI] Add support for multiple file loading 2025-05-29 05:11:06 +03:00
VaDiM
548f8a52cf Minor fix for multibundle reader 2025-05-25 01:17:54 +03:00
VaDiM
24337f66f9 Fix parsing of Material assets from some 2021.2 versions 2025-05-21 16:08:56 +03:00
VaDiM
92a89db4e8 Fix parsing of legacy Tuanjie AnimationClip assets 2025-05-18 02:18:58 +03:00
VaDiM
c11e085e2e Fix build 2025-05-17 14:30:19 +03:00
VaDiM
55406553f6 Some minor fixes 2025-05-17 04:58:43 +03:00
VaDiM
b0a051fc47 [GUI] Add exact search option for Scene Hierarchy. Close #49 2025-05-11 09:29:11 +03:00
VaDiM
97fa42742b [CLI] Add flag to allow filtering assets using regex. Close #45
- Added --filter-with-regex flag
2025-05-11 09:29:11 +03:00
VaDiM
97bdef0891 Update UnityCN detection method 2025-05-09 03:41:54 +03:00
VaDiM
876bafdda1 Add oodle compression support (unofficial) 2025-05-09 03:41:53 +03:00
VaDiM
66229e564a Fix parsing of AnimationClip assets via typetree for Unity versions < 5 2025-05-09 02:23:42 +03:00
VaDiM
13f37ec260 Fix audioClip converting 2025-04-17 01:01:58 +03:00
VaDiM
a0c2a7bdfe Improve integration with Live2D assets
- Added container-independent method for searching AnimationClip assets
(However, it's not really universal, so it can't completely replace the container-dependent method)
2025-04-10 01:30:45 +03:00
VaDiM
0cc74b8c12 Fix Tuanjie detection 2025-04-08 02:46:11 +03:00
VaDiM
f077064a6a Fix for UV bindings 2025-04-06 00:06:09 +03:00
VaDiM
190cb68b07 [CLI] Add flag to export all UVs as diffuse maps 2025-03-31 20:14:33 +03:00
VaDiM
3fa2ef1694 Some minor fixes 2025-03-31 20:10:02 +03:00
VaDiM
40e0bd0248 [CLI] Fix export of some fbx models 2025-03-31 19:45:47 +03:00
VaDiM
e1e43439c3 Add option to manually bind UV map types 2025-03-29 23:57:59 +03:00
VaDiM
e8ca265a43 Fix multiBundle file extraction 2025-03-25 21:54:34 +03:00
VaDiM
81ed77819a [CLI] Improve UnityVersion option info 2025-03-22 19:01:07 +03:00
VaDiM
d1fed47f92 [CLI] Change color of option example string 2025-03-22 19:01:07 +03:00
VaDiM
3b10a808d3 [GUI] Add option to autoplay audioClip assets 2025-03-22 19:01:06 +03:00
VaDiM
47d67e0a49 Update FMOD to v2.03.06
- Fixed a bug that caused audioСlip preview volume to reset when selecting an asset
- Added some native libs for linux-arm64, win-arm64
2025-03-22 19:01:06 +03:00
VaDiM
bc0e32efec Add multiBundle support
including fake headers
2025-03-10 18:08:40 +03:00
VaDiM
db4eb30a27 Fix PPtrConverter (#69) 2025-03-04 04:05:22 +03:00
VaDiM
9f918d0332 Fix export of selected Live2D motions 2025-03-03 22:18:29 +03:00
VaDiM
81cd6d79d0 Add AnimationClip equality comparer 2025-03-03 22:18:29 +03:00
VaDiM
9024e6a235 Improve external data extraction for ExportRaw mode 2025-02-24 19:03:22 +03:00
VaDiM
0b7b809285 [GUI] Some visual fixes for audio player 2025-02-20 17:33:59 +03:00
VaDiM
f7e6d23084 Add support for obfuscated unity versions 2025-02-17 18:51:05 +03:00
VaDiM
6ea1ff3e96 Fix for m_MuscleClipSize 2025-02-10 17:01:21 +03:00
VaDiM
185348d9b8 Replace Math with MathF 2025-01-31 17:55:47 +03:00
VaDiM
a8bb6c714b A small refactoring for Live2D motion export 2025-01-23 18:18:47 +03:00
VaDiM
cc21d4fa4d [CLI] Add support of Extract mode 2025-01-23 17:57:42 +03:00
VaDiM
e3e343320c [GUI] AudioClip improvements
- Increased loading speed of AudioClip preview
- Optimized memory consumption of AudioClip preview
- Fixed incorrect length detection for some sound types
- Added channel count info (audio channels)
2025-01-20 13:07:25 +03:00
VaDiM
1cdb0b762a Some fixes and improvements for Live2D export
- Fixed l2d model export for bundles with multiple models inside
- Added support of grouping exported models by model name
2025-01-15 03:38:33 +03:00
VaDiM
02f64f3c97 [GUI] Workaround for progress bar in Dark mode 2025-01-15 00:41:01 +03:00
VaDiM
58917ab7dc [GUI] Add tree view for dump 2025-01-15 00:41:01 +03:00
VaDiM
b7d21e5bd8 Add support for Tuanjie AnimationClip assets 2025-01-12 04:08:20 +03:00
VaDiM
d7b4d415ca Add support for Tuanjie Mesh assets 2025-01-12 04:08:20 +03:00
VaDiM
95f7d70419 Fix support of Tuanjie GameObject assets 2025-01-12 04:08:20 +03:00
VaDiM
4e93ea5a82 Improve ExportRaw option
- External data will also be added to exported assets
2025-01-12 04:08:19 +03:00
VaDiM
6608e76471 Improve error messages for AudioClip assets 2025-01-12 04:08:19 +03:00
VaDiM
ff92d1784d [GUI] Some fixes for Dark mode 2025-01-12 04:08:19 +03:00
VaDiM
064f5cbe57 Improve integration with Live2D assets 2025-01-12 04:08:19 +03:00
VaDiM
59db27de3a [GUI] Fix a bug with OpenFolderAfterExport option
- Fixed a bug with the OpenFolderAfterExport option when it launched a file instead of opening a folder in some cases
2025-01-12 04:08:19 +03:00
VaDiM
0d4e7ba4ae [GUI] Add Dark mode support for .NET 9 (wip). Close #9
Dark mode support for winforms was added with .net9, but the feature is still not finished. It should become better in future versions.
2025-01-12 04:08:19 +03:00
VaDiM
3605bc0ff9 Update project files: add .NET 9 & update dependencies 2025-01-12 04:08:19 +03:00
VaDiM
188ee088a2 Improve support of Texture2DArray assets 2025-01-12 04:08:19 +03:00
VaDiM
341612be16 Add Tuanjie WebFile support 2025-01-12 04:08:19 +03:00
VaDiM
e16046d775 Add support for Tuanjie Texture2D assets 2025-01-12 04:08:19 +03:00
VaDiM
d2f69432e4 Add Tuanjie build targets 2025-01-12 04:08:18 +03:00
VaDiM
08d50a8013 Update BuildTarget.cs 2025-01-12 04:08:18 +03:00
VaDiM
7b1585eff0 A small refactoring of l2d extractor 2025-01-12 04:08:18 +03:00
VaDiM
70aa8bec59 Add support for exporting l2d poses (pose3.json) 2025-01-12 04:08:18 +03:00
VaDiM
18813b22c3 Add names of pptr objects to object dumps 2024-11-02 04:51:21 +03:00
VaDiM
316837dfdf Fix parsing via typetree of old Material assets
- Fixed parsing via typetree of Material assets from Unity version <5.6
2024-11-02 02:12:49 +03:00
VaDiM
fca937e5e6 Some fixes for asset parsing via typetree 2024-11-02 01:40:45 +03:00
VaDiM
c2095c4e7a Fix audio preview for some fmod formats. Close #53 2024-10-30 17:11:19 +03:00
VaDiM
f253c868d4 Fix calculations in Live2D motions
- Fixed calculation of totalPointCount and totalSegmentCount in Live2D motions.
https://github.com/Live2D/CubismNativeFramework/pull/57
2024-10-30 01:26:37 +03:00
VaDiM
8ccdd0fd4e Minor fix for PPtrConverter 2024-10-22 01:58:15 +03:00
VaDiM
bc92dfb77c Add Material loading via typetree 2024-10-20 22:29:06 +03:00
VaDiM
c37e2e65b7 Fixes and improvements for asset parsing via typetree 2024-10-18 20:55:34 +03:00
VaDiM
58ee2b8f1e Improve support for some older Unity versions (<3.0)
- Fix export of AudioClip assets from unity v2.5 and earlier
- Fix parsing of PlayerSettings assets from unity v2.6 and earlier
- Fix parsing of AnimationClip assets from unity v2.5 and earlier
2024-10-05 02:17:16 +03:00
VaDiM
c93d27d9a4 Fixes for Unity version parser 2024-10-03 16:23:51 +03:00
VaDiM
5a84a67955 Move BuildType to UnityVersion class 2024-09-25 23:40:41 +03:00
VaDiM
fa332b45df Improve support of Unity 2023+ 2024-09-25 23:38:19 +03:00
VaDiM
348aea2be8 Update CommonString.cs
Unity 6
2024-09-25 23:38:18 +03:00
VaDiM
d52f192e75 Fix support of Sprites with wrong SpriteAtlas pathID 2024-09-13 00:39:04 +03:00
VaDiM
81a1eeb2d1 Merge branch 'pr/40' into AssetStudioMod 2024-09-04 01:15:22 +03:00
VaDiM
05ea91ef5e Merge branch 'pr/44' into AssetStudioMod 2024-08-08 21:49:27 +03:00
VaDiM
e0d5e5c6b7 Display "type" as a string in object dumps 2024-08-08 18:58:42 +03:00
VaDiM
b439cfed66 Update ClassIDType.cs 2024-08-08 18:42:28 +03:00
VaDiM
573b87b570 Replace "type" with "classID" in object dumps 2024-08-08 18:16:41 +03:00
Loyie King
585b69fb36 fix bundle blocks read failed with ArchiveFlags.BlocksInfoAtTheEnd
Bundle files may be aligned and padding with zeros. Previously `ArchiveFlags.BlocksInfoAtTheEnd` will read the end padding zeros rather than the real block infos, causing decompression errors in following logics.
2024-07-10 19:23:36 +08:00
hungrydoodles
5e3fe1775f Added so when the exported animator contains MeshRenderers without meshes attached it tries to find the missing meshes by the Renderer's original name. (Fixes NagantSR0101 from Girls Frontline 2 Animator export not exporting meshes at all in any existing variant.) Also set ReShade in 3D view to be disabled by default as it is misleading otherwise 2024-05-15 00:05:50 +05:00
VaDiM
8704feb079 Merge branch 'pr/37' into AssetStudioMod 2024-05-10 03:45:06 +03:00
VaDiM
f54fe3492b [CLI] Fix Mesh export for some region formats. Close #38 2024-05-10 03:22:39 +03:00
BM85-Hz
6d953d774d simplify loop label 2024-05-08 22:30:50 -07:00
BM85-Hz
f0a793bd3d added AudioClip loop point display to GUI 2024-05-05 18:34:28 -07:00
VaDiM
d886bf1c5d Update dependencies 2024-04-25 01:23:34 +03:00
VaDiM
1623981c0e [GUI] Add ability to filter live2d model assets 2024-04-24 22:19:51 +03:00
VaDiM
2c860f004b Use system.text.json to parse typetree
well, it's still slower than some more suitable libs for such task, but stable and with minimal code changes (and has net472 support, yeah)
2024-04-14 02:17:06 +03:00
VaDiM
a3f4c7a029 [CLI] Update readme 2024-04-12 21:48:57 +03:00
VaDiM
f86b5a97ac Fix resourceFileReader for webFile 2024-04-12 21:48:53 +03:00
VaDiM
7e408a3667 [GUI] Fix displayed info for non-fmod audio clips from Unity <5 2024-04-12 21:48:53 +03:00
VaDiM
6c515aee2e Fix support for sprite assets from Unity <5.2 2024-04-10 10:34:46 +03:00
VaDiM
bb7accd04d Update version to v0.18.0
- Updated dependencies
2024-04-04 22:44:20 +03:00
VaDiM
5120999026 Update readme and other text files 2024-04-04 21:55:59 +03:00
VaDiM
1fc504e587 Optimize memory consumption of swizzled textures 2024-04-02 00:40:24 +03:00
VaDiM
4e991d85fb More fixes for unity 2019.4 assets 2024-04-01 00:56:48 +03:00
VaDiM
29b4bb59a0 [GUI] Move "loading via typetree" option to a better place 2024-04-01 00:56:48 +03:00
VaDiM
9750f486d5 Fix moc3 export 2024-04-01 00:21:51 +03:00
VaDiM
97bbfe8fbb Fix type of public "offset" property in ResourceReader 2024-04-01 00:21:50 +03:00
VaDiM
684bf5a874 Show assumed unity ver in some cases for assets with stripped ver 2024-04-01 00:21:50 +03:00
VaDiM
3cc6bed844 Raplace Unity ver array with Unity ver class 2024-04-01 00:21:50 +03:00
VaDiM
c9e9bc840c Add parallel export support for some asset types 2024-04-01 00:21:50 +03:00
VaDiM
cadcf0b492 Fix displayed info for non-fmod audio clips 2024-03-28 01:52:43 +03:00
VaDiM
1e8085da2d Fix AssetBundle structure for Unity v5.4.x. Close #31 2024-03-28 01:52:43 +03:00
VaDiM
770d7e7532 [GUI] Fix compatibility with High Contrast modes 2024-03-15 18:19:05 +03:00
VaDiM
d0d8a35f67 [GUI] Fixes for Tex2DArrayImage 2024-03-14 00:42:56 +03:00
VaDiM
3f004f74d1 Add option to disable asset loading via typetree 2024-03-13 22:52:43 +03:00
VaDiM
3effd06e64 Unity 2023.2+ Texture2D fix 2024-03-13 22:52:43 +03:00
VaDiM
4f0afffeba Add AnimationClip loading via typetree 2024-03-13 22:52:43 +03:00
VaDiM
9b69b5607c Fix DisplayInfo default value in model3.json 2024-03-10 23:17:25 +03:00
VaDiM
9b16ea8d41 Fix bug with Blend type in l2d expressions 2024-03-09 22:47:11 +03:00
VaDiM
ae4548f1c3 Add support for swizzled Switch textures
Co-Authored-By: nesrak1 <12544505+nesrak1@users.noreply.github.com>
2024-03-09 02:35:23 +03:00
VaDiM
4cd246592b [CLI] Fix wrong error handler. Fix option description msgs 2024-03-07 04:38:39 +03:00
VaDiM
f54cc004bd Add support for Zstd block compression 2024-03-07 03:49:06 +03:00
VaDiM
afdc81bca8 Some minor fixes 2024-03-05 23:42:35 +03:00
VaDiM
045f6c0ff4 Add Texture2DArray loading via typetree 2024-03-05 23:42:29 +03:00
VaDiM
bc9380b8be Add Texture2D loading via typetree 2024-03-05 23:42:29 +03:00
VaDiM
46f8023756 [GUI] Improve export of Texture2DArray images
- Do not export an entire tex2darray array if both the tex2darray and some of its images were selected for exporting
2024-03-05 23:42:07 +03:00
VaDiM
0f9afa60d7 Add support for Texture2DArray 2024-03-04 19:46:28 +03:00
VaDiM
ec7f2c393d [CLI] Update readme 2024-02-13 05:43:34 +03:00
VaDiM
3ec8169b08 [GUI] Add more details to log when exporting assets 2024-02-13 04:55:25 +03:00
VaDiM
5c24183d18 Add more options to work with Scene Hierarchy (#23)
- Added option to group exported assets by node path in scene hierarchy
- Added field with node path to exported xml asset list
2024-02-13 04:52:59 +03:00
VaDiM
c68eaa5e3c Fixes for previous fixes 2024-02-13 04:51:14 +03:00
VaDiM
8460ecef8d Show/Export object dump if typetree dump is not available 2024-02-12 05:21:23 +03:00
VaDiM
f90c0ecc00 Add option to export assets with PathID in filename (#25)
https://github.com/Perfare/AssetStudio/issues/1050
https://github.com/Perfare/AssetStudio/issues/975
https://github.com/Perfare/AssetStudio/issues/762
2024-02-11 03:01:40 +03:00
VaDiM
535153be6b Add cdi3.json support for l2d export (beta) 2024-02-09 22:35:14 +03:00
VaDiM
d4162161be [GUI] Replace "Show all error msgs" option with "Show debug msgs" 2024-02-08 22:44:57 +03:00
VaDiM
6fe12d274f [CLI] Add colors to help message 2024-02-08 22:35:48 +03:00
VaDiM
70213e3012 Improve integration with Live2D assets
- Improved export method of AnimationClip motions
- [GUI] Added display of model info on the preview tab
- [GUI] Added support for partial export:
  - selected models
  - model + selected AnimationClip motions
  - model + selected Fade motions
  - model + selected Fade Motion List
2024-02-08 22:34:00 +03:00
VaDiM
2f6d9ec77f Fixes & Cleanup 2024-01-31 22:34:12 +03:00
VaDiM
0d2aebc1f4 Fix a bug where UV is exported incorrectly.
Co-Authored-By: Razmoth <32140579+razmoth@users.noreply.github.com>
2024-01-24 23:26:13 +03:00
VaDiM
115074fdc0 [GUI] Preserve selection order of AnimationClips (#24) 2023-12-30 18:51:01 +03:00
VaDiM
c2d3b8c5f9 Improve Live2D export 2023-12-30 18:13:40 +03:00
VaDiM
67a74fd395 Bugfix for unity 2022.2+ Texture2D reader 2023-12-30 17:08:07 +03:00
VaDiM
a00c857ac3 Update version to v0.17.4 2023-12-16 04:41:00 +03:00
VaDiM
5333757843 Update dependencies 2023-12-16 04:16:36 +03:00
VaDiM
4747687bec Update README.md 2023-12-15 15:11:48 +03:00
VaDiM
5c2ac1a5e8 Add .NET8 to the TargetFrameworks 2023-12-15 14:45:07 +03:00
VaDiM
e2eae53ac0 Update Live2DExtractor.cs 2023-12-15 01:24:54 +03:00
VaDiM
87347e8b60 [CLI] Update readme 2023-12-11 01:58:05 +03:00
VaDiM
0fdbddea55 [CLI] Fix asset filter for sprites 2023-12-11 01:58:00 +03:00
VaDiM
823190abb7 Improve parsing of Live2D Fade motions 2023-12-09 02:31:54 +03:00
VaDiM
60aef1b8ed [GUI] Add option to not build a tree structure 2023-12-09 02:25:59 +03:00
VaDiM
f82a73f018 [GUI] Add console logger 2023-12-06 17:28:10 +03:00
VaDiM
d42a1879ab [GUI] Add support for Drag&Drop files from a browser
Co-Authored-By: Luke <17146677+lukefz@users.noreply.github.com>
2023-12-05 00:38:24 +03:00
VaDiM
632e5f8d08 [GUI] Add support for .lnk files via Drag&Drop. Close #13 2023-12-04 04:10:49 +03:00
VaDiM
51d259464b Merge branch 'pr/16' into AssetStudioMod 2023-11-21 02:15:19 +03:00
VaDiM
efd06648ad Add support for separate PreloadData
https://github.com/Perfare/AssetStudio/issues/690

https://docs.unity.cn/550/Documentation/Manual/AssetBundleInternalStructure.html
2023-11-21 01:35:25 +03:00
VaDiM
b27482e22b Don't display SourceRevisionId in titles
https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/8.0/source-link
2023-11-21 00:31:09 +03:00
VaDiM
d572bd0e64 Add support for Live2D Fade motions 2023-11-20 19:56:41 +03:00
VaDiM
e415740373 Some fixes for Live2D export 2023-11-19 02:51:48 +03:00
VaDiM
45bf9251c9 Fix crash when SpriteAtlas is missing 2023-11-07 01:31:27 +03:00
Evaldas Ciakas
75ebe67713 Fix parsing secondary textures 2023-11-01 02:29:06 +02:00
VaDiM
ed7b0a2415 Unity 2022.2+ AnimationClip fix 2023-09-27 23:41:20 +03:00
VaDiM
22ab5c0633 Update README.md
- Added ArknightsStudio link
2023-09-24 16:19:09 +03:00
VaDiM
a2bc935850 [CLI] Improve help message 2023-09-24 16:14:26 +03:00
VaDiM
cb84c137e5 Add exception checking for gzip decompression 2023-09-24 10:41:19 +03:00
VaDiM
25c611fb9e Update README.md 2023-09-15 16:35:47 +03:00
VaDiM
6d3875cb2c Update version to v0.17.3 2023-09-13 10:55:57 +03:00
VaDiM
be4ced77ea Update readmes 2023-09-12 03:44:18 +03:00
VaDiM
2bd762e8f4 [CLI] Add names for AssetBundle and Animator assets 2023-09-12 03:33:59 +03:00
VaDiM
a926644ff6 [CLI] Add --load-all flag
- Added --load-all flag to load assets of all types
- Improved option grouping on the help screen
2023-09-12 03:33:53 +03:00
VaDiM
a4cdff5934 Fix a bit of incorrect copy-paste
in commit e216abd6be
2023-09-08 23:47:26 +03:00
VaDiM
2e10e627b0 AssemblyLoader fix (#6) 2023-09-08 06:18:41 +03:00
VaDiM
e216abd6be Unity 2022.2+ Texture2D fix 2023-09-08 06:18:34 +03:00
VaDiM
93c7e617d8 [CLI] Show names of all loaded assets in the exported asset list 2023-09-08 06:18:34 +03:00
VaDiM
000916913e [CLI] Fix a bug where the default output folder might not exist 2023-09-08 06:17:34 +03:00
VaDiM
28f9744497 Update README.md 2023-09-08 06:17:34 +03:00
VaDiM
c3f99216b6 [CLI] Add --filter-by-name support for fbx export mode 2023-09-08 01:45:25 +03:00
VaDiM
19c4835ea3 Merge branch 'pr/10' into AssetStudioMod 2023-09-05 19:38:04 +03:00
VaDiM
6b321da695 [CLI] Add FBX native libs (Linux, Mac) 2023-09-05 00:48:44 +03:00
svn
7cca301f7a Add split object fbx export to CLI 2023-08-31 21:07:02 +01:00
svn
5ac597c935 Add CMakeLists for cross platform FBXNative build 2023-08-31 21:03:07 +01:00
VaDiM
171962e61f Update version to v0.17.2
- Updated projects and dependencies
2023-08-27 01:47:06 +03:00
VaDiM
c8a21838c9 Some changes to motion list for l2d models
- Motion list is now sorted
- Motions divided into groups (each motion is a separate group)
- Motion names are used as group names
2023-08-27 01:46:06 +03:00
VaDiM
cf67815d53 Minor fixes 2023-08-26 03:22:19 +03:00
VaDiM
94c8b355fe [CLI] Fix asset filter
- Fixed sprite export in sprite only mode
2023-08-14 00:46:27 +03:00
VaDiM
4e41caf203 [CLI] Refactor 2023-08-13 20:58:26 +03:00
VaDiM
74a8555514 Merge branch 'relatedAssets' into AssetStudioMod 2023-08-07 23:20:11 +03:00
VaDiM
e1d883adf6 [CLI] Refactor
- Made some classes static
2023-08-07 23:10:57 +03:00
VaDiM
9784df0e16 [GUI] Add app.manifest for net472 build
- Added long paths support (win10 v1607+)
- Fixed blurring at high DPI with scaling
2023-08-06 20:08:05 +03:00
VaDiM
4d919a2bfe [GUI] Improve Scene Hierarchy tab context menu
- Added "Related assets" item to the context menu
2023-08-05 18:10:36 +03:00
VaDiM
6701f467b7 [CLI] Show the number of successfully loaded assets 2023-07-14 20:20:58 +03:00
VaDiM
50f5da5554 [GUI] Don't count Shaders in unity 2021+ assets 2023-07-14 19:17:56 +03:00
VaDiM
2b6dcca9c8 Update readme files, add CHANGELOG.md 2023-07-12 04:54:30 +03:00
VaDiM
0bdcb89b08 Update version to v0.17.1 2023-07-09 05:59:39 +03:00
VaDiM
dcd7b98229 Some minor fixes 2023-07-09 05:59:33 +03:00
VaDiM
007e5c7e4d [CLI] Update ReadMe.md 2023-07-08 11:48:58 +03:00
VaDiM
63564d5fff Add assembly folder support for Live2D export 2023-07-02 23:40:04 +03:00
VaDiM
aea6cbc97f Add option to export Live2D Cubism models 2023-07-02 23:20:14 +03:00
VaDiM
6d41693b85 Update dependencies 2023-06-27 00:27:41 +03:00
Pierce Thompson
5695afae7b Add support for exporting meshes from the CLI (#5)
* Add support for exporting meshes from the CLI

* Add the Mesh ClassIDType to CLIOptions' supportedAssetTypes
2023-06-23 15:37:40 +03:00
VaDiM
bb9ea7d86b Update version to v0.17.0 2023-06-05 02:03:28 +03:00
VaDiM
547659e151 [GUI] Display progress in the taskbar button 2023-06-05 01:33:48 +03:00
VaDiM
2f8f57c1a6 [GUI] Improve file and folder loading (drag&drop)
- Added support for drag&drop of multiple folders
- Open/Export dialog can now also use a path taken from drag&drop items
2023-05-29 05:14:50 +03:00
VaDiM
b7d5d73f23 [GUI] Fix audio player position in maximized window 2023-05-29 04:35:38 +03:00
VaDiM
f0c237473c [GUI] Some fixes for asset list filtering 2023-05-29 04:20:57 +03:00
VaDiM
09947fd14f [CLI] Update ReadMe.md 2023-05-23 16:21:38 +03:00
VaDiM
da216dace8 Improve "Restore TextAsset extension name" option
- If checked, AssetStudio will first try to find an extension in an asset's name and only then in its container. If no extension is found, ".txt" will be used
2023-05-23 16:18:24 +03:00
VaDiM
c7356875f9 Add grouping option with full container path
* [GUI] - "container path full (with name)"
* [CLI] - "containerFull"
(https://github.com/Perfare/AssetStudio/issues/815)
2023-05-23 16:17:00 +03:00
VaDiM
02e46eaa0d [GUI] Improve asset list filtering
- Added filter history
- Added more filtering modes: Include, Exclude, Regex (Name/Container)
2023-05-18 23:45:54 +03:00
VaDiM
b0bf5e0cfd Optimize drawing performance of packed sprites
- Restored some code from an earlier version (e501940f03), since it works faster for packed sprites with a small number of triangles
2023-05-15 00:07:46 +03:00
VaDiM
11b9ca37da Fix cutout glitch in some packed sprites
- Improved performance
(https://github.com/Perfare/AssetStudio/issues/1015)
2023-05-15 00:06:52 +03:00
VaDiM
5944dd8c58 [GUI] Fix typo
merge https://github.com/Perfare/AssetStudio/pull/1009

Co-Authored-By: Dirk Kok <the@dirkkok.nl>
2023-05-13 12:55:12 +03:00
VaDiM
1c67e39504 [GUI] Add "About" window & update titles 2023-05-13 12:46:43 +03:00
VaDiM
2d81007556 [GUI] Improve de-selection in Scene Hierarchy tab
- improved de-selection perfomance
- selected objects count is now displayed in the status bar
- "Select none" renamed to "Clear selection"
2023-04-26 09:57:38 +03:00
VaDiM
4bae98813b [GUI] One more bugfix
- bugfix for 44a1240f5f
2023-04-13 22:08:01 +03:00
VaDiM
90ec395b2a Block alignment fix for Unity 2019.4.X
- src: 10346b4f02
2023-04-09 15:40:34 +03:00
VaDiM
af3684bab8 [GUI] Bugfix
- bugfix for ea09a8de64
2023-04-06 02:14:53 +03:00
VaDiM
1da51ac95b Add error message on incorrect format of specified unity ver 2023-03-20 19:32:00 +03:00
VaDiM
9e14f1ef00 Add error message for bundles with CN encryption 2023-03-20 19:31:49 +03:00
VaDiM
4edadb19f8 Disable Shader support for Unity > 2020 2023-03-20 06:13:08 +03:00
VaDiM
44a1240f5f [GUI] Improve memory usage of image previews
- also a bit increased performance of alpha mask resizing for previews
2023-03-14 04:10:48 +03:00
VaDiM
01957a9443 [CLI] Add draft readme 2023-03-10 21:18:29 +03:00
VaDiM
ad1b3b4911 [CLI] Some fixes for logging 2023-03-10 21:01:12 +03:00
VaDiM
0925751776 [CLI] Add MovieTexture support 2023-03-10 19:37:53 +03:00
VaDiM
b59ba3ba94 [GUI] Add some videoClip info to preview tab 2023-03-10 11:53:38 +03:00
VaDiM
67898c72ca Update projects files
- Fixed build options
2023-03-10 09:01:27 +03:00
VaDiM
0425423ca9 [CLI] Add debugging info for video 2023-03-08 19:59:19 +03:00
VaDiM
16a7107d4e [CLI] Partial assets reading 2023-03-08 18:28:50 +03:00
VaDiM
10b7e84ffb [CLI] More debugging info for audio 2023-03-08 17:31:34 +03:00
VaDiM
679e7041a6 [GUI] A bit better(?) error handling 2023-03-08 17:12:59 +03:00
VaDiM
629c6248a4 [GUI] Use blocking call to show messages in correct order 2023-03-08 12:11:45 +03:00
VaDiM
7674081df7 [GUI] Add context menu to the Scene Hierarchy tab
- Added context menu with "Select all", "Select none", "Expand all", "Collapse all" options to the "Scene Hierarchy" tab.
https://github.com/aelurum/AssetStudio/issues/1
2023-03-07 18:21:34 +03:00
VaDiM
fb574064c9 [GUI] Avoid overflow in alphanum sorting 2023-03-07 06:55:45 +03:00
VaDiM
c52940abc4 Add AssetStudioCLI project
- Updated projects and dependencies
2023-03-07 06:52:33 +03:00
VaDiM
5c662d64e4 Add exclude mode to asset list filter 2023-02-05 00:47:04 +03:00
VaDiM
b9cf95616b SwapBytesForXbox refactor 2023-01-27 13:46:55 +03:00
VaDiM
39490d4e03 Update fmod to 0.2.0.22 (CLI Preparation) 2023-01-27 13:17:01 +03:00
VaDiM
a96d1a5d5d Fix bug in alphanum sorting 2022-12-27 05:21:42 +03:00
VaDiM
568daafc7f Add progress info to LoadZipFile()
Displays the progress of loading zip(apk) files on the progress bar
2022-12-15 17:43:28 +03:00
VaDiM
2a2216e2bf Update projects and dependencies 2022-12-10 20:23:45 +03:00
VaDiM
dfbe46e1e5 Improve sorting performance
Improved performance of AlphanumComparatorFast sorting for names, as well as the default sorting for containers
2022-12-03 05:16:19 +03:00
VaDiM
6a9aad510c Add image export in WebP format 2022-11-22 03:33:47 +03:00
VaDiM
fd21cafd29 Merge branch 'Perfare_master' into AssetStudio-mod 2022-11-21 02:37:02 +03:00
VaDiM
ea09a8de64 Add support for sprites with alpha mask
- Sprites with alpha mask can now be viewed and exported with transparency
- Added hotkeys to control display of an alpha mask  on the preview tab
- Added an option to the export settings to enable/disable export with alpha mask as well
- Prevented texture2D preview options from being changed with hotkeys outside of texture preview (e.g. when some other asset is selected)
2022-11-21 01:59:16 +03:00
VaDiM
7fa5b4f355 Update ImageSharp.Drawing version
- migrate to ImageSharp v2+
2022-11-18 06:33:26 +03:00
VaDiM
c22d92009a Update project files 2022-11-17 04:39:49 +03:00
Perfare
53f3e8232a support 2022.1 2022-11-17 04:32:05 +03:00
Perfare
2fe57a1c5d update enum 2022-11-17 04:31:30 +03:00
Perfare
ded2dcd54e Fixed #962 2022-11-17 04:31:16 +03:00
Perfare
8ae3df6197 minor improvements 2022-11-17 04:30:52 +03:00
Kanglai Qian
64d9718c34 avoid useless search for non exist files (#967) 2022-11-17 04:30:39 +03:00
Perfare
220004c976 support 2021.3 2022-11-17 04:30:27 +03:00
Perfare
a324366be9 BundleFile fix 2022-11-17 04:30:17 +03:00
Perfare
06b4ae9ffe Fix type conversion bug 2022-11-17 04:29:55 +03:00
Perfare
77b056de5e update project file 2022-11-17 04:29:02 +03:00
Perfare
344edb722f revert 2022-11-17 04:23:17 +03:00
Perfare
98c4d0c3ab minor fixes and improvements 2022-11-17 04:23:00 +03:00
Perfare
23ac590648 Fixed #941 2022-11-17 04:22:31 +03:00
Perfare
54445475a3 Fix and improve Texture2D convert 2022-11-17 04:22:14 +03:00
Perfare
7299bcba6d Create build.yml 2022-11-17 04:22:06 +03:00
Perfare
5487ff4e60 Fixed #924 2022-11-17 04:21:13 +03:00
Perfare
b3621a75b0 Fixed #929 2022-11-17 04:20:20 +03:00
Perfare
8b048b9e1e improved Sprite export
Fixed #944
Fixed #923
2022-11-17 04:20:20 +03:00
Perfare
41a79f485f using IProgress 2022-11-17 04:18:40 +03:00
Perfare
a060a392e7 Fixed #919 2022-11-17 04:18:06 +03:00
Rudolf Kolbe
0798af7c5c fix apk loading issues (#913)
* fix apk loading issues

Someone contacted me some days ago and notified me that some problems showed up with my APK loading implementation.
Namely:

file reference registration (importFilesHash) was missing
split files weren't handled
external resource files weren't registered
This pr fixes those problems.

* revert weird changes

* fix missing }

* fix formatting

* use entry.FullName for the basePath instead of entry.Name
2022-11-17 04:17:33 +03:00
VaDiM
8ebfa16e19 Return to ImageSharp
coz the perfomance issue was fixed by Perfare in later commits
2022-11-17 03:59:59 +03:00
Perfare
d158e864b5 support 2022.1 2022-06-16 18:41:55 +08:00
Perfare
b70b5196e3 update enum 2022-06-16 17:45:54 +08:00
Perfare
4f88841026 Fixed #962 2022-06-01 15:33:01 +08:00
Perfare
dc9429feac minor improvements 2022-05-21 21:16:34 +08:00
Kanglai Qian
a3c16ed3d6 avoid useless search for non exist files (#967) 2022-05-21 21:10:02 +08:00
Perfare
5b83eebdda support 2021.3 2022-05-21 17:38:40 +08:00
Perfare
1fcf7a4364 BundleFile fix 2022-05-21 17:24:54 +08:00
Perfare
973d50ce8b Fix type conversion bug 2022-05-21 05:46:44 +08:00
Perfare
50485a9bd3 update project file 2022-03-24 10:38:52 +08:00
Perfare
dbb3d3fef7 revert 2022-03-24 09:47:36 +08:00
Perfare
e1cfff63c3 minor fixes and improvements 2022-03-23 01:41:59 +08:00
Perfare
44514a4e10 Fixed #941 2022-03-22 22:54:49 +08:00
Perfare
b1205808e2 Fix and improve Texture2D convert 2022-03-22 01:00:20 +08:00
Perfare
7d3a4a10fc Create build.yml 2022-03-20 02:36:32 +08:00
Perfare
b909857820 Fixed #924 2022-03-19 08:06:03 +08:00
Perfare
b674e66407 Fixed #929 2022-03-19 07:48:39 +08:00
Perfare
d7dcd3f405 improved Sprite export
Fixed #944
Fixed #923
2022-03-19 07:43:53 +08:00
Perfare
44145e0b9c using IProgress 2022-03-19 06:40:51 +08:00
Perfare
d4e21f824c Fixed #919 2022-02-17 01:07:24 +08:00
Rudolf Kolbe
e7a4604a65 fix apk loading issues (#913)
* fix apk loading issues

Someone contacted me some days ago and notified me that some problems showed up with my APK loading implementation.
Namely:

file reference registration (importFilesHash) was missing
split files weren't handled
external resource files weren't registered
This pr fixes those problems.

* revert weird changes

* fix missing }

* fix formatting

* use entry.FullName for the basePath instead of entry.Name
2022-02-15 11:19:50 +08:00
VaDiM
74f2c3190b Merge branch 'Perfare_master' into AssetStudio-mod 2022-01-13 18:10:31 +02:00
Rudolf Kolbe
8d193a63cd Zip (including APK) Loading (#902)
* load ZipFile

makes it possible to directly load apk files

* use LoadFile for recursive zip opening

* set System.IO.Compression version

* keep identical format in AssetStudio.csproj

* try/catch the loading of each zip entry

* remove extra new line in FileReader.cs

* apply requested changes
2021-12-27 15:59:18 +08:00
brianpow
e61a317185 use FullPath instead of FileName for easier identification of broken file (#900)
* use FullPath instead of FileName for easier identification of broken file.

* use FullPath instead of FileName for easier identification of broken file
2021-12-24 13:23:09 +08:00
VaDiM
f67965b1dd Texture2DDecoderNative - Linux/macOS compatibility fix
+ CMakeLists.txt
2021-12-15 02:49:28 +02:00
VaDiM
07a81d9bfe Update projects 2021-12-15 00:35:46 +02:00
VaDiM
95fd1823c8 Merge branch 'Perfare_master' into AssetStudio-mod 2021-12-13 04:45:41 +02:00
VaDiM
d25451d5b9 Merge branch 'Perfare_master' into AssetStudio-mod 2021-12-13 00:43:49 +02:00
scriptkitz
0e1a886e0b 修正UV导出计算错误问题。 (#891) 2021-12-11 15:48:54 +08:00
Perfare
97b5f51f3a Fix build 2021-12-09 20:23:25 +08:00
Perfare
7295feda72 Update README.md 2021-12-09 19:16:13 +08:00
Perfare
fe95c91759 Add net6.0 target framework 2021-12-09 19:00:59 +08:00
Perfare
d220315d9b Add detailed export progress in the status bar 2021-12-09 18:08:56 +08:00
Perfare
a94caa5e34 Update project 2021-12-09 17:21:44 +08:00
Perfare
3660b4ed67 Some improvements 2021-12-09 17:13:21 +08:00
Perfare
3370f93037 Fixed bug 2021-12-06 17:37:59 +08:00
Perfare
80653711cd Performance improvement 2021-12-06 13:36:22 +08:00
VaDiM
f0b23bbfe7 Merge branch 'Perfare_master' into AssetStudio-mod 2021-12-05 02:41:24 +02:00
Perfare
88c5804586 Fixed #886 2021-12-04 09:23:41 +08:00
Perfare
e501940f03 Use a better way to crop Sprite 2021-12-04 08:44:33 +08:00
Perfare
d4060cde6d Fixed bug 2021-12-04 02:05:35 +08:00
Perfare
582a779441 Update project file 2021-12-03 19:46:20 +08:00
Perfare
5fa4934787 Add net5.0 target framework 2021-12-03 17:21:24 +08:00
Perfare
18277fbea8 fixed bug 2021-12-03 17:05:06 +08:00
VaDiM
571ea2da4a Don't use ImageSharp for texture processing
- returned to System.Drawing
(ImageSharp is a good lib, but too slow for such app, IMO)
2021-11-24 19:30:38 +02:00
VaDiM
9cbe91decb Improve sorting by asset names
- added alphanumeric sorting for more natural presentation of asset list
2021-11-24 14:56:28 +02:00
VaDiM
19c6c5fe73 Minor UI improvments & bugfixes
- improved "Copy text" option in right click menu, to display what exactly to copy
- added "Dump selected assets" option to right click menu
- added 'selected assets count' info to status strip when you select assets
- added 'exported count / total export count` info to status strip during export
- "Show error message" option on the "Debug" tab renamed to "Show all error messages" and is now disabled by default
- "fixed" an issue with getting stuck during the "Building tree structure" step
- fixed a bug with listSearch that could make it not work in some conditions
- fixed a rare bug for resource files with the same name, that caused their data to be overwritten and become incorrect
2021-11-24 14:55:38 +02:00
VaDiM
792850dbb2 Update projects 2021-11-22 16:00:51 +02:00
Perfare
2ce9cae957 Modify the prompt statement 2021-11-20 03:11:02 +08:00
Perfare
af5e50cfa9 Update README.md 2021-11-20 02:52:53 +08:00
Perfare
ce1172ca9a rename. closed #817 2021-11-19 18:24:18 +08:00
Perfare
a7e6d91f5b Fixed bug 2021-11-19 18:22:39 +08:00
Perfare
34a0af683a Fixed bug 2021-11-19 18:11:00 +08:00
Perfare
91410a33b1 Improve the handling of compressed files. 2021-11-19 17:54:06 +08:00
Perfare
d08b78c2cf support 2021.2 2021-11-12 10:25:22 +08:00
Perfare
2ef52afe1e Fixed #835 2021-11-12 09:30:12 +08:00
Perfare
05a41d2f1e Merge pull request #855 from nikitalita/fix-assembly-loading
Fix AssemblyLoading bug
2021-11-08 09:36:03 +08:00
nikitalita
34c38e1415 Fix AssemblyLoading bug
If the AssemblyLoader attempted to load a non-csil dll
while iterating through the file list, it would catch the exception
OUTSIDE the loop, and wouldn't load the rest.
This fix makes it catch inside the loop so it will continue iterating.
2021-10-07 13:36:03 -07:00
Perfare
c85873b729 0.16.0 2021-07-06 16:03:54 +08:00
Perfare
b146d251a7 add option to not show error message 2021-07-06 15:57:59 +08:00
Perfare
3129d67fc1 Improve ShaderConverter 2021-07-06 12:45:24 +08:00
Perfare
850ba63a10 support exporting VideoClips with a size above 2gb. close #765 2021-07-02 03:26:46 +08:00
Perfare
17b91984d6 fixed bug 2021-07-02 02:29:03 +08:00
Perfare
7ab2cda120 refactor the file reading part 2021-07-02 02:17:59 +08:00
Perfare
4345885cc9 remember the last opened path, close #646 2021-06-30 22:41:16 +08:00
Perfare
53720e37ab Fixed #435 2021-06-30 06:31:05 +08:00
Perfare
7c3cb36630 update project files 2021-06-29 11:03:19 +08:00
Perfare
c1cddce031 added option to support version stripped files, close #766 2021-06-29 10:32:19 +08:00
Perfare
973a1076e4 support exporting AnimationClip versions below 4.3 2021-06-29 02:43:42 +08:00
Perfare
089e164756 improved Sprite export 2021-06-28 07:14:02 +08:00
Perfare
c2b6691fd9 fix build 2021-06-27 09:42:13 +08:00
Perfare
8dec094304 update project files 2021-06-27 09:27:40 +08:00
Perfare
bedee240be Use ImageSharp to process textures 2021-06-27 07:33:20 +08:00
Perfare
d963d71b12 clean up TypeDefinitionConverter code 2021-06-26 13:16:12 +08:00
Perfare
77a0c9c40a Fbx multiple uv export 2021-06-24 13:48:56 +08:00
Perfare
f3e406983b Merge pull request #768 from Fraxul/master
Fix blend shape export with multiple submeshes
2021-06-24 12:59:31 +08:00
Dan Weatherford
08b7bfcf9a Fix blend shape export with multiple submeshes
Share a single vertex list between submeshes in the exported mesh, which
makes the blend target vertex list indices line up correctly.

As a bonus, the exported FBX file will be smaller for meshes with more
than one submesh, since we're not duplicating vertices anymore.
2021-06-20 00:18:22 -05:00
Patrick King
57e4f7cefd Add an option to export all UVs as diffuse maps. 2021-06-11 17:12:15 -06:00
Patrick King
c9cf2d188e Enable FBX export for higher UV maps. 2021-06-11 14:26:37 -06:00
Perfare
ab98585b6a Fix Shader reading. Close #720 2021-05-29 05:11:05 +08:00
Perfare
075d53a455 small improvement 2021-05-28 23:19:31 +08:00
Perfare
432116d834 Improve SerializedFile reading. 2021-05-28 22:23:07 +08:00
Perfare
caa45216ef fix compilation error 2021-05-28 22:16:50 +08:00
Perfare
c9394cd957 Fixed #734 2021-05-28 03:49:46 +08:00
Perfare
46c0e8ffe1 Improve stream file processing 2021-05-28 03:43:32 +08:00
Perfare
d14c232015 Improve the error message 2021-05-28 03:27:50 +08:00
Perfare
4002bdecb8 Update README.md 2021-05-27 03:55:37 +08:00
StarHeart
17259e00c7 correct grammar (#749) 2021-05-27 03:49:40 +08:00
Perfare
44b02b92d8 fix lzma decompression 2021-05-27 03:46:15 +08:00
Joshua May
251854cc41 Adds exporter for list of assets to XML (#710) 2021-04-18 01:27:15 +08:00
Perfare
6f7b77245d Merge pull request #639 from sk-zk/nul-fix
[GUI] Fix \0 chars in TextAssets cutting off preview
2021-04-18 01:21:16 +08:00
Perfare
6d99f5ebf6 Improve vertex format parsing. Close #689 2021-04-12 15:11:17 +08:00
Perfare
f1f2430f97 Support 2021.1 2021-04-11 23:49:44 +08:00
Perfare
b52696c965 Merge pull request #713 from K0lb3/patch-1
Update ClassIDType according to official reference
2021-04-11 21:54:45 +08:00
K0lb3
5fba52dc83 Update ClassIDType according to official reference
I noticed that Unity has made a [ClassID Reference table](https://docs.unity3d.com/Manual/ClassIDReference.html) and thought that copying it over here might be useful for dumps.
2021-03-28 14:24:20 -07:00
Perfare
dfb74baf79 Fix for mesh weights output 2021-01-15 09:32:57 +08:00
Perfare
978e90a403 Fix if AudioClip does not contain subsound. Close #672 2021-01-15 05:39:45 +08:00
Perfare
c17d7d6331 Update README.md 2021-01-15 04:38:54 +08:00
Perfare
9fef18d6ea fixes bug 2021-01-15 04:33:54 +08:00
Perfare
ee0cd4ab52 Fixed #609 2021-01-15 03:43:52 +08:00
Perfare
f904bc138b typo 2021-01-15 02:17:11 +08:00
Perfare
7ed5345b1b Fixed #652 2021-01-15 02:12:54 +08:00
Perfare
d7f652d572 improved Sprite export 2021-01-14 19:27:57 +08:00
Perfare
32ce032655 Support 2020.2 2021-01-14 05:23:19 +08:00
Perfare
e1cf36aa3c Fixed #650 2020-12-14 21:20:04 +08:00
sk-zk
f644396a15 Fix \0 chars in TextAssets cutting off preview 2020-10-30 23:08:06 +01:00
Perfare
3e77c34bd5 Fixed #618 2020-09-29 07:08:14 +08:00
Perfare
052c60f629 Fix file occupation conflict 2020-09-26 23:29:38 +08:00
Perfare
a1f2e3e7fe Merge pull request #613 from Ishotihadus/master
Problems in exporting fbx with multiple blendshapes
2020-09-26 10:18:42 -05:00
Ishotihadus
32ee8b326f fix problems in exporting fbx with multiple blendshapes 2020-09-16 19:44:11 +09:00
Perfare
06ce479eb6 Fixes #591 2020-08-26 09:50:25 +08:00
Perfare
03f74bac64 Fix BlendShape output error 2020-08-24 22:00:53 +08:00
Perfare
344b675745 Update README.md 2020-08-16 18:53:55 +08:00
Perfare
86590d95a5 Add dump viewer 2020-08-14 17:38:43 +08:00
Perfare
bbea1341b2 Update README.md 2020-08-14 15:50:45 +08:00
Perfare
ca60dd9834 Support exporting MonoBehaviour to json. Close #477 2020-08-14 15:45:48 +08:00
Perfare
7aa35b5b8c Fix get class from divided UnityEngine.dll 2020-08-14 01:31:49 +08:00
Perfare
bd2decdb8f Fix element alignment errors 2020-08-14 01:18:43 +08:00
Perfare
9b2c85bcae Refactor MonoBehaviour reading 2020-08-14 00:02:59 +08:00
Perfare
efbab7c43a using Nuget 2020-08-12 22:22:04 +08:00
Perfare
729a8a8263 implemented SPIR-V shader export 2020-08-12 22:11:26 +08:00
Perfare
0ec29f62ca Improve shader conversion, fixes #589 2020-08-12 20:49:36 +08:00
Perfare
796317f9d9 support 2020.1 2020-08-12 19:13:10 +08:00
Perfare
7596dcc7cd keep path when extracting folder 2020-08-12 02:55:02 +08:00
Perfare
422851cdab Fix mesh index errors 2020-08-12 02:24:08 +08:00
Perfare
ec0a2a47f1 can choose the directory to save the extracted files 2020-08-10 14:07:29 +08:00
Perfare
8ce5b947f6 Update README.md 2020-08-10 11:01:37 +08:00
Perfare
419ca63f9d Set Runtime Library to /MT 2020-08-10 09:52:09 +08:00
Perfare
6fdb0c7b0e add ResourceManager 2020-08-06 23:17:44 +08:00
Perfare
4e97b4b898 improve export 2020-08-06 21:07:37 +08:00
Perfare
1766dcbdeb Fixed #570 2020-08-06 13:31:17 +08:00
Perfare
ef38471ff1 move code 2020-08-06 13:11:41 +08:00
Perfare
217a7993e9 fixed bug 2020-08-06 12:56:47 +08:00
Perfare
0a41615763 fix UV problems 2020-08-06 12:34:59 +08:00
Perfare
9d34f668d5 modify project file 2020-08-06 11:59:35 +08:00
Perfare
9269a36725 Merge pull request #555 from Jayatubi/allowdrag
Allow drag and drop files or folder
2020-08-05 21:42:32 -05:00
Jayatubi
813e8b10a6 Export local keywords of shader as well as global keywords (#554)
* Export local keywords of shader

* Export local keywords of shader
2020-08-06 10:39:48 +08:00
Tahvohck
84c75fadf5 Sort code for PathID (change to numeric) (#550)
* Sort code for PathID (change to numeric)

* Remove comments (were only for reference)

* Match Perfare formatting
2020-08-06 10:38:12 +08:00
hozuki
c76e41b1ab Replace C++/CLI components with P/Invoke components (#562)
* Replace C++/CLI components with P/Invoke

* Deleted C++/CLI projects

* Use Utf8StringHandle to marshal UTF-8 strings

* Use plaform-default calling convention

* Handle DLL preloading on Linux and macOS

* Change intermediate and output directories of native projects

* Improve P/Invoke documentation
2020-08-06 10:35:50 +08:00
jayatubi
fefeea5f35 Allow drag and drop files or folder 2020-05-18 14:17:42 +08:00
Perfare
4a81c461e8 Modify Sprite processing function as an extension function 2020-04-10 18:57:04 +08:00
Perfare
b10d03d50d fixed bug 2020-04-10 18:51:43 +08:00
Perfare
da98a0c5b8 fixed bug 2020-04-10 18:20:45 +08:00
Perfare
76d17bacf5 improve type read 2020-04-10 18:11:56 +08:00
Perfare
6678ce082b refactor BundleFile read 2020-04-07 16:13:04 +08:00
Perfare
07074b3deb improve SerializedFile read 2020-04-07 08:59:04 +08:00
Perfare
df5d9f90d4 Add copy function to assetListView 2020-04-07 08:55:51 +08:00
Perfare
4f2d30552a set UV1 to NormalMap channel 2020-04-07 08:23:13 +08:00
Perfare
d259c7a5cd multiple uv export 2020-04-06 19:29:15 +08:00
Perfare
c71ceb7ea6 improve SerializedType read 2020-04-06 19:21:48 +08:00
Perfare
85cf134a49 Fixed if the container has the same key 2020-03-30 09:01:25 +08:00
Perfare
687b1d3a0d Fixed get triangles of mesh #510 2020-03-30 08:52:16 +08:00
Perfare
a30a0d0bc5 Update README.md 2020-03-28 15:52:15 +08:00
Perfare
e1dc54d6d7 use list to store objects in their original order 2020-03-28 14:13:25 +08:00
Perfare
c4270e186d fixed bug 2020-03-28 13:46:30 +08:00
Perfare
182a42ace2 optimize ResourceReader 2020-03-28 13:33:37 +08:00
Perfare
06fbe69a97 performance improvement 2020-03-28 04:24:32 +08:00
Perfare
a0bf4f9acd update LICENSE 2020-03-28 01:22:26 +08:00
Perfare
12568ba044 fix ico 2020-03-27 21:52:16 +08:00
Perfare
de95b02285 update to .net framework 4.7.2 2020-03-27 21:42:40 +08:00
Perfare
286edfe72c improve texture channel filter 2020-03-27 16:52:21 +08:00
Perfare
d717b223b7 delete some useless features 2020-03-27 01:06:22 +08:00
Perfare
9e195832ef reduce memory usage 2020-03-26 03:44:07 +08:00
Perfare
c8d08b2793 improve file type check 2020-03-26 02:17:48 +08:00
Perfare
2bcd9662be improve export 2020-03-26 01:01:02 +08:00
Perfare
ea461ee3d2 improve Texture2D decode 2020-03-25 22:45:53 +08:00
Perfare
fda821b441 add more information to the asset list 2020-03-25 14:01:59 +08:00
Perfare
5c193c761a using strong typing for setting 2020-03-25 11:18:12 +08:00
Perfare
14f47c6d30 fixed bug 2020-03-24 14:09:54 +08:00
Perfare
e53eacef78 improved 2020-03-24 11:31:57 +08:00
Perfare
ada26db659 improved 2020-03-24 10:42:39 +08:00
Perfare
48ca96807f Merge pull request #485 from K0lb3/patch-1
kSPMTight fix
2020-03-24 10:29:01 +08:00
Perfare
2018028853 fixed bug 2020-03-24 09:17:26 +08:00
Perfare
6f138dcc05 Update README.md 2020-03-24 08:52:30 +08:00
Perfare
69bcd2be67 update project 2020-03-24 07:45:47 +08:00
Perfare
45ad53b19a using Nuget 2020-03-24 07:19:59 +08:00
Perfare
6230240ee3 Merge pull request #499 from qiankanglai/master
corner case as protection
2020-03-24 07:09:18 +08:00
Perfare
73ec9f4bee update FBX SDK 2020.0.1 VS2017 2020-03-24 07:04:42 +08:00
Perfare
f3a0bf505e refactor Texture2D convert 2020-03-24 06:41:58 +08:00
Kanglai Qian
290708876d corner case as protection 2020-03-14 21:17:34 +08:00
Perfare
5b96a29cca move file 2020-03-14 16:06:21 +08:00
Perfare
948e2c4d92 Merge pull request #495 from qiankanglai/texchannel
texture channel support
2020-03-14 00:02:33 +08:00
Perfare
76da1c33ae Merge pull request #493 from Druhin13/master
Optimized images
2020-03-14 00:01:13 +08:00
Perfare
72b84ee24d Merge pull request #494 from qiankanglai/tga
support exporting texture2d as tga
2020-03-14 00:00:40 +08:00
Kanglai Qian
7b33d41172 texture channel 2020-03-03 12:46:51 +08:00
Kanglai Qian
c7043c1a83 support export texture2d as tga 2020-03-03 11:23:36 +08:00
Druhin Tarafder
d0baf26c61 Merge pull request #1 from Druhin13/imgbot
Optimized images
2020-03-02 14:39:00 +05:30
ImgBotApp
60ac10b043 [ImgBot] Optimize images
/AssetStudioGUI/Resources/preview.png -- 6.89kb -> 3.87kb (43.78%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2020-03-02 08:56:17 +00:00
Perfare
80dc24b487 Update README.md 2020-02-28 15:41:39 +08:00
Perfare
9d32a9dd6a 2019.3 support 2020-02-28 15:39:11 +08:00
Perfare
d96cc3c762 Merge pull request #489 from DaZombieKiller/2020
Support for SerializedFile version 22
2020-02-27 23:09:26 +08:00
Zombie
509df42730 Support for SerializedFile version 22 2020-02-27 20:29:02 +10:00
K0lb3
4efa5b0507 kSPMTight fix
SpritePackingMode.kSPMTight can occur outside of settingsRaw.packed == 1.

[sample file](https://cdn.discordapp.com/attachments/603359898507673632/678238497894563860/kuroyukiwedding_base_1_a)
from Dengeki Bunko: Crossing Void
2020-02-20 09:42:19 +01:00
Perfare
cffe96b409 Skip reading failed assets 2019-10-20 08:05:55 +08:00
Perfare
16dddc01e3 always show the debug menu 2019-08-12 05:50:04 +08:00
Perfare
b5d2c2cadb improved 2019-08-12 04:36:07 +08:00
Perfare
1d2c0ab6cb Fixed #428 2019-08-12 04:17:06 +08:00
Perfare
c6b7e04c47 improved 2019-08-06 17:57:14 +08:00
Perfare
5704813b28 Improved UI 2019-08-06 17:43:51 +08:00
Perfare
465c989e75 fixed bug 2019-08-06 15:49:41 +08:00
Perfare
d335aaef9e improved 2019-08-06 09:48:21 +08:00
Perfare
495b48c783 improved Sprite export 2019-08-01 15:23:36 +08:00
Perfare
05b55722fb change text 2019-07-30 03:34:15 +08:00
Perfare
de54257eef improved bone export 2019-07-29 13:41:42 +08:00
Perfare
e62b6c3d77 improved 2019-07-29 00:31:43 +08:00
Perfare
dc05e5b5eb Fixed bug 2019-07-29 00:25:26 +08:00
Perfare
f377381e26 Support for exporting raw data 2019-07-28 19:48:06 +08:00
Perfare
20f9fe493f add more options for export model 2019-07-28 18:55:08 +08:00
Perfare
0b462754a5 Implemented BlendShape export 2019-07-28 16:41:23 +08:00
Perfare
b1ea8dd346 clean up code 2019-07-28 03:47:12 +08:00
Perfare
4a46f897bd add default values to materials 2019-07-28 00:26:56 +08:00
Perfare
6a5ec80de7 fixed bug 2019-07-27 23:20:47 +08:00
Perfare
4f2046d412 improved 2019-07-27 22:54:18 +08:00
Perfare
1cf59e8d67 fixed bug 2019-07-27 18:01:57 +08:00
Perfare
e9e8390bbc Supported merge GameObject to export 2019-07-17 12:51:00 +08:00
Perfare
738b084440 Fixed bug 2019-07-16 17:53:50 +08:00
Perfare
32cce894ac Fixed #373 2019-07-16 17:49:10 +08:00
Perfare
a6264b39d1 improved morph export 2019-07-16 13:21:32 +08:00
Perfare
eb4981808b Fixed coding errors 2019-07-16 05:32:54 +08:00
Perfare
50c17c2ec4 improved model export 2019-07-16 04:33:37 +08:00
Perfare
e001dff3de fixed bug 2019-06-14 16:17:56 +08:00
Perfare
3a0100ed37 update 2019-06-14 12:47:22 +08:00
Perfare
58ab3116db Implemented AnimationEvent 2019-06-14 11:58:59 +08:00
Perfare
6b93df41f2 fixed bug 2019-06-09 07:44:50 +08:00
Perfare
b9cf7d5874 fixed bug 2019-06-04 18:56:18 +08:00
Perfare
da4eb15d6b Fixed #400 2019-06-04 13:34:59 +08:00
Perfare
378840bc1b improved Texture2D convert 2019-06-04 13:05:49 +08:00
Perfare
3441135b2f Change the way rename same name assets 2019-06-02 14:36:35 +08:00
Perfare
afcbba8182 fixed SpriteAtlas 2019-04-26 10:48:24 +08:00
Perfare
cefdf08873 Fixed #390 2019-04-26 09:51:02 +08:00
Perfare
59be547a82 fixed bug 2019-04-18 14:07:17 +08:00
Perfare
a2be5ebdac fixed bug 2019-04-18 13:58:06 +08:00
Perfare
f76d3d8fcd fixed bugs 2019-04-18 12:31:16 +08:00
Perfare
edb6256fc9 fixed bugs 2019-04-18 11:07:51 +08:00
Perfare
8946a4fba5 2019.1 support 2019-04-18 10:46:06 +08:00
Perfare
87e1739208 Fixed #386 2019-04-14 20:17:38 +08:00
Perfare
10f4aaa39f Update README.md 2019-04-05 01:59:18 +08:00
Perfare
957073b041 move file 2019-04-04 21:14:52 +08:00
Perfare
e1bb9a6cf0 Fixed ASTC Decoding 2019-04-04 21:05:44 +08:00
Perfare
558adb0b66 Fixed #376 2019-03-28 02:55:58 +08:00
Perfare
6a4979f999 fixed bugs 2019-03-07 04:50:36 +08:00
Perfare
9e76d94eea Remove SharpDX 2019-01-24 01:03:45 +08:00
Perfare
fa91820016 FIxed #351 2019-01-24 00:35:42 +08:00
Perfare
be091ecebb Fixed #344 2019-01-15 07:37:30 +08:00
Perfare
903be743ac Fixed #345
Fixed bug
2019-01-13 23:21:45 +08:00
Perfare
c3c4697562 small fixed 2019-01-03 09:02:12 +08:00
Perfare
e6ed312de2 change math library
fixed bug
2019-01-03 08:55:43 +08:00
Perfare
33461e068f small improved 2018-12-28 10:24:32 +08:00
Perfare
7f13c90189 small improved 2018-12-24 17:38:12 +08:00
Perfare
54ed3971a2 small improved 2018-12-24 17:31:35 +08:00
Perfare
e602a5cf3b Fixed #332 2018-12-24 08:46:20 +08:00
Perfare
dec0a22ffe Fixed #297 2018-12-24 08:28:26 +08:00
Perfare
911272167a Fixed #331 2018-12-24 04:47:12 +08:00
Perfare
54d78d55a0 Fixed #326 2018-12-24 04:25:55 +08:00
Perfare
ff550b457f improved mesh read 2018-12-23 23:17:01 +08:00
Perfare
f449d7a8ab improved script dump 2018-12-23 15:51:00 +08:00
Perfare
761579ab1a Fixed bug 2018-12-18 09:59:48 +08:00
Perfare
5cd4cf67cf Update README.md 2018-12-18 02:08:55 +08:00
Perfare
fabfc77a52 improved console shader export 2018-12-17 23:12:24 +08:00
Perfare
f8ffaa0400 Fixed bug 2018-12-11 23:36:15 +08:00
Perfare
d156b5d947 small fixed 2018-12-11 15:24:49 +08:00
Perfare
d7551bdeb2 small fixed 2018-12-11 15:21:23 +08:00
Perfare
7d5e06bce4 improved shader export 2018-12-11 13:01:10 +08:00
Perfare
0bc17f0ff5 Fixed bug 2018-12-11 10:47:35 +08:00
Perfare
9edc268cd4 small improvement 2018-12-11 05:22:39 +08:00
Perfare
356d5fa8a4 Fixed Sprite read
improved script dump
2018-12-11 04:50:38 +08:00
Perfare
eb170d4f34 minor improvements 2018-12-09 11:56:24 +08:00
Perfare
324c5ec7a2 Fixed bug 2018-12-05 23:16:02 +08:00
Perfare
ae155ca603 Fixed bug 2018-12-05 23:08:39 +08:00
Perfare
eb13585174 2018.3.0b support
Refactor mesh read
Fixed bug
2018-12-05 22:35:05 +08:00
Perfare
98c9eea58a Improved file reading 2018-12-03 02:42:07 +08:00
John Lyu
067517740f try to fix IO exceptions with valid assetsFile. (#317) 2018-11-28 20:16:18 +08:00
Perfare
3addb0e894 improve Sprite export 2018-11-28 15:02:31 +08:00
Perfare
7452d4275e minor improvements 2018-11-26 08:47:20 +08:00
Perfare
96ea522e83 minor improvements 2018-11-25 15:50:28 +08:00
Perfare
ab24f049cf Completed tight Sprite export 2018-11-25 12:37:55 +08:00
Perfare
ec9184ba93 Fixed #302 2018-11-24 23:30:04 +08:00
Perfare
0a5b866a03 rename
move files
improve Sprite read
2018-11-24 23:02:05 +08:00
Perfare
58d5a3fc37 minor fixes 2018-11-24 04:42:45 +08:00
Perfare
19534ebb4d minor fixes 2018-11-22 14:45:28 +08:00
Perfare
0a764c74d6 Fixed #284 2018-11-22 13:38:07 +08:00
Perfare
ab5f5fbd9d Restore the extension of TextAsset
Export Animator to a separate folder
2018-11-22 12:17:16 +08:00
Perfare
7dbc2ff95d Fixed #311 2018-11-21 16:13:32 +08:00
Perfare
bfaa207853 Refactor read assets
Generic PPtr
Misc
2018-11-21 15:37:56 +08:00
Perfare
8c749e21e1 improve 2018-11-20 16:47:35 +08:00
Perfare
8ea998b81f separate code into library
misc
2018-11-19 06:48:06 +08:00
Perfare
b93866d196 Fixed #308 2018-11-15 05:11:16 +08:00
Perfare
c0a5a7a5dd improve 2018-11-14 21:16:17 +08:00
Perfare
6d68f2bde5 Fixed 2018-11-14 16:01:52 +08:00
Perfare
a89fd049f1 improve Shader export 2018-11-14 12:20:11 +08:00
Perfare
e7c5976f7c Add scaleFactor option 2018-11-13 01:07:24 +08:00
Perfare
798a63e33c improve Sprite export 2018-11-08 17:30:12 +08:00
Perfare
e13b4489c3 improve Sprite export 2018-11-08 09:09:55 +08:00
Perfare
c6484ba77e improved 2018-11-08 06:45:33 +08:00
Perfare
a98fd52831 improved 2018-11-08 05:00:53 +08:00
Perfare
9d3cae8b28 new icon 2018-11-07 17:54:46 +08:00
Perfare
f5aef9486f Fixed bug 2018-11-07 17:15:54 +08:00
Perfare
c2ae9e63e0 Fixed bug 2018-11-07 06:11:39 +08:00
Perfare
b04cdbf12b Fixed bug 2018-11-01 19:15:15 +08:00
Perfare
1f897cf431 Delete obsolete code 2018-10-27 09:39:45 +08:00
Perfare
d380c38710 Fixed #282 2018-10-27 08:30:43 +08:00
Perfare
3cd6126ed9 Fixed bug 2018-10-25 15:02:57 +08:00
Perfare
22b2d472bc Fixed #272 2018-10-23 01:18:19 +08:00
Perfare
2c58fae804 Fixed bug 2018-10-22 22:37:24 +08:00
Perfare
1e9b8037ab Fixed bug 2018-10-22 13:23:49 +08:00
Perfare
0dbd5b52f0 Fixed bug 2018-10-17 01:59:14 +08:00
Perfare
21a8d7ef49 continue work 2018-10-17 01:51:25 +08:00
Perfare
17bd7a210a continue work 2018-10-17 00:43:34 +08:00
Perfare
40b191f039 Fixed 2018-10-16 12:39:20 +08:00
Perfare
3442b39784 rewrite some code to make it closer to the source code 2018-10-16 11:48:23 +08:00
Perfare
f15ee038b4 improved 2018-10-16 00:42:56 +08:00
Perfare
ec8b41155a Update README.md 2018-10-07 19:54:32 +08:00
Perfare
d54bfbdfe7 improved & fixed 2018-10-07 19:38:07 +08:00
Perfare
a1f491af25 modify project 2018-09-29 00:48:35 +08:00
Perfare
f2b041741b improved 2018-09-27 05:23:10 +08:00
Perfare
97169ff6dd Fixed bug 2018-09-27 04:16:59 +08:00
Perfare
11019a8473 improved 2018-09-27 01:28:03 +08:00
Perfare
767e4d0bf6 improved 2018-09-27 01:15:37 +08:00
Perfare
250856598b Fixed bug 2018-09-26 15:19:59 +08:00
Perfare
61751eeb1b Fixes 2018-09-25 22:30:59 +08:00
Perfare
99651a5d77 Fixed #266 2018-09-19 21:10:47 +08:00
Perfare
b31614641d Fixed Mesh in Xbox 2018-09-19 16:00:24 +08:00
Perfare
310c165824 FIxed #258 2018-09-13 20:52:17 +08:00
Perfare
a233af5b8f fixes 2018-09-10 13:45:12 +08:00
Perfare
2d0278db87 support optimized transform hierarchy 2018-09-09 17:32:12 +08:00
Perfare
18af0a8856 preparation work 2018-09-09 14:26:34 +08:00
Perfare
d7d56b4ad8 completed CompressedMesh 2018-09-09 05:06:34 +08:00
Perfare
3034dbc392 improve Mesh (VertexData) 2018-09-09 01:19:49 +08:00
Perfare
0b508509af Fixed bug 2018-09-08 23:45:13 +08:00
Perfare
14ad9431b9 more complete CompressedMesh (m_Skin, m_Normals, m_Tangents) 2018-09-08 23:14:18 +08:00
Perfare
c9a98d7163 compressed AnimationClip supported 2018-09-08 10:01:44 +08:00
Perfare
afae830ece improved AnimationClip export 2018-09-03 15:13:18 +08:00
Perfare
ec8c3e71d6 Fixed #249 2018-09-01 07:23:37 +08:00
Perfare
a7c5330042 Fixed #257 2018-09-01 07:07:26 +08:00
Perfare
10f02af70b Fixed #256 2018-08-30 21:34:41 +08:00
Perfare
2fd2b71148 UI update 2018-08-30 09:35:18 +08:00
Perfare
d1bec6a672 UI update 2018-08-30 09:27:19 +08:00
Perfare
9336613755 UI update 2018-08-30 06:45:08 +08:00
Perfare
9f482b7cf9 Fixed some bugs 2018-08-16 20:46:23 +08:00
Perfare
0c8fcb07b1 UI adjust 2018-08-16 06:43:26 +08:00
Perfare
eb302be569 add model preview mouse control 2018-08-15 08:40:46 +08:00
Perfare
cb3cf2a5ea Try fix bug 2018-08-15 04:53:11 +08:00
Perfare
9e5a06c107 Merge pull request #243 from qiankanglai/improveGlControl
improve GLControl:
2018-08-15 02:23:36 +08:00
Kanglai Qian
b49d5bdeb4 improve GLControl:
- resize when form changes size
- keep aspect
2018-08-06 20:52:42 +08:00
Perfare
0c23548817 improve 2018-08-05 20:03:54 +08:00
Perfare
cdaeb36e06 Update README.md 2018-08-05 06:12:35 +08:00
Perfare
114073f359 rename 2018-08-05 05:25:26 +08:00
Perfare
959a1a65b9 update OpenTK 2018-08-05 05:11:23 +08:00
Perfare
3e59a78376 add MonoScript to dump MonoBehaviour 2018-08-05 04:46:27 +08:00
Perfare
2bd4729fe7 Fixed #242 2018-08-03 13:01:51 +08:00
Perfare
84054428a8 Fixed #237 2018-07-29 04:53:56 +08:00
Perfare
9ad063bd0a improve 2018-07-26 10:00:32 +08:00
Perfare
9d1fd2f945 Fixed bug 2018-07-24 23:25:17 +08:00
Perfare
35edb9d391 optimizing 2018-07-24 22:05:02 +08:00
Perfare
d523862fac Fixed bug 2018-07-24 20:48:09 +08:00
Perfare
21ff88c890 Fixed #234 2018-07-24 13:02:08 +08:00
Perfare
e034ac5c1e Fixed #228 2018-07-19 17:58:20 +08:00
Perfare
adf39dde27 Fixed #225 2018-07-17 02:19:11 +08:00
Perfare
9b1e3435d6 try to fix combined mesh export error 2018-07-17 01:47:55 +08:00
Perfare
66a2dbe730 Fixed bug 2018-07-15 13:43:24 +08:00
Perfare
28a3b6cb23 Fixed bug 2018-07-15 05:15:05 +08:00
Perfare
2adda81b28 change the brotli library 2018-07-15 04:36:28 +08:00
Perfare
380afbf295 Fixed bug 2018-07-15 03:36:51 +08:00
Perfare
d39e24246e support load over 2GB file, Fixed #149 2018-07-14 23:46:32 +08:00
Perfare
a3e430d98d Fixed #223 2018-07-14 18:22:14 +08:00
Perfare
e0dcd6ac10 Fixed bug 2018-07-14 17:57:30 +08:00
Perfare
02f8d46620 Fixed #217 2018-07-13 01:20:31 +08:00
Perfare
dc6b9748a3 Add ResourcesHelper 2018-07-13 01:08:28 +08:00
Perfare
54c2bdc728 2018.2 support 2018-07-13 00:54:38 +08:00
Perfare
18275557df Fixed #218 2018-07-07 02:59:44 +08:00
Perfare
453f6b6e36 Fixed #213 2018-06-26 20:29:25 +08:00
Perfare
7236136cf1 Fixed #211 2018-06-24 18:35:34 +08:00
Perfare
ac6bd5236e Fixed #204 Fixed #207 2018-06-20 23:27:50 +08:00
Perfare
b2acf9a2a7 fixed bug 2018-06-20 23:02:21 +08:00
Perfare
7a8ac79ec4 fixed bug 2018-06-20 22:48:44 +08:00
Perfare
70c9d0edb3 Fixed #203 2018-06-20 22:36:45 +08:00
Perfare
18e934dd7e fixed bug 2018-06-10 05:11:44 +08:00
Perfare
3457d4d22c fixed struct read & write 2018-06-10 05:03:39 +08:00
Perfare
f65514b320 rebuild libraries 2018-05-26 16:40:53 +08:00
Perfare
0a0b172a09 add: read asset to c# dynamic class & write c# dynamic class to asset file 2018-05-09 23:13:30 +08:00
Perfare
3e2d0935b8 split code 2018-05-09 22:48:50 +08:00
Perfare
71c633b506 change structure read logic 2018-05-09 02:55:24 +08:00
Perfare
79af119cf4 Fixed #190 2018-05-06 16:46:23 +08:00
Perfare
9385b4da76 Fixed #186
Fixed #187
Fixed #188
2018-05-05 01:32:55 +08:00
Perfare
75985c8bf0 fixed bug 2018-05-04 23:14:18 +08:00
Perfare
9c8601a665 fixed bug 2018-05-04 23:03:42 +08:00
Perfare
8218662548 support 2018.1.0
some improvements
2018-05-03 02:41:47 +08:00
Perfare
52ba354dc5 Some improvements 2018-04-21 21:52:15 +08:00
Perfare
87d6a26232 Improve search 2018-04-21 16:36:18 +08:00
Perfare
546fe52ff0 Improve Filter 2018-04-21 15:50:13 +08:00
Perfare
674c634c2c Some improvements 2018-04-21 09:36:10 +08:00
Perfare
a3c92ddb8f add jump to scene hierarchy
some improvements
2018-04-19 07:06:52 +08:00
Perfare
4bcc16245c Improve extract file 2018-04-18 12:04:46 +08:00
Perfare
bd5eb3be5d Some improvements 2018-04-18 11:17:33 +08:00
Perfare
ffda15a1a5 Add FixRotation option 2018-04-18 10:36:57 +08:00
Perfare
5354506315 Improve model export 2018-04-18 08:19:30 +08:00
Perfare
ed569bfaf8 UI improvements 2018-04-18 07:11:10 +08:00
Perfare
592bfb64e7 add show type feature 2018-04-18 05:05:17 +08:00
Perfare
17b986f5df new icon 2018-04-18 02:13:23 +08:00
Perfare
de464dfe10 Some improvements 2018-04-18 01:29:18 +08:00
Perfare
906149a58a Fixed #177 2018-04-13 03:16:09 +08:00
Perfare
e3a0ab4e4a Separate code
Delete some useless code
2018-04-11 23:45:39 +08:00
Perfare
500f7788d4 Fixed bug 2018-04-11 17:17:27 +08:00
Perfare
af80b270cf Export objects with Animation 2018-04-11 15:52:37 +08:00
Perfare
8031d1a03f Add right-mouse menu export function 2018-04-10 04:45:09 +08:00
Perfare
bc2469e11a improve QuaternionToEuler 2018-04-09 08:18:45 +08:00
Perfare
9e4be3e082 Some improvements 2018-04-09 02:43:58 +08:00
Perfare
7410511c40 Update README.md 2018-04-08 05:39:36 +08:00
Perfare
8906c856e8 Update README.md 2018-04-07 08:41:48 +08:00
Perfare
dec672f9e2 Fixed appveyor build 2018-04-07 08:24:59 +08:00
Perfare
0b111d5f79 Prototype animation export 2018-04-07 07:51:33 +08:00
Perfare
4bcbdbc57d Fixed #170 2018-04-07 00:10:13 +08:00
Perfare
d5d937247e Add animation related classes 2018-04-06 23:57:36 +08:00
Perfare
4ab513002f New project name 2018-04-03 06:51:22 +08:00
Perfare
140a732046 Fixed #165 2018-03-29 01:29:51 +08:00
Perfare
e5104d5cc7 some changes 2018-03-28 06:29:28 +08:00
Perfare
f87390cc2b Update README.md
Updated project
Support 2017.4
2018-03-25 13:53:52 +08:00
Perfare
a062905734 platform update 2018-03-05 06:02:19 +08:00
Perfare
62206f8977 add brotli compression support 2018-03-05 05:07:41 +08:00
Perfare
8891414f60 fixed bug 2018-03-05 03:05:06 +08:00
Perfare
90dce1c17d fixed bug 2018-03-05 02:39:16 +08:00
Perfare
a9f1bd320e support UnityWebData 2018-03-05 02:35:53 +08:00
Perfare
c8393e165f Separate code
rename
2018-03-01 20:01:25 +08:00
Perfare
9d7c3b9f64 Merge pull request #154 from mafaca/master
Fixed sprite reading for Unity 4.x
2018-03-01 16:38:13 +08:00
mafaca
aa653cd508 Merge branch 'master' of https://github.com/Perfare/UnityStudio
merge
2018-03-01 02:32:09 +03:00
Perfare
3d60c5a7f6 Improve file import
fixed bug
2018-03-01 03:42:43 +08:00
Perfare
4ef160de34 Improve Sprite export 2018-02-28 19:10:36 +08:00
mafaca
8f7def379d fixed sprite reading for Unity 4.x 2018-02-28 13:52:38 +03:00
Perfare
351228e45c Improve external file reading 2018-02-27 18:20:12 +08:00
Perfare
ee6c050330 new crunch library after Unity 2017.3 2018-02-27 17:23:15 +08:00
Perfare
b4ce12a9e8 Split Texture2D conversion code 2018-02-27 17:11:08 +08:00
Perfare
8664531c47 Merge pull request #151 from mafaca/master
fixed compressed mesh reading
2018-02-19 14:52:11 +08:00
mafaca
40f6dbcc06 fixed compressed mesh reading 2018-02-17 23:15:45 +03:00
Perfare
1f21a67610 fixed bug 2018-01-31 07:09:46 +08:00
Perfare
929781a380 Release 0.9.0 2018-01-22 04:02:18 +08:00
Perfare
4d85c7f665 improve AudioClip export 2018-01-22 03:55:30 +08:00
Perfare
7e67f354e4 fixed some bug 2018-01-19 10:25:37 +08:00
Perfare
0cd8d51526 move file
UI adjust
2018-01-18 22:08:44 +08:00
Perfare
6f2c4521b2 Update README.md 2018-01-18 09:56:19 +08:00
Perfare
738e7d3785 Update README.md 2018-01-18 09:31:15 +08:00
Perfare
fc44ba373b add Sprite support 2018-01-18 08:08:48 +08:00
Perfare
468976db58 improve the speed of loading a large number of files
Rewriting folder related functions
fixed some bug
2018-01-17 09:57:05 +08:00
Perfare
647ce56f81 Fixed #121
clean up code
2018-01-17 06:20:06 +08:00
Perfare
db92daedf0 Update README.md 2018-01-15 10:08:02 +08:00
Perfare
6969412385 support new TextureFormat 2018-01-15 08:16:55 +08:00
Perfare
8da4c4623f update OpenTK to 3.0.0-pre 2018-01-15 06:27:23 +08:00
Perfare
50265c1d57 Fixed #129 2018-01-15 06:07:10 +08:00
Perfare
c00da37267 Fixed #130 2018-01-08 23:53:15 +08:00
Perfare
17d2140909 support Unity 2017.3, Fixed #126 2018-01-03 04:24:17 +08:00
Perfare
40153f6f19 fixed bug 2017-11-29 03:57:32 +08:00
Perfare
e75b9858da Merge pull request #122 from mafaca/master
fix skin indexes
2017-11-29 02:13:37 +08:00
mafaca
1f69f476f9 fix skin indexes 2017-11-25 02:17:31 +03:00
Perfare
b2ecc65885 support export MovieTexture 2017-11-13 17:46:26 +08:00
Perfare
682ef4552e clean up code 2017-11-13 17:04:29 +08:00
Perfare
96c7aaabb0 Support export VideoClip 2017-11-10 22:00:09 +08:00
Perfare
38f1f068d2 update ClassID 2017-11-10 19:18:42 +08:00
Perfare
0359169802 fixed #103 2017-11-10 07:58:53 +08:00
Perfare
a49d409619 fixed #110 2017-11-10 07:11:27 +08:00
Perfare
7e6ef31875 Update README.md 2017-11-10 04:34:03 +08:00
Perfare
5dd9f31398 Add Unity 2017.2 Shader support
Stop decompress Shader
2017-11-10 04:24:12 +08:00
Perfare
120c3e235d fixed bug 2017-11-10 03:39:35 +08:00
Perfare
3a6ebf7ce6 clean up code 2017-11-10 03:36:08 +08:00
Perfare
9d505c8900 change Audio related code 2017-11-10 02:27:36 +08:00
Perfare
d0486d855a Add fullSize 2017-11-10 00:04:27 +08:00
Perfare
7ddbf3ce3e fixed bug 2017-10-23 22:22:24 +08:00
Perfare
4666b378b3 fixed #107 2017-10-23 00:05:55 +08:00
Perfare
2a7d40616d add OpenFolderDialog 2017-10-22 23:48:31 +08:00
Kanglai Qian
96b8732d91 fix rotation&translation order (#101) 2017-09-30 15:32:09 +08:00
Kanglai Qian
e19ecf4770 we don't need matrix[] in fact (#98)
fix scale to avoid near face cull
2017-09-30 07:26:27 +08:00
Perfare
df45fa9b8e Fixes #99 2017-09-29 05:21:53 +08:00
Kanglai Qian
bd7a43f0dc better shader with sky/ground light, along with half lambert (#96)
* better shader with sky/ground light, along with half lambert

* force recalculate normal

* more wireframe/shade/normal mode!
2017-09-29 05:08:59 +08:00
Kanglai Qian
01f1d7c14e normalize model to center (#95)
* normalize model to center

* force same scale on XYZ
2017-09-27 01:57:47 +08:00
Perfare
cc74130ad4 display message if resource file can't be found 2017-09-24 08:27:49 +08:00
Perfare
dc8990115a modify export UI
delete AboutBox
2017-09-24 07:14:18 +08:00
Perfare
1c777aa1a8 Fixes #91 2017-09-21 05:50:14 +08:00
Perfare
6d019e6e8a When open multiple bundle files, first extract all the assets files into memory,and then parse the file to make sure the sharedfile index is correct 2017-09-19 04:34:58 +08:00
Perfare
2d7fd68ff5 Merge branch 'master' of https://github.com/Perfare/UnityStudio.git 2017-09-19 01:02:13 +08:00
Perfare
cdfc9cf2e6 fixed PlayerSettings in unity 2017.1
split code
improve read struct
2017-09-19 01:01:14 +08:00
Perfare
6e3c808799 Update README.md 2017-09-06 01:30:05 +08:00
Perfare
1ecf4c8c27 Release 0.8.0 2017-09-06 01:12:55 +08:00
Perfare
3dea2936d7 fixed bug 2017-09-06 01:03:54 +08:00
Perfare
e4533b4ec3 Add json file to read Shader 2017-08-21 22:00:28 +08:00
Perfare
9d87fead21 move glsl file to resource file 2017-08-21 19:51:32 +08:00
Perfare
14bd7f9789 try to read shader after Unity 5.4 2017-08-21 09:20:00 +08:00
Perfare
d02a4ea02e rewrite TextAsset.cs and Shader.cs 2017-08-21 07:10:30 +08:00
Perfare
14829c5e1b update TextureFormat 2017-08-21 06:52:31 +08:00
Perfare
ef29d220e0 Fixes #73 2017-08-21 06:46:46 +08:00
Perfare
14ec7c8259 support Unity 2017.1.0
fixed show "bundle file" original file
2017-07-15 15:27:09 +08:00
Perfare
9687f823fb Add "show original file" right click menu 2017-06-30 16:11:16 +08:00
Perfare
bb36839774 fix bug in export RGB565 format texture 2017-06-22 15:31:38 +08:00
Perfare
b0114520a8 fixed bug 2017-06-22 08:51:20 +08:00
Perfare
8a3af0bfba rewrite export mesh 2017-06-22 06:59:16 +08:00
Perfare
65a13e97c4 Add some simple judgment 2017-06-22 05:29:51 +08:00
Perfare
fe6b7760b0 fixed bug 2017-06-20 17:14:27 +08:00
Perfare
b319e92b3e fixed bug 2017-04-21 11:14:05 +08:00
Perfare
06b8fcea64 fix vertex color 2017-04-13 15:21:57 +08:00
Perfare
100238d232 fixed bug 2017-04-12 14:43:41 +08:00
Perfare
df3e5b31cd Release 0.7.0 2017-04-11 16:21:37 +08:00
Perfare
a04c0d0223 Update README.md 2017-04-11 15:06:40 +08:00
Perfare
d1ec1c29a4 cleanup code 2017-04-10 03:13:08 +08:00
Perfare
a928660dd3 Fixed some bugs 2017-04-10 00:50:33 +08:00
Perfare
e37a04e05b Modify project file
Fixed some bugs
2017-04-09 09:59:31 +08:00
Perfare
2c721272dd support Unity 5.6.0f3 2017-04-04 08:19:26 +08:00
Perfare
6f3b438d92 Fixed read struct 2017-04-04 05:49:26 +08:00
Perfare
f8e7303169 support use asset original name when display and export 2017-04-01 04:28:46 +08:00
Perfare
bd18bfb8ea Move code
Fixed some bugs
2017-04-01 00:41:18 +08:00
Perfare
86843f81da Fix FileName 2017-03-31 16:41:36 +08:00
ordigdug
60cc81b2dd Added 32bit ManagedFbx.dll (#32) 2017-03-07 23:30:50 +08:00
ordigdug
cfbcdecfe6 Added ExportMesh support -- (#31)
utilizing a modified ManagedFbx
2017-03-07 00:20:21 +08:00
Perfare
45b9b781b1 Clean up code
Adjust UI
Fixed some bugs
2017-02-27 23:56:24 +08:00
Perfare
29068481f5 Move file
Update OpenTK to 2.0
Fixed bug in high resolution
2017-02-26 01:40:14 +08:00
ordigdug
384dd2e4e3 Mesh Preview Support (#26)
* Added OpenTK preview

* Bug fix

* Cleanup

* Initial Mesh preview support

* Mesh preview support

* Mesh preview - lighting and color
2017-02-25 18:04:05 +08:00
Perfare
b4bce77381 Support Wii U Asset
All types selection
2017-02-24 15:39:06 +08:00
Perfare
631f2e7027 Update README.md 2017-02-20 15:40:44 +08:00
Perfare
2585be69f9 clean up code 2017-02-20 15:38:04 +08:00
Perfare
332e4cc6e2 Fixed some bugs 2017-02-16 15:30:11 +08:00
Perfare
16ed347a30 Tidy up a part of the code 2017-02-12 04:57:24 +08:00
Perfare
b580b293f3 Fixed some bugs 2017-02-12 03:03:37 +08:00
ordigdug
66b9b46523 Code moved out of UnityStudioForm and into new class UnityStudio.cs (#17) 2017-02-11 15:39:14 +08:00
Perfare
2357e55337 Fixed some bugs 2017-02-10 03:49:13 +08:00
Perfare
256eeb8f7c Add crunch and texgenpack 2017-02-02 02:23:46 +08:00
Perfare
5688f03869 Rewrite wrapper dll 2017-02-01 22:07:50 +08:00
Perfare
c2f7f0a92d No longer use DevIL 2017-02-01 20:23:09 +08:00
Perfare
0ad6e6a456 Support R16 TextureFormat 2017-02-01 15:03:15 +08:00
Perfare
fff759fe72 Move texture related code to Texture2D.cs
Delete some astc related code
2017-02-01 01:20:43 +08:00
Perfare
7e7397ab7e Remove exportSize 2017-01-31 17:13:33 +08:00
Perfare
86e30c5dc0 Support file size greater than 2GB
Support preview .otf type font
2017-01-28 19:17:31 +08:00
Perfare
2e8ef2a403 update cmmon string 2017-01-26 23:08:59 +08:00
Perfare
7456f9b106 improve ClassStruct read and parse 2017-01-25 19:38:44 +08:00
415 changed files with 73291 additions and 22993 deletions

57
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: AssetStudioBuild
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: microsoft/setup-msbuild@v1.1
- name: Download FBX SDK
run: |
md fbx
cd fbx
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_win.exe" -OutFile "fbxsdk.exe"
Start-Process -FilePath "fbxsdk.exe" /S -Wait
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_pdbs.exe" -OutFile "fbxpdb.exe"
Start-Process -FilePath "fbxpdb.exe" /S -Wait
cd ..
- name: Nuget Restore
run: nuget restore
- name: Build .Net472
run: msbuild /p:Configuration=Release /p:TargetFramework=net472 /verbosity:minimal
- name: Build .Net5
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net5.0-windows /p:SelfContained=false /verbosity:minimal
- name: Build .Net6
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net6.0-windows /p:SelfContained=false /verbosity:minimal
- name: Upload .Net472 Artifact
uses: actions/upload-artifact@v2
with:
name: AssetStudio.net472
path: AssetStudioGUI/bin/Release/net472
- name: Upload .Net5 Artifact
uses: actions/upload-artifact@v2
with:
name: AssetStudio.net5
path: AssetStudioGUI/bin/Release/net5.0-windows/publish
- name: Upload .Net6 Artifact
uses: actions/upload-artifact@v2
with:
name: AssetStudio.net6
path: AssetStudioGUI/bin/Release/net6.0-windows/publish

175
.gitignore vendored
View File

@@ -1,7 +1,10 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
@@ -15,13 +18,25 @@
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
build/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# Launch Settings
*launchSettings.json
# MSTest test Results
[Tt]est[Rr]esult*/
@@ -36,18 +51,28 @@ TestResult.xml
[Rr]eleasePS/
dlldata.c
# DNX
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
@@ -57,6 +82,7 @@ artifacts/
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
@@ -72,14 +98,21 @@ _Chutzpah*
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
@@ -101,9 +134,18 @@ _TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
@@ -131,47 +173,68 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
## TODO: Comment the next line if you want to checkin your
## web deploy settings but do note that will include unencrypted
## passwords
#*.pubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.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
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
**/[Pp]ackages/*
# 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
#!**/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/
*.build.csdef
# Windows Store app package directory
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
!?*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
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
Generated_Code/
@@ -182,21 +245,30 @@ _UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
@@ -204,7 +276,68 @@ FakesAssemblies/
# Visual Studio 6 workspace options file
*.opt
# LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# 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

View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;net8.0;net8.0-windows;net9.0;net9.0-windows</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.19.0.0</Version>
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,65 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
#if NETFRAMEWORK
namespace AssetStudio.PInvoke
{
public static class DllLoader
{
public static void PreloadDll(string dllName)
{
var localPath = Process.GetCurrentProcess().MainModule?.FileName;
var localDir = Path.GetDirectoryName(localPath);
// Not using OperatingSystem.Platform.
// See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Win32.LoadDll(GetDirectedDllDirectory(localDir), dllName);
}
}
private static string GetDirectedDllDirectory(string localDir)
{
var win32Path = Path.Combine("runtimes", "win-x86", "native");
var win64Path = Path.Combine("runtimes", "win-x64", "native");
var subDir = Environment.Is64BitProcess ? win64Path : win32Path;
var directedDllDir = Path.Combine(localDir, subDir);
return directedDllDir;
}
private static class Win32
{
internal static void LoadDll(string dllDir, string dllName)
{
var dllFileName = $"{dllName}.dll";
var directedDllPath = Path.Combine(dllDir, dllFileName);
// Specify SEARCH_DLL_LOAD_DIR to load dependent libraries located in the same platform-specific directory.
var hLibrary = LoadLibraryEx(directedDllPath, IntPtr.Zero, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
if (hLibrary == IntPtr.Zero)
{
var errorCode = Marshal.GetLastWin32Error();
var exception = new Win32Exception(errorCode);
throw new DllNotFoundException(exception.Message, exception);
}
}
// HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
// HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags);
private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000;
private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100;
}
}
}
#endif

View File

@@ -0,0 +1,100 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace AssetStudio.PInvoke
{
// Generally the technique from Steamworks.NET
public class Utf8StringHandle : SafeHandleZeroOrMinusOneIsInvalid
{
static Utf8StringHandle()
{
Utf8 = new UTF8Encoding(false);
}
public Utf8StringHandle(string str)
: base(true)
{
IntPtr buffer;
if (str == null)
{
buffer = IntPtr.Zero;
}
else
{
if (str.Length == 0)
{
buffer = Marshal.AllocHGlobal(1);
unsafe
{
*(byte*)buffer = 0;
}
}
else
{
var strlen = Utf8.GetByteCount(str);
var strBuffer = new byte[strlen + 1];
Utf8.GetBytes(str, 0, str.Length, strBuffer, 0);
buffer = Marshal.AllocHGlobal(strBuffer.Length);
Marshal.Copy(strBuffer, 0, buffer, strBuffer.Length);
}
}
SetHandle(buffer);
}
public static string ReadUtf8StringFromPointer(IntPtr lpstr)
{
if (lpstr == IntPtr.Zero || lpstr == new IntPtr(-1))
{
return null;
}
var byteCount = 0;
unsafe
{
var p = (byte*)lpstr.ToPointer();
while (*p != 0)
{
byteCount += 1;
p += 1;
}
}
if (byteCount == 0)
{
return string.Empty;
}
var strBuffer = new byte[byteCount];
Marshal.Copy(lpstr, strBuffer, 0, byteCount);
var str = Utf8.GetString(strBuffer);
return str;
}
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
Marshal.FreeHGlobal(handle);
}
return true;
}
private static readonly UTF8Encoding Utf8;
}
}

159
AssetStudio.sln Normal file
View File

@@ -0,0 +1,159 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33414.496
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{422FEC21-EF60-4F29-AA56-95DFDA23C913}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio.PInvoke", "AssetStudio.PInvoke\AssetStudio.PInvoke.csproj", "{0B2BE613-3049-4021-85D1-21C325F729F4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioFBXWrapper", "AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj", "{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}"
ProjectSection(ProjectDependencies) = postProject
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027} = {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{29EAD018-1C67-497A-AB8E-727D595AD756}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Texture2DDecoderWrapper", "Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj", "{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}"
ProjectSection(ProjectDependencies) = postProject
{29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "AssetStudioFBXNative\AssetStudioFBXNative.vcxproj", "{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioCLI", "AssetStudioCLI\AssetStudioCLI.csproj", "{34B6329B-0E73-45AC-B8CC-015F119F63DC}"
ProjectSection(ProjectDependencies) = postProject
{422FEC21-EF60-4F29-AA56-95DFDA23C913} = {422FEC21-EF60-4F29-AA56-95DFDA23C913}
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF} = {65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.Build.0 = Release|Any CPU
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.Build.0 = Debug|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.Build.0 = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.Build.0 = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.ActiveCfg = Release|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = Release|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.Build.0 = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.Build.0 = Debug|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.ActiveCfg = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.Build.0 = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.ActiveCfg = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.Build.0 = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.ActiveCfg = Release|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x64.ActiveCfg = Debug|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x64.Build.0 = Debug|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x86.ActiveCfg = Debug|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x86.Build.0 = Debug|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|Any CPU.Build.0 = Release|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x64.ActiveCfg = Release|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x64.Build.0 = Release|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x86.ActiveCfg = Release|Any CPU
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3C074481-9CDD-4780-B9F6-57BBC5092EA2}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;net8.0;net8.0-windows;net9.0;net9.0-windows</TargetFrameworks>
<Version>0.19.0.0</Version>
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2025</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ZstdSharp.Port" Version="0.8.6" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.Bcl.Numerics" Version="9.0.8" />
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,876 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Text.Json;
using AssetStudio.CustomOptions;
using AssetStudio.CustomOptions.Asmo;
using static AssetStudio.ImportHelper;
namespace AssetStudio
{
public class AssetsManager
{
public bool LoadViaTypeTree = true;
public bool MeshLazyLoad = true;
public ImportOptions Options = new ImportOptions();
public readonly List<Action<OptionsFile>> OptionLoaders = new List<Action<OptionsFile>>();
public readonly List<SerializedFile> AssetsFileList = new List<SerializedFile>();
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
internal ConcurrentDictionary<string, BinaryReader> resourceFileReaders = new ConcurrentDictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
private readonly List<string> importFiles = new List<string>();
private readonly HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
private readonly HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
public AssetsManager()
{
OptionLoaders.Add(LoadImportOptions);
}
public void SetAssetFilter(params ClassIDType[] classIDTypes)
{
filteredAssetTypesList.UnionWith(new[]
{
ClassIDType.AssetBundle,
ClassIDType.ResourceManager,
ClassIDType.GameObject,
ClassIDType.Transform,
ClassIDType.RectTransform,
});
if (classIDTypes.Contains(ClassIDType.MonoBehaviour))
{
filteredAssetTypesList.Add(ClassIDType.MonoScript);
}
if (classIDTypes.Contains(ClassIDType.Sprite))
{
filteredAssetTypesList.Add(ClassIDType.Texture2D);
filteredAssetTypesList.Add(ClassIDType.SpriteAtlas);
}
if (classIDTypes.Contains(ClassIDType.Animator))
{
filteredAssetTypesList.Add(ClassIDType.AnimatorController);
filteredAssetTypesList.Add(ClassIDType.AnimatorOverrideController);
filteredAssetTypesList.Add(ClassIDType.Animation);
filteredAssetTypesList.Add(ClassIDType.AnimationClip);
filteredAssetTypesList.Add(ClassIDType.Avatar);
filteredAssetTypesList.Add(ClassIDType.Material);
filteredAssetTypesList.Add(ClassIDType.MeshFilter);
filteredAssetTypesList.Add(ClassIDType.MeshRenderer);
filteredAssetTypesList.Add(ClassIDType.SkinnedMeshRenderer);
}
if (classIDTypes.Contains(ClassIDType.AnimatorController))
{
filteredAssetTypesList.Add(ClassIDType.Animator);
filteredAssetTypesList.Add(ClassIDType.AnimatorOverrideController);
}
filteredAssetTypesList.UnionWith(classIDTypes);
}
public void SetAssetFilter(List<ClassIDType> classIDTypeList)
{
SetAssetFilter(classIDTypeList.ToArray());
}
public void LoadFilesAndFolders(params string[] paths)
{
LoadFilesAndFolders(out _, paths.ToList());
}
public void LoadFilesAndFolders(out string parentPath, params string[] paths)
{
LoadFilesAndFolders(out parentPath, paths.ToList());
}
public void LoadFilesAndFolders(out string parentPath, List<string> pathList)
{
var fileList = new List<string>();
var filesInPath = false;
parentPath = "";
foreach (var path in pathList)
{
var fullPath = Path.GetFullPath(path);
if (Directory.Exists(fullPath))
{
var parent = Directory.GetParent(fullPath)?.FullName;
if (!filesInPath && (parentPath == "" || parentPath?.Length > parent?.Length))
{
parentPath = parent;
}
MergeSplitAssets(fullPath, true);
fileList.AddRange(Directory.GetFiles(fullPath, "*.*", SearchOption.AllDirectories));
}
else if (File.Exists(fullPath))
{
parentPath = Path.GetDirectoryName(fullPath);
fileList.Add(fullPath);
filesInPath = true;
}
}
if (filesInPath)
{
MergeSplitAssets(parentPath);
}
LoadOptionFiles(fileList);
var toReadFile = ProcessingSplitFiles(fileList);
fileList.Clear();
pathList.Clear();
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++)
{
if (LoadFile(importFiles[i]))
{
Progress.Report(i + 1, importFiles.Count);
}
else
{
break;
}
}
importFiles.Clear();
importFilesHash.Clear();
noexistFiles.Clear();
assetsFileListHash.Clear();
if (AssetsFileList.Count == 0)
return;
ReadAssets();
ProcessAssets();
}
private bool LoadFile(string fullName)
{
var reader = new FileReader(fullName);
return LoadFile(reader);
}
private bool LoadFile(FileReader reader, bool fromZip = false)
{
if (reader == null)
return false;
switch (reader.FileType)
{
case FileType.AssetsFile:
return LoadAssetsFile(reader, fromZip);
case FileType.BundleFile:
return LoadBundleFile(reader);
case FileType.WebFile:
LoadWebFile(reader);
break;
case FileType.GZipFile:
LoadFile(DecompressGZip(reader));
break;
case FileType.BrotliFile:
LoadFile(DecompressBrotli(reader));
break;
case FileType.ZipFile:
LoadZipFile(reader);
break;
case FileType.ResourceFile when !fromZip:
reader.Dispose();
break;
}
return true;
}
private bool LoadAssetsFile(FileReader reader, bool fromZip)
{
if (!assetsFileListHash.Contains(reader.FileName))
{
Logger.Info($"Loading \"{reader.FullPath}\"");
try
{
var assetsFile = new SerializedFile(reader, this);
var dirName = Path.GetDirectoryName(reader.FullPath);
CheckStrippedVersion(assetsFile);
AssetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName);
if (fromZip)
return true;
foreach (var sharedFile in assetsFile.m_Externals)
{
var sharedFileName = sharedFile.fileName;
if (!importFilesHash.Contains(sharedFileName))
{
var sharedFilePath = Path.Combine(dirName, sharedFileName);
if (!noexistFiles.Contains(sharedFilePath))
{
if (!File.Exists(sharedFilePath))
{
var findFiles = Directory.GetFiles(dirName, sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
}
}
if (File.Exists(sharedFilePath))
{
importFiles.Add(sharedFilePath);
importFilesHash.Add(sharedFileName);
}
else
{
noexistFiles.Add(sharedFilePath);
Logger.Warning($"Dependency wasn't found: {sharedFilePath}");
}
}
}
}
}
catch (NotSupportedException e)
{
Logger.Error(e.Message);
reader.Dispose();
return false;
}
catch (Exception e)
{
Logger.Warning($"Failed to read assets file \"{reader.FullPath}\"\n{e}");
reader.Dispose();
}
}
else
{
Logger.Info($"Skipping \"{reader.FullPath}\"");
reader.Dispose();
}
return true;
}
private bool LoadAssetsFromMemory(FileReader reader, string originalPath, UnityVersion assetBundleUnityVer = null)
{
if (!assetsFileListHash.Contains(reader.FileName))
{
try
{
var assetsFile = new SerializedFile(reader, this);
assetsFile.originalPath = originalPath;
if (assetBundleUnityVer != null && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
{
assetsFile.version = assetBundleUnityVer;
}
CheckStrippedVersion(assetsFile, assetBundleUnityVer);
AssetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName);
}
catch (NotSupportedException e)
{
Logger.Error(e.Message);
reader.Dispose();
return false;
}
catch (Exception e)
{
Logger.Warning($"Failed to read assets file \"{reader.FullPath}\" from {Path.GetFileName(originalPath)}\n{e}");
resourceFileReaders.TryAdd(reader.FileName, reader);
}
}
else
{
Logger.Info($"Skipping \"{originalPath}\" ({reader.FileName})");
}
return true;
}
private bool LoadBundleFile(FileReader reader, string originalPath = null)
{
Logger.Info($"Loading \"{reader.FullPath}\"");
Logger.Debug($"Bundle offset: {reader.Position}");
var bundleStream = new OffsetStream(reader);
var bundleReader = new FileReader(reader.FullPath, bundleStream);
var isLoaded = false;
try
{
var bundleFile = new BundleFile(bundleReader, Options.BundleOptions);
isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath);
if (!isLoaded)
return false;
while (bundleFile.IsDataAfterBundle && isLoaded)
{
isLoaded = false;
bundleStream.Offset = reader.Position;
bundleReader = new FileReader($"{reader.FullPath}_0x{bundleStream.Offset:X}", bundleStream);
if (bundleReader.FileType != FileType.BundleFile)
{
Logger.Debug("Unknown data was detected after the end of the bundle.");
break;
}
if (bundleReader.Position > 0)
{
bundleStream.Offset += bundleReader.Position;
bundleReader.FullPath = $"{reader.FullPath}_0x{bundleStream.Offset:X}";
bundleReader.FileName = $"{reader.FileName}_0x{bundleStream.Offset:X}";
}
Logger.Info($"[MultiBundle] Loading \"{reader.FileName}\" from offset: 0x{bundleStream.Offset:X}");
bundleFile = new BundleFile(bundleReader, Options.BundleOptions, isMultiBundle: true);
isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath ?? reader.FullPath);
}
return isLoaded;
}
catch (NotSupportedException e)
{
Logger.Error(e.Message);
return false;
}
catch (Exception e)
{
var str = $"Error while reading bundle file \"{bundleReader.FullPath}\"";
if (originalPath != null)
{
str += $" from {Path.GetFileName(originalPath)}";
}
Logger.Warning($"{str}\n{e}");
return true;
}
finally
{
if (!isLoaded)
bundleReader.Dispose();
}
}
private bool LoadBundleFiles(FileReader reader, BundleFile bundleFile, string originalPath = null)
{
foreach (var file in bundleFile.fileList)
{
if (file.stream == null)
continue;
file.stream.Position = 0; //go to file offset
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile)
{
if (!LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision))
return false;
}
else
{
resourceFileReaders.TryAdd(file.fileName, subReader);
}
}
return true;
}
private void LoadWebFile(FileReader reader)
{
Logger.Info($"Loading \"{reader.FullPath}\"");
try
{
var webFile = new WebFile(reader);
foreach (var file in webFile.fileList)
{
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
switch (subReader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFromMemory(subReader, reader.FullPath);
break;
case FileType.BundleFile:
LoadBundleFile(subReader, reader.FullPath);
break;
case FileType.WebFile:
LoadWebFile(subReader);
break;
case FileType.ResourceFile:
resourceFileReaders.TryAdd(file.fileName, subReader);
break;
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading web file \"{reader.FullPath}\"", e);
}
finally
{
reader.Dispose();
}
}
private void LoadZipFile(FileReader reader)
{
Logger.Info("Reading " + reader.FileName);
try
{
using (ZipArchive archive = new ZipArchive(reader.BaseStream, ZipArchiveMode.Read))
{
List<string> splitFiles = new List<string>();
// register all files before parsing the assets so that the external references can be found
// and find split files
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.Name.Contains(".split"))
{
string baseName = Path.GetFileNameWithoutExtension(entry.Name);
string basePath = Path.Combine(Path.GetDirectoryName(entry.FullName), baseName);
if (!splitFiles.Contains(basePath))
{
splitFiles.Add(basePath);
importFilesHash.Add(baseName);
}
}
else
{
importFilesHash.Add(entry.Name);
}
}
// merge split files and load the result
for (var i = 0; i < splitFiles.Count; i++)
{
var basePath = splitFiles[i].Replace("\\", "/");
try
{
Stream splitStream = new MemoryStream();
var j = 0;
while (true)
{
string path = $"{basePath}.split{j++}";
ZipArchiveEntry entry = archive.GetEntry(path);
if (entry == null)
break;
using (Stream entryStream = entry.Open())
{
entryStream.CopyTo(splitStream);
}
}
splitStream.Seek(0, SeekOrigin.Begin);
FileReader entryReader = new FileReader(basePath, splitStream);
if (!LoadFile(entryReader, fromZip: true))
break;
}
catch (Exception e)
{
Logger.Warning($"Error while reading zip split file \"{basePath}\"\n{e}");
}
}
// load all entries
var progressCount = archive.Entries.Count;
int k = 0;
Progress.Reset();
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.Length == 0)
continue;
try
{
string dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), reader.FileName, entry.FullName);
// create a new stream
// - to store the deflated stream in
// - to keep the data for later extraction
Stream streamReader = new MemoryStream();
using (Stream entryStream = entry.Open())
{
entryStream.CopyTo(streamReader);
}
streamReader.Position = 0;
FileReader entryReader = new FileReader(dummyPath, streamReader);
if (!LoadFile(entryReader, fromZip: true))
break;
if (entryReader.FileType == FileType.ResourceFile)
{
entryReader.Position = 0;
resourceFileReaders.TryAdd(entry.Name, entryReader);
}
Progress.Report(++k, progressCount);
}
catch (Exception e)
{
Logger.Warning($"Error while reading zip entry \"{entry.FullName}\"\n{e}");
}
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading zip file {reader.FileName}", e);
}
finally
{
reader.Dispose();
}
}
public void LoadOptionFiles(List<string> pathList)
{
if (pathList.Count == 0)
return;
var optionFileIndexes = new List<int>();
for (var i = 0; i < pathList.Count; i++)
{
var path = pathList[i];
if (!path.EndsWith(OptionsFile.Extension, StringComparison.OrdinalIgnoreCase))
continue;
optionFileIndexes.Add(i);
var optionsFile = LoadOptionsFile(new FileReader(path));
if (optionsFile == null)
continue;
foreach (var optionsLoader in OptionLoaders)
{
optionsLoader(optionsFile);
}
}
for (var i = 0; i < optionFileIndexes.Count; i++)
{
pathList.RemoveAt(optionFileIndexes[i] - i);
}
}
private static OptionsFile LoadOptionsFile(FileReader reader)
{
Logger.Info($"Loading options file \"{reader.FullPath}\"");
try
{
return new OptionsFile(reader);
}
catch (Exception e)
{
Logger.Warning($"Error while loading options file \"{reader.FullPath}\"\n{e}");
return null;
}
finally
{
reader.Dispose();
}
}
private void LoadImportOptions(OptionsFile optionsFile)
{
try
{
var importOptions = ImportOptions.FromOptionsFile(optionsFile);
if (importOptions == null)
return;
Options = importOptions;
Logger.Info("Import options successfully loaded.");
}
catch (Exception e)
{
Logger.Warning($"Error while reading import options\n{e}");
}
}
public void CheckStrippedVersion(SerializedFile assetsFile, UnityVersion bundleUnityVer = null)
{
if (assetsFile.version.IsStripped && Options.CustomUnityVersion == null)
{
var msg = "The asset's Unity version has been stripped, please set the version in the options.";
if (bundleUnityVer != null && !bundleUnityVer.IsStripped)
msg += $"\n\nAssumed Unity version based on asset bundle: {bundleUnityVer}";
throw new NotSupportedException(msg);
}
if (Options.CustomUnityVersion != null)
{
assetsFile.version = Options.CustomUnityVersion;
}
}
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 jsonOptions = new JsonSerializerOptions
{
Converters = { new JsonConverterHelper.ByteArrayConverter(), new JsonConverterHelper.PPtrConverter(), new JsonConverterHelper.KVPConverter() },
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,
PropertyNameCaseInsensitive = true,
IncludeFields = true,
};
var progressCount = AssetsFileList.Sum(x => x.m_Objects.Count);
var i = 0;
Progress.Reset();
foreach (var assetsFile in AssetsFileList)
{
JsonConverterHelper.AssetsFile = assetsFile;
foreach (var objectInfo in assetsFile.m_Objects)
{
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
if (filteredAssetTypesList.Count > 0 && !filteredAssetTypesList.Contains(objectReader.type))
{
continue;
}
try
{
Object obj = null;
switch (objectReader.type)
{
case ClassIDType.Animation:
obj = new Animation(objectReader);
break;
case ClassIDType.AnimationClip:
obj = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new AnimationClip(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions, objectInfo)
: 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.BuildSettings:
obj = new BuildSettings(objectReader);
break;
case ClassIDType.Font:
obj = new Font(objectReader);
break;
case ClassIDType.GameObject:
obj = new GameObject(objectReader);
break;
case ClassIDType.Material:
obj = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new Material(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions)
: 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.PreloadData:
obj = new PreloadData(objectReader);
break;
case ClassIDType.RectTransform:
obj = new RectTransform(objectReader);
break;
case ClassIDType.Shader:
if (objectReader.version < 2021)
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 = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new Texture2D(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions)
: new Texture2D(objectReader);
break;
case ClassIDType.Texture2DArray:
obj = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new Texture2DArray(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions)
: new Texture2DArray(objectReader);
break;
case ClassIDType.Transform:
obj = new Transform(objectReader);
break;
case ClassIDType.VideoClip:
obj = new VideoClip(objectReader);
break;
case ClassIDType.ResourceManager:
obj = new ResourceManager(objectReader);
break;
default:
obj = new Object(objectReader);
break;
}
if (obj != null)
{
assetsFile.AddObject(obj);
}
}
catch (Exception e)
{
var sb = new StringBuilder();
sb.AppendLine("Unable to load object")
.AppendLine($"Assets {assetsFile.fileName}")
.AppendLine($"Path {assetsFile.originalPath}")
.AppendLine($"Type {objectReader.type}")
.AppendLine($"PathID {objectInfo.m_PathID}")
.Append(e);
Logger.Warning(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;
case MonoBehaviour m_MonoBehaviour:
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{
switch (m_Script.m_ClassName)
{
case "CubismModel":
if (m_GameObject.m_Transform == null)
break;
m_GameObject.CubismModel = new CubismModel(m_GameObject)
{
CubismModelMono = m_MonoBehaviour
};
break;
case "CubismPhysicsController":
if (m_GameObject.CubismModel != null)
m_GameObject.CubismModel.PhysicsController = m_MonoBehaviour;
break;
case "CubismFadeController":
if (m_GameObject.CubismModel != null)
m_GameObject.CubismModel.FadeController = m_MonoBehaviour;
break;
case "CubismExpressionController":
if (m_GameObject.CubismModel != null)
m_GameObject.CubismModel.ExpressionController = m_MonoBehaviour;
break;
}
}
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);
}
else if (m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlasOld))
{
if (m_SpriteAtlasOld.m_IsVariant)
{
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
}
else
{
Logger.Debug($"\"{m_Sprite.m_Name}\": The actual SpriteAtlas PathID \"{m_SpriteAtlas.m_PathID}\" does not match the specified one \"{m_Sprite.m_SpriteAtlas.m_PathID}\".");
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Buffers;
namespace AssetStudio
{
public static class BigArrayPool<T>
{
public static ArrayPool<T> Shared { get; }
static BigArrayPool()
{
Shared = ArrayPool<T>.Create(256 * 1024 * 1024, 5);
}
}
}

View 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);
}
}
}
}

View 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() {}
}
}

View 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)
{
}
}
}

View 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
}
}

View 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);
}
}
}
}

File diff suppressed because one or more lines are too long

View 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);
}
}
}
}
}

View 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;
}
}
}
}

View 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);
}
}
}
}

View 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 };
}
}

View 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
View 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);
}
}
}

View 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;
}
}
}

View 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;
}
}
}
}

View 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;
}
}
}

View File

@@ -0,0 +1,65 @@
namespace AssetStudio
{
public enum BuildTarget
{
NoTarget = -2,
AnyPlayer = -1,
ValidPlayer = 1,
StandaloneOSX = 2,
StandaloneOSXPPC = 3,
StandaloneOSXIntel = 4,
StandaloneWindows,
WebPlayer,
WebPlayerStreamed,
Wii = 8,
iOS = 9,
PS3,
XBOX360,
Broadcom = 12,
Android = 13,
StandaloneGLESEmu = 14,
StandaloneGLES20Emu = 15,
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,
Lumin,
Stadia,
CloudRendering,
GameCoreXboxSeries,
GameCoreXboxOne,
PS5,
EmbeddedLinux,
QNX,
VisionOS,
Switch2,
UnknownPlatform = 9999
}
public enum TuanjieBuildTarget
{
MiniGame = 47,
OpenHarmony,
HMIAndroid,
ArmLinux,
ArmLinuxServer,
VisionOS,
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Runtime.InteropServices;
#if NETFRAMEWORK
using AssetStudio.PInvoke;
#endif
namespace BundleCompression.Oodle
{
public static class OodleLZ
{
private const string LibName = "ooz";
#if NETFRAMEWORK
static OodleLZ()
{
DllLoader.PreloadDll(LibName);
}
#endif
[DllImport(LibName)]
private static extern int Ooz_Decompress(
in byte srcBuffer,
UIntPtr srcLen,
ref byte dstBuffer,
UIntPtr dstLen,
int fuzzSafetyFlag,
int crcCheckFlag,
int logVerbosityFlag,
UIntPtr rawBuffer,
UIntPtr rawBufferSize,
UIntPtr chunkDecodeCallback,
UIntPtr chunkDecodeContext,
UIntPtr scratchBuf,
UIntPtr scratchBufSize,
int threadPhase);
public static int Decompress(ReadOnlySpan<byte> srcSpanBuffer, Span<byte> dstSpanBuffer)
{
return Ooz_Decompress(in srcSpanBuffer[0], (UIntPtr)srcSpanBuffer.Length, ref dstSpanBuffer[0], (UIntPtr)dstSpanBuffer.Length,
0, 0, 0, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, 0);
}
}
}

View File

@@ -2,7 +2,7 @@
namespace SevenZip
{
class CRC
public class CRC
{
public static readonly uint[] Table;
@@ -22,26 +22,26 @@ namespace SevenZip
}
}
uint _value = 0xFFFFFFFF;
private uint _value = 0xFFFFFFFF;
public void Init() { _value = 0xFFFFFFFF; }
public void UpdateByte(byte b)
{
_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
_value = Table[(byte)_value ^ b] ^ (_value >> 8);
}
public void Update(byte[] data, uint offset, uint size)
{
for (uint i = 0; i < size; i++)
_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
_value = Table[(byte)_value ^ data[offset + i]] ^ (_value >> 8);
}
public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
static uint CalculateDigest(byte[] data, uint offset, uint size)
public static uint CalculateDigest(byte[] data, uint offset, uint size)
{
CRC crc = new CRC();
var crc = new CRC();
// crc.Init();
crc.Update(data, offset, size);
return crc.GetDigest();
@@ -49,7 +49,7 @@ namespace SevenZip
static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
{
return (CalculateDigest(data, offset, size) == digest);
return CalculateDigest(data, offset, size) == digest;
}
}
}

View File

@@ -1,6 +1,7 @@
// LzmaDecoder.cs
using System;
using AssetStudio;
namespace SevenZip.Compression.LZMA
{
@@ -247,6 +248,8 @@ namespace SevenZip.Compression.LZMA
m_OutWindow.PutByte(b);
nowPos64++;
}
Progress.Reset(index: 1);
while (nowPos64 < outSize64)
{
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
@@ -338,6 +341,8 @@ namespace SevenZip.Compression.LZMA
}
m_OutWindow.CopyBlock(rep0, len);
nowPos64 += len;
Progress.Report((int)(nowPos64 * 100f / outSize64), 100, index: 1);
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.IO;
using SevenZip.Compression.LZMA;
namespace BundleCompression.Lzma
{
public static class SevenZipLzma
{
public static MemoryStream DecompressStream(MemoryStream inStream)
{
var decoder = new Decoder();
inStream.Seek(0, SeekOrigin.Begin);
var newOutStream = new MemoryStream();
var properties = new byte[5];
if (inStream.Read(properties, 0, 5) != 5)
throw new Exception("input .lzma is too short");
long outSize = 0;
for (var i = 0; i < 8; i++)
{
var v = inStream.ReadByte();
if (v < 0)
throw new Exception("Can't Read 1");
outSize |= ((long)(byte)v) << (8 * i);
}
decoder.SetDecoderProperties(properties);
var compressedSize = inStream.Length - inStream.Position;
decoder.Code(inStream, newOutStream, compressedSize, outSize, null);
newOutStream.Position = 0;
return newOutStream;
}
public static long DecompressStream(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize)
{
var basePosition = compressedStream.Position;
var decoder = new Decoder();
var properties = new byte[5];
if (compressedStream.Read(properties, 0, 5) != 5)
throw new Exception("input .lzma is too short");
decoder.SetDecoderProperties(properties);
decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null);
compressedStream.Position = basePosition + compressedSize;
return decompressedStream.Position;
}
}
}

View File

@@ -0,0 +1,65 @@
using BundleCompression.Lzma;
using BundleCompression.Oodle;
using System;
using System.IO;
using System.Text.RegularExpressions;
using K4os.Compression.LZ4;
using ZstdSharp;
namespace AssetStudio
{
public static class BundleDecompressionHelper
{
private static readonly Decompressor ZstdDecompressor = new Decompressor();
private static readonly string MsgPattern = @"\. ";
public static MemoryStream DecompressLzmaStream(MemoryStream inStream)
{
return SevenZipLzma.DecompressStream(inStream);
}
public static long DecompressLzmaStream(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize, ref string errorMsg)
{
var numWrite = -1L;
try
{
numWrite = SevenZipLzma.DecompressStream(compressedStream, decompressedStream, compressedSize, decompressedSize);
}
catch (Exception e)
{
Logger.Debug(e.ToString());
errorMsg = $"({Regex.Split(e.Message, MsgPattern, RegexOptions.CultureInvariant)[0]})";
}
return numWrite;
}
public static int DecompressBlock(CompressionType type, ReadOnlySpan<byte> srcBuffer, Span<byte> dstBuffer, ref string errorMsg)
{
var numWrite = -1;
try
{
switch (type)
{
case CompressionType.Lz4:
case CompressionType.Lz4HC:
numWrite = LZ4Codec.Decode(srcBuffer, dstBuffer);
break;
case CompressionType.Zstd:
numWrite = ZstdDecompressor.Unwrap(srcBuffer, dstBuffer);
break;
case CompressionType.Oodle:
numWrite = OodleLZ.Decompress(srcBuffer, dstBuffer);
break;
default:
throw new NotSupportedException();
}
}
catch (Exception e)
{
Logger.Debug(e.ToString());
errorMsg = $"({Regex.Split(e.Message, MsgPattern, RegexOptions.CultureInvariant)[0]})";
}
return numWrite;
}
}
}

553
AssetStudio/BundleFile.cs Normal file
View File

@@ -0,0 +1,553 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using AssetStudio.CustomOptions;
namespace AssetStudio
{
[Flags]
public enum ArchiveFlags
{
CompressionTypeMask = 0x3f,
BlocksAndDirectoryInfoCombined = 0x40,
BlocksInfoAtTheEnd = 0x80,
OldWebPluginCompatibility = 0x100,
BlockInfoNeedPaddingAtStart = 0x200
}
[Flags]
public enum CnEncryptionFlags
{
V1 = 0x200,
V2_V3 = 0x1400,
}
[Flags]
public enum StorageBlockFlags
{
CompressionTypeMask = 0x3f,
Streamed = 0x40
}
public enum CompressionType
{
Auto = -1,
None,
Lzma,
Lz4,
Lz4HC,
Lzham,
Zstd, //custom
Oodle, //custom
}
public class BundleFile
{
public readonly bool IsDataAfterBundle;
private readonly CustomBundleOptions _bundleOptions;
public class Header
{
public string signature;
public uint version;
public string unityVersion;
public UnityVersion unityRevision;
public long size;
public uint compressedBlocksInfoSize;
public uint uncompressedBlocksInfoSize;
public ArchiveFlags flags;
}
public class StorageBlock
{
public uint compressedSize;
public uint uncompressedSize;
public StorageBlockFlags 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 List<StreamFile> fileList;
public BundleFile(FileReader reader, CustomBundleOptions bundleOptions, bool isMultiBundle = false)
{
_bundleOptions = bundleOptions;
m_Header = new Header();
m_Header.signature = reader.ReadStringToNull();
m_Header.version = reader.ReadUInt32();
m_Header.unityVersion = reader.ReadStringToNull();
m_Header.unityRevision = UnityVersion.TryParse(reader.ReadStringToNull(), out var ver) ? ver : new UnityVersion();
switch (m_Header.signature)
{
case "UnityArchive":
break; //TODO
case "UnityWeb":
case "UnityRaw":
if (m_Header.version == 6)
{
goto case "UnityFS";
}
ReadHeaderAndBlocksInfo(reader);
using (reader)
{
ReadFiles(ReadBlocksAndDirectory(reader));
}
break;
case "UnityFS":
ReadHeader(reader);
var bundleSize = m_Header.size;
var streamSize = reader.BaseStream.Length;
if (bundleSize > streamSize)
Logger.Warning("Bundle size is incorrect.");
IsDataAfterBundle = streamSize - bundleSize > 200;
var unityVer = m_Header.unityRevision;
var customUnityVer = _bundleOptions.Options.CustomUnityVersion;
if (customUnityVer != null)
{
if (!unityVer.IsStripped && customUnityVer != unityVer)
{
Logger.Warning($"Detected Unity version is different from the specified one ({customUnityVer.FullVersion.Color(ColorConsole.BrightCyan)}).\n" +
$"Assets may load with errors.\n" +
$"It is recommended to specify the detected Unity version: {unityVer.FullVersion.Color(ColorConsole.BrightCyan)}");
}
unityVer = customUnityVer;
}
UnityCnCheck(reader, unityVer);
ReadBlocksInfoAndDirectory(reader, unityVer);
if (IsUncompressedBundle && !IsDataAfterBundle && !isMultiBundle)
{
Logger.Debug($"[Uncompressed bundle] BlockData count: {m_BlocksInfo.Length}");
ReadFiles(reader.BaseStream, reader.Position);
break;
}
ReadFiles(ReadBlocks(reader));
if (!IsDataAfterBundle)
reader.Close();
break;
}
}
private void ReadHeaderAndBlocksInfo(FileReader reader)
{
if (m_Header.version >= 4)
{
var hash = reader.ReadBytes(16);
var crc = reader.ReadUInt32();
}
var minimumStreamedBytes = reader.ReadUInt32();
m_Header.size = 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(),
};
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 = m_Header.size;
}
private Stream CreateBlocksStream(string path)
{
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
if (uncompressedSizeSum < int.MaxValue && !_bundleOptions.DecompressToDisk)
return new MemoryStream((int)uncompressedSizeSum);
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
var tempDir = Path.Combine(Directory.GetCurrentDirectory(), "Studio_temp");
Directory.CreateDirectory(tempDir);
var filename = Path.GetFileName(path);
var hash = path.GetHashCode();
path = Path.Combine(tempDir, $"{filename}_{hash:X}");
}
return new TempFileStream(path + ".temp", FileMode.Create);
}
private Stream ReadBlocksAndDirectory(FileReader reader)
{
var blocksStream = CreateBlocksStream(reader.FullPath);
var isCompressed = m_Header.signature == "UnityWeb";
foreach (var blockInfo in m_BlocksInfo)
{
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
if (isCompressed)
{
using (var memoryStream = new MemoryStream(uncompressedBytes))
{
using (var decompressStream = BundleDecompressionHelper.DecompressLzmaStream(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 (var i = 0; i < nodesCount; i++)
{
m_DirectoryInfo[i] = new Node
{
path = blocksReader.ReadStringToNull(),
offset = blocksReader.ReadUInt32(),
size = blocksReader.ReadUInt32()
};
}
return blocksStream;
}
private void ReadFiles(Stream inputStream, long blocksOffset = 0)
{
fileList = new List<StreamFile>(m_DirectoryInfo.Length);
foreach (var node in m_DirectoryInfo)
{
var file = new StreamFile();
fileList.Add(file);
file.path = node.path;
file.fileName = Path.GetFileName(node.path);
try
{
file.stream = new OffsetStream(inputStream, node.offset + blocksOffset, node.size);
}
catch (IOException e)
{
Logger.Warning($"Failed to access {file.fileName} file.\n{e}");
}
}
}
private void ReadHeader(FileReader reader)
{
m_Header.size = reader.ReadInt64();
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
m_Header.flags = (ArchiveFlags)reader.ReadUInt32();
if (m_Header.signature != "UnityFS")
{
reader.ReadByte();
}
}
private void ReadBlocksInfoAndDirectory(FileReader reader, UnityVersion unityVer, bool silent = false)
{
byte[] blocksInfoBytes;
if (m_Header.version >= 7)
{
reader.AlignStream(16);
}
else if (unityVer >= (2019, 4) && m_Header.flags != ArchiveFlags.BlocksAndDirectoryInfoCombined)
{
//check if we need to align the reader
//- align to 16 bytes and check if all are 0
//- if not, reset the reader to the previous position
var preAlign = reader.Position;
var alignData = reader.ReadBytes((16 - (int)(preAlign % 16)) % 16);
if (alignData.Any(x => x != 0))
{
reader.Position = preAlign;
}
}
var compressedSize = (int)m_Header.compressedBlocksInfoSize;
var uncompressedSize = (int)m_Header.uncompressedBlocksInfoSize;
if (uncompressedSize < 0 || compressedSize < 0 || compressedSize > reader.BaseStream.Length)
{
throw new IOException("Incorrect blockInfo length.\nBlockInfo sizes might be encrypted.\n");
}
if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
{
var position = reader.Position;
reader.Position = m_Header.size - compressedSize;
blocksInfoBytes = reader.ReadBytes(compressedSize);
reader.Position = position;
}
else //0x40 BlocksAndDirectoryInfoCombined
{
blocksInfoBytes = reader.ReadBytes(compressedSize);
}
var customBlockInfoCompression = _bundleOptions.CustomBlockInfoCompression;
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
if (customBlockInfoCompression == CompressionType.Auto)
{
if (!silent && compressionType > CompressionType.Lzham && Enum.IsDefined(typeof(CompressionType), compressionType))
{
Logger.Warning($"Non-standard blockInfo compression type: {(int)compressionType}. Trying to decompress as {compressionType} archive..");
}
}
else if (compressionType != CompressionType.None)
{
compressionType = customBlockInfoCompression;
if (!silent)
{
Logger.Info($"Custom blockInfo compression type: {customBlockInfoCompression}");
}
}
Logger.Debug($"BlockInfo compression: {compressionType}");
int numWrite;
var errorMsg = string.Empty;
MemoryStream blocksInfoUncompressedStream;
switch (compressionType)
{
case CompressionType.None:
{
blocksInfoUncompressedStream = new MemoryStream(blocksInfoBytes);
numWrite = compressedSize;
break;
}
case CompressionType.Lzma:
{
blocksInfoUncompressedStream = new MemoryStream(uncompressedSize);
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
{
numWrite = (int)BundleDecompressionHelper.DecompressLzmaStream(blocksInfoCompressedStream, blocksInfoUncompressedStream, compressedSize, uncompressedSize, ref errorMsg);
}
blocksInfoUncompressedStream.Position = 0;
break;
}
case CompressionType.Lz4:
case CompressionType.Lz4HC:
case CompressionType.Zstd:
case CompressionType.Oodle:
{
var uncompressedBytes = new byte[uncompressedSize];
numWrite = BundleDecompressionHelper.DecompressBlock(compressionType, blocksInfoBytes, uncompressedBytes, ref errorMsg);
blocksInfoUncompressedStream = new MemoryStream(uncompressedBytes);
break;
}
case CompressionType.Lzham:
throw new IOException($"Unsupported blockInfo compression type: {compressionType}.\n");
default:
throw new IOException($"Unknown blockInfo compression type: {compressionType}.\nYou may try to specify the compression type manually.\n");
}
if (numWrite != uncompressedSize)
{
var msg = $"{compressionType} blockInfo decompression error. {errorMsg}\nWrite {numWrite} bytes but expected {uncompressedSize} bytes.";
var exMsg = compressionType > CompressionType.Lz4HC || customBlockInfoCompression != CompressionType.Auto
? "Wrong compression type or blockInfo data might be encrypted."
: "BlockInfo data might be encrypted.";
throw new IOException($"{msg}\n{exMsg}\n");
}
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompressedStream))
{
var uncompressedDataHash = blocksInfoReader.ReadBytes(16);
var blocksInfoCount = blocksInfoReader.ReadInt32();
m_BlocksInfo = new StorageBlock[blocksInfoCount];
for (var i = 0; i < blocksInfoCount; i++)
{
m_BlocksInfo[i] = new StorageBlock
{
uncompressedSize = blocksInfoReader.ReadUInt32(),
compressedSize = blocksInfoReader.ReadUInt32(),
flags = (StorageBlockFlags)blocksInfoReader.ReadUInt16()
};
}
var nodesCount = blocksInfoReader.ReadInt32();
m_DirectoryInfo = new Node[nodesCount];
for (var i = 0; i < nodesCount; i++)
{
m_DirectoryInfo[i] = new Node
{
offset = blocksInfoReader.ReadInt64(),
size = blocksInfoReader.ReadInt64(),
flags = blocksInfoReader.ReadUInt32(),
path = blocksInfoReader.ReadStringToNull(),
};
}
}
if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
{
reader.AlignStream(16);
}
}
private Stream ReadBlocks(FileReader reader)
{
var customBlockCompression = _bundleOptions.CustomBlockCompression;
var blocksStream = CreateBlocksStream(reader.FullPath);
var blocksCompression = m_BlocksInfo.Max(x => (CompressionType)(x.flags & StorageBlockFlags.CompressionTypeMask));
var blockSize = (int)m_BlocksInfo.Max(x => x.uncompressedSize);
Logger.Debug($"BlockData compression: {blocksCompression}\n" +
$"BlockData count: {m_BlocksInfo.Length}\n" +
$"BlockSize: {blockSize}");
if (customBlockCompression == CompressionType.Auto)
{
if (blocksCompression > CompressionType.Lzham && Enum.IsDefined(typeof(CompressionType), blocksCompression))
{
Logger.Warning($"Non-standard block compression type: {(int)blocksCompression}. Trying to decompress as {blocksCompression} archive..");
}
}
else
{
Logger.Info($"Custom block compression type: {customBlockCompression}");
blocksCompression = customBlockCompression;
}
byte[] sharedCompressedBuff = null;
byte[] sharedUncompressedBuff = null;
if (blocksCompression > CompressionType.Lzma && blocksCompression != CompressionType.Lzham)
{
sharedCompressedBuff = BigArrayPool<byte>.Shared.Rent(blockSize);
sharedUncompressedBuff = BigArrayPool<byte>.Shared.Rent(blockSize);
}
try
{
for (var i = 0; i < m_BlocksInfo.Length; i++)
{
var blockInfo = m_BlocksInfo[i];
var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
if (customBlockCompression != CompressionType.Auto && compressionType > 0)
{
compressionType = customBlockCompression;
}
var debugMsg = $"[{i:D2}] Compression: {compressionType} | UncompressedSize: {blockInfo.uncompressedSize} | CompressedSize: {blockInfo.compressedSize} ";
long numWrite;
var errorMsg = string.Empty;
switch (compressionType)
{
case CompressionType.None:
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
numWrite = blockInfo.compressedSize;
break;
case CompressionType.Lzma:
numWrite = BundleDecompressionHelper.DecompressLzmaStream(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize, ref errorMsg);
break;
case CompressionType.Lz4:
case CompressionType.Lz4HC:
case CompressionType.Zstd:
case CompressionType.Oodle:
var compressedSize = (int)blockInfo.compressedSize;
var uncompressedSize = (int)blockInfo.uncompressedSize;
sharedCompressedBuff.AsSpan().Clear();
sharedUncompressedBuff.AsSpan().Clear();
var read = reader.Read(sharedCompressedBuff, 0, compressedSize);
debugMsg += $"(read: {read.ToString().ColorIf(read != compressedSize, ColorConsole.BrightRed)})";
var compressedSpan = new ReadOnlySpan<byte>(sharedCompressedBuff, 0, compressedSize);
var uncompressedSpan = new Span<byte>(sharedUncompressedBuff, 0, uncompressedSize);
numWrite = BundleDecompressionHelper.DecompressBlock(compressionType, compressedSpan, uncompressedSpan, ref errorMsg);
if (numWrite == uncompressedSize)
{
blocksStream.Write(sharedUncompressedBuff, 0, uncompressedSize);
}
break;
case CompressionType.Lzham:
throw new IOException($"Unsupported block compression type: {compressionType}.\n");
default:
throw new IOException($"Unknown block compression type: {compressionType}.\nYou may try to specify the compression type manually.\n");
}
Logger.Debug(debugMsg);
if (numWrite != blockInfo.uncompressedSize)
{
var msg = $"{compressionType} block decompression error. {errorMsg}\nWrite {numWrite} bytes but expected {blockInfo.uncompressedSize} bytes.";
var exMsg = compressionType > CompressionType.Lz4HC || customBlockCompression != CompressionType.Auto
? "Wrong compression type or block data might be encrypted."
: "Block data might be encrypted.";
throw new IOException($"{msg}\n{exMsg}\n");
}
}
}
finally
{
if (sharedCompressedBuff != null)
BigArrayPool<byte>.Shared.Return(sharedCompressedBuff, clearArray: true);
if (sharedUncompressedBuff != null)
BigArrayPool<byte>.Shared.Return(sharedUncompressedBuff, clearArray: true);
}
return blocksStream;
}
private void UnityCnCheck(FileReader reader, UnityVersion unityVer)
{
if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
return;
var hasUnityCnFlag = false;
if (!unityVer.IsStripped)
{
// https://issuetracker.unity3d.com/issues/files-within-assetbundles-do-not-start-on-aligned-boundaries-breaking-patching-on-nintendo-switch
if (unityVer < 2020
|| unityVer.IsInRange(2020, (2020, 3, 34))
|| unityVer.IsInRange(2021, (2021, 3, 2))
|| unityVer.IsInRange(2022, (2022, 1, 1)))
{
hasUnityCnFlag = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.V1) != 0;
}
else
{
hasUnityCnFlag = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.V2_V3) != 0;
}
}
if (!hasUnityCnFlag)
return;
var pos = reader.Position;
reader.Position += 70;
try
{
ReadBlocksInfoAndDirectory(reader, unityVer, silent: true);
}
catch (Exception)
{
reader.Position = pos;
return;
}
throw new NotSupportedException("Unsupported bundle file. UnityCN encryption was detected.");
}
private bool IsUncompressedBundle => m_BlocksInfo.All(x => (CompressionType)(x.flags & StorageBlockFlags.CompressionTypeMask) == CompressionType.None);
}
}

407
AssetStudio/ClassIDType.cs Normal file
View File

@@ -0,0 +1,407 @@
// official Class ID Reference: https://docs.unity3d.com/Manual/ClassIDReference.html
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,
OcclusionCullingSettings = 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,
CompositeCollider2D = 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,
NavMeshProjectSettings = 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,
Texture2DArrayImage = -187, //fake type
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,
SortingGroup = 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,
PlayableDirector = 320,
VideoPlayer = 328,
VideoClip = 329,
ParticleSystemForceField = 330,
SpriteMask = 331,
WorldAnchor = 362,
OcclusionCullingData = 363,
//kLargestRuntimeClassID = 364
SmallestEditorClassID = 1000,
PrefabInstance = 1001,
EditorExtensionImpl = 1002,
AssetImporter = 1003,
AssetDatabaseV1 = 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,
PreviewAnimationClip = 1108,
AnimatorTransition = 1109,
SpeedTreeImporter = 1110,
AnimatorTransitionBase = 1111,
SubstanceImporter = 1112,
LightmapParameters = 1113,
LightingDataAsset = 1120,
GISRaster = 1121,
GISRasterImporter = 1122,
CadImporter = 1123,
SketchUpImporter = 1124,
BuildReport = 1125,
PackedAssets = 1126,
VideoClipImporter = 1127,
ActivationLogComponent = 2000,
//kLargestEditorClassID = 2001
//kClassIdOutOfHierarchy = 100000
//int = 100000,
//bool = 100001,
//float = 100002,
MonoObject = 100003,
Collision = 100004,
Vector3f = 100005,
RootMotionData = 100006,
Collision2D = 100007,
AudioMixerLiveUpdateFloat = 100008,
AudioMixerLiveUpdateBool = 100009,
Polygon2D = 100010,
//void = 100011,
TilemapCollider2D = 19719996,
AssetImporterLog = 41386430,
GraphicsStateCollection = 55640938,
VFXRenderer = 73398921,
SerializableManagedRefTestClass = 76251197,
Grid = 156049354,
ScenesUsingAssets = 156483287,
ArticulationBody = 171741748,
Preset = 181963792,
EmptyObject = 277625683,
IConstraint = 285090594,
TestObjectWithSpecialLayoutOne = 293259124,
AssemblyDefinitionReferenceImporter = 294290339,
SiblingDerived = 334799969,
TestObjectWithSerializedMapStringNonAlignedStruct = 342846651,
AudioResource = 355983997,
SubDerived = 367388927,
AssetImportInProgressProxy = 369655926,
PluginBuildInfo = 382020655,
MemorySettings = 387306366,
BuildMetaDataImporter = 403037116,
BuildInstructionImporter = 403037117,
EditorProjectAccess = 426301858,
PrefabImporter = 468431735,
TestObjectWithSerializedArray = 478637458,
TestObjectWithSerializedAnimationCurve = 478637459,
TilemapRenderer = 483693784,
ScriptableCamera = 488575907,
SpriteAtlasAsset = 612988286,
SpriteAtlasDatabase = 638013454,
AudioBuildInfo = 641289076,
CachedSpriteAtlasRuntimeData = 644342135,
RendererFake = 646504946,
MultiplayerManager = 655991488,
AssemblyDefinitionReferenceAsset = 662584278,
BuiltAssetBundleInfoSet = 668709126,
SpriteAtlas = 687078895,
RayTracingShaderImporter = 747330370,
BuildArchiveImporter = 780535461,
PreviewImporter = 815301076,
RayTracingShader = 825902497,
LightingSettings = 850595691,
PlatformModuleSetup = 877146078,
VersionControlSettings = 890905787,
CustomCollider2D = 893571522,
AimConstraint = 895512359,
VFXManager = 937362698,
RoslynAnalyzerConfigAsset = 947337230,
RuleSetFileAsset = 954905827,
VisualEffectSubgraph = 994735392,
VisualEffectSubgraphOperator = 994735403,
VisualEffectSubgraphBlock = 994735404,
LocalizationImporter = 1027052791,
Derived = 1091556383,
PropertyModificationsTargetTestObject = 1111377672,
ReferencesArtifactGenerator = 1114811875,
AssemblyDefinitionAsset = 1152215463,
SceneVisibilityState = 1154873562,
LookAtConstraint = 1183024399,
SpriteAtlasImporter = 1210832254,
MultiArtifactTestImporter = 1223240404,
AudioContainerElement = 1233149941,
GameObjectRecorder = 1268269756,
AudioRandomContainer = 1307931743,
LightingDataAssetParent = 1325145578,
PresetManager = 1386491679,
TestObjectWithSpecialLayoutTwo = 1392443030,
StreamingManager = 1403656975,
LowerResBlitTexture = 1480428607,
VideoBuildInfo = 1521398425,
C4DImporter = 1541671625,
StreamingController = 1542919678,
RenderPassAttachment = 1571458007,
TestObjectVectorPairStringBool = 1628831178,
ShaderContainer = 1557264870,
RoslynAdditionalFileAsset = 1597193336,
RoslynAdditionalFileImporter = 1642787288,
MultiplayerRolesData = 1652712579,
SceneRoots = 1660057539,
BrokenPrefabAsset = 1731078267,
AndroidAssetPackImporter = 1736697216,
VulkanDeviceFilterLists = 1740304944,
GridLayout = 1742807556,
AssemblyDefinitionImporter = 1766753193,
ParentConstraint = 1773428102,
FakeComponent = 1803986026,
RuleSetFileImporter = 1777034230,
PositionConstraint = 1818360608,
RotationConstraint = 1818360609,
ScaleConstraint = 1818360610,
Tilemap = 1839735485,
PackageManifest = 1896753125,
PackageManifestImporter = 1896753126,
RoslynAnalyzerConfigImporter = 1903396204,
UIRenderer = 1931382933,
TerrainLayer = 1953259897,
SpriteShapeRenderer = 1971053207,
NativeObjectType = 1977754360,
TestObjectWithSerializedMapStringBool = 1981279845,
SerializableManagedHost = 1995898324,
VisualEffectAsset = 2058629509,
VisualEffectImporter = 2058629510,
VisualEffectResource = 2058629511,
VisualEffectObject = 2059678085,
VisualEffect = 2083052967,
LocalizationAsset = 2083778819,
ScriptedImporter = 2089858483,
ShaderIncludeImporter = 2103361453,
}
}

View File

@@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class Animation : Behaviour
{
public List<PPtr<AnimationClip>> m_Animations;
public Animation(ObjectReader reader) : base(reader)
{
var m_Animation = new PPtr<AnimationClip>(reader);
int numAnimations = reader.ReadInt32();
m_Animations = new List<PPtr<AnimationClip>>();
for (var i = 0; i < numAnimations; i++)
{
m_Animations.Add(new PPtr<AnimationClip>(reader));
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
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 >= (4, 5)) //4.5 and up
{
var m_UpdateMode = reader.ReadInt32();
}
if (version.IsTuanjie && (version > (2022, 3, 48) || version == (2022, 3, 48) && version.Build >= 7)) //2022.3.48t7(1.4.4) and up
{
var m_UpdateFrequencyMode = reader.ReadInt32();
var m_UpdateFrequency = reader.ReadSingle();
}
var m_ApplyRootMotion = reader.ReadBoolean();
if (version == 4 && version.Minor >= 5) //4.5 and up - 5.0 down
{
reader.AlignStream();
}
if (version >= 5) //5.0 and up
{
var m_LinearVelocityBlending = reader.ReadBoolean();
if (version >= (2021, 2)) //2021.2 and up
{
var m_StabilizeFeet = reader.ReadBoolean();
}
if (version >= (2023, 1)) //2023.1 and up
{
var m_AnimatePhysics = reader.ReadBoolean();
}
reader.AlignStream();
}
if (version < (4, 5)) //4.5 down
{
var m_AnimatePhysics = reader.ReadBoolean();
}
if (version >= (4, 3)) //4.3 and up
{
m_HasTransformHierarchy = reader.ReadBoolean();
}
if (version >= (4, 5)) //4.5 and up
{
var m_AllowConstantClipSamplingOptimization = reader.ReadBoolean();
}
if (version.IsInRange(5, 2018)) //5.0 and up - 2018 down
{
reader.AlignStream();
}
if (version >= 2018) //2018 and up
{
var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();
reader.AlignStream();
}
}
}
}

View File

@@ -0,0 +1,625 @@
using System.Collections.Generic;
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 >= (5, 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 List<SkeletonMaskElement> m_Data;
public SkeletonMask(ObjectReader reader)
{
int numElements = reader.ReadInt32();
m_Data = new List<SkeletonMaskElement>();
for (var i = 0; i < numElements; i++)
{
m_Data.Add(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 >= (4, 2)) //4.2 and up
{
m_DefaultWeight = reader.ReadSingle();
}
m_IKPass = reader.ReadBoolean();
if (version >= (4, 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();
var conditionConstantList = new List<ConditionConstant>();
for (var i = 0; i < numConditions; i++)
{
conditionConstantList.Add(new ConditionConstant(reader));
}
m_ConditionConstantArray = conditionConstantList.ToArray();
m_DestinationState = reader.ReadUInt32();
if (version >= 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 >= 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 >= (4, 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();
var childNeighborLists = new List<MotionNeighborList>();
for (var i = 0; i < numNeighbours; i++)
{
childNeighborLists.Add(new MotionNeighborList(reader));
}
m_ChildNeighborListArray = childNeighborLists.ToArray();
}
}
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 >= (4, 1)) //4.1 and up
{
m_BlendType = reader.ReadUInt32();
}
m_BlendEventID = reader.ReadUInt32();
if (version >= (4, 1)) //4.1 and up
{
m_BlendEventYID = reader.ReadUInt32();
}
m_ChildIndices = reader.ReadUInt32Array();
if (version < (4, 1)) //4.1 down
{
m_ChildThresholdArray = reader.ReadSingleArray();
}
if (version >= (4, 1)) //4.1 and up
{
m_Blend1dData = new Blend1dDataConstant(reader);
m_Blend2dData = new Blend2dDataConstant(reader);
}
if (version >= 5) //5.0 and up
{
m_BlendDirectData = new BlendDirectDataConstant(reader);
}
m_ClipID = reader.ReadUInt32();
if (version == 4 && version.Minor >= 5) //4.5 - 5.0
{
m_ClipIndex = reader.ReadUInt32();
}
m_Duration = reader.ReadSingle();
if (version >= (4, 1, 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();
var nodeList = new List<BlendTreeNodeConstant>();
for (var i = 0; i < numNodes; i++)
{
nodeList.Add(new BlendTreeNodeConstant(reader));
}
m_NodeArray = nodeList.ToArray();
if (version < (4, 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 numTransitions = reader.ReadInt32();
var transitionConstantList = new List<TransitionConstant>();
for (var i = 0; i < numTransitions; i++)
{
transitionConstantList.Add(new TransitionConstant(reader));
}
m_TransitionConstantArray = transitionConstantList.ToArray();
m_BlendTreeConstantIndexArray = reader.ReadInt32Array();
if (version < (5, 2)) //5.2 down
{
int numInfos = reader.ReadInt32();
var leafInfoList = new List<LeafInfoConstant>();
for (var i = 0; i < numInfos; i++)
{
leafInfoList.Add(new LeafInfoConstant(reader));
}
m_LeafInfoArray = leafInfoList.ToArray();
}
int numBlends = reader.ReadInt32();
var blendTreeConstantList = new List<BlendTreeConstant>();
for (var i = 0; i < numBlends; i++)
{
blendTreeConstantList.Add(new BlendTreeConstant(reader));
}
m_BlendTreeConstantArray = blendTreeConstantList.ToArray();
m_NameID = reader.ReadUInt32();
if (version >= (4, 3)) //4.3 and up
{
m_PathID = reader.ReadUInt32();
}
if (version >= 5) //5.0 and up
{
m_FullPathID = reader.ReadUInt32();
}
m_TagID = reader.ReadUInt32();
if (version >= (5, 1)) //5.1 and up
{
m_SpeedParamID = reader.ReadUInt32();
m_MirrorParamID = reader.ReadUInt32();
m_CycleOffsetParamID = reader.ReadUInt32();
}
if (version >= (2017, 2)) //2017.2 and up
{
var m_TimeParamID = reader.ReadUInt32();
}
m_Speed = reader.ReadSingle();
if (version >= (4, 1)) //4.1 and up
{
m_CycleOffset = reader.ReadSingle();
}
m_IKOnFeet = reader.ReadBoolean();
if (version >= 5) //5.0 and up
{
m_WriteDefaultValues = reader.ReadBoolean();
}
m_Loop = reader.ReadBoolean();
if (version >= (4, 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();
var conditionConstantList = new List<ConditionConstant>();
for (var i = 0; i < numConditions; i++)
{
conditionConstantList.Add(new ConditionConstant(reader));
}
m_ConditionConstantArray = conditionConstantList.ToArray();
}
}
public class SelectorStateConstant
{
public SelectorTransitionConstant[] m_TransitionConstantArray;
public uint m_FullPathID;
public bool m_isEntry;
public SelectorStateConstant(ObjectReader reader)
{
int numTransitions = reader.ReadInt32();
var transitionConstantList = new List<SelectorTransitionConstant>();
for (var i = 0; i < numTransitions; i++)
{
transitionConstantList.Add(new SelectorTransitionConstant(reader));
}
m_TransitionConstantArray = transitionConstantList.ToArray();
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();
var stateConstantList = new List<StateConstant>();
for (var i = 0; i < numStates; i++)
{
stateConstantList.Add(new StateConstant(reader));
}
m_StateConstantArray = stateConstantList.ToArray();
int numAnyStates = reader.ReadInt32();
var anyStateTransitionConstantList = new List<TransitionConstant>();
for (var i = 0; i < numAnyStates; i++)
{
anyStateTransitionConstantList.Add(new TransitionConstant(reader));
}
m_AnyStateTransitionConstantArray = anyStateTransitionConstantList.ToArray();
if (version >= 5) //5.0 and up
{
int numSelectors = reader.ReadInt32();
var selectorStateConstantList = new List<SelectorStateConstant>();
for (var i = 0; i < numSelectors; i++)
{
selectorStateConstantList.Add(new SelectorStateConstant(reader));
}
m_SelectorStateConstantArray = selectorStateConstantList.ToArray();
}
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 int[] m_EntityIdValues;
public ValueArray(ObjectReader reader)
{
var version = reader.version;
if (version < (5, 5)) //5.5 down
{
m_BoolValues = reader.ReadBooleanArray();
reader.AlignStream();
m_IntValues = reader.ReadInt32Array();
m_FloatValues = reader.ReadSingleArray();
}
if (version < (4, 3)) //4.3 down
{
m_VectorValues = reader.ReadVector4Array();
}
else
{
int numPosValues = reader.ReadInt32();
var positionValuesList = new List<Vector3>();
for (var i = 0; i < numPosValues; i++)
{
positionValuesList.Add(version >= (5, 4) //5.4 and up
? reader.ReadVector3()
: (Vector3)reader.ReadVector4());
}
m_PositionValues = positionValuesList.ToArray();
m_QuaternionValues = reader.ReadVector4Array();
int numScaleValues = reader.ReadInt32();
var scaleValuesList = new List<Vector3>();
for (var i = 0; i < numScaleValues; i++)
{
scaleValuesList.Add(version >= (5, 4) //5.4 and up
? reader.ReadVector3()
: (Vector3)reader.ReadVector4());
}
m_ScaleValues = scaleValuesList.ToArray();
if (version >= (5, 5)) //5.5 and up
{
m_FloatValues = reader.ReadSingleArray();
m_IntValues = reader.ReadInt32Array();
m_BoolValues = reader.ReadBooleanArray();
reader.AlignStream();
if (version >= (6000, 2)) //6000.2 and up
{
m_EntityIdValues = reader.ReadInt32Array();
}
}
}
}
}
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();
var layerList = new List<LayerConstant>();
for (var i = 0; i < numLayers; i++)
{
layerList.Add(new LayerConstant(reader));
}
m_LayerArray = layerList.ToArray();
int numStates = reader.ReadInt32();
var stateMachineList = new List<StateMachineConstant>();
for (var i = 0; i < numStates; i++)
{
stateMachineList.Add(new StateMachineConstant(reader));
}
m_StateMachineArray = stateMachineList.ToArray();
m_Values = new ValueArrayConstant(reader);
m_DefaultValues = new ValueArray(reader);
}
}
public sealed class AnimatorController : RuntimeAnimatorController
{
public List<PPtr<AnimationClip>> m_AnimationClips;
public List<KeyValuePair<uint, string>> m_TOS;
public AnimatorController(ObjectReader reader) : base(reader)
{
var m_ControllerSize = reader.ReadUInt32();
var m_Controller = new ControllerConstant(reader);
int tosSize = reader.ReadInt32();
m_TOS = new List<KeyValuePair<uint, string>>();
for (var i = 0; i < tosSize; i++)
{
m_TOS.Add(new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString()));
}
int numClips = reader.ReadInt32();
m_AnimationClips = new List<PPtr<AnimationClip>>();
for (var i = 0; i < numClips; i++)
{
m_AnimationClips.Add(new PPtr<AnimationClip>(reader));
}
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
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 List<AnimationClipOverride> m_Clips;
public AnimatorOverrideController(ObjectReader reader) : base(reader)
{
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
int numOverrides = reader.ReadInt32();
m_Clips = new List<AnimationClipOverride>();
for (var i = 0; i < numOverrides; i++)
{
m_Clips.Add(new AnimationClipOverride(reader));
}
}
}
}

View File

@@ -0,0 +1,70 @@
using System.Collections.Generic;
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 List<PPtr<Object>> m_PreloadTable;
public List<KeyValuePair<string, AssetInfo>> m_Container;
public string m_AssetBundleName;
public string[] m_Dependencies;
public bool m_IsStreamedSceneAssetBundle;
public AssetBundle(ObjectReader reader) : base(reader)
{
var m_PreloadTableSize = reader.ReadInt32();
m_PreloadTable = new List<PPtr<Object>>();
for (var i = 0; i < m_PreloadTableSize; i++)
{
m_PreloadTable.Add(new PPtr<Object>(reader));
}
var m_ContainerSize = reader.ReadInt32();
m_Container = new List<KeyValuePair<string, AssetInfo>>();
for (var i = 0; i < m_ContainerSize; i++)
{
m_Container.Add(new KeyValuePair<string, AssetInfo>(reader.ReadAlignedString(), new AssetInfo(reader)));
}
var m_MainAsset = new AssetInfo(reader);
if (version == (5, 4)) //5.4.x
{
var m_ClassVersionMapSize = reader.ReadInt32();
for (var i = 0; i < m_ClassVersionMapSize; i++)
{
var first = reader.ReadInt32();
var second = reader.ReadInt32();
}
}
if (version >= (4, 2)) //4.2 and up
{
var m_RuntimeCompatibility = reader.ReadUInt32();
}
if (version >= 5) //5.0 and up
{
m_AssetBundleName = reader.ReadAlignedString();
m_Dependencies = reader.ReadStringArray();
m_IsStreamedSceneAssetBundle = reader.ReadBoolean();
}
}
}
}

View File

@@ -0,0 +1,144 @@
namespace AssetStudio
{
public sealed class AudioClip : NamedObject
{
public int m_Format;
public FMODSoundType 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; //ulong
public long m_Size; //ulong
public ResourceReader m_AudioData;
public AudioClip(ObjectReader reader) : base(reader)
{
if (version < 5)
{
m_Format = reader.ReadInt32();
if (version >= (2, 6)) //2.6 to 5
{
m_Type = (FMODSoundType)reader.ReadInt32();
m_3D = reader.ReadBoolean();
m_UseHardware = reader.ReadBoolean();
reader.AlignStream();
}
else
{
m_Length = reader.ReadSingle();
m_Frequency = reader.ReadInt32();
m_Channels = m_Format != 0x05 ? m_Format >> 1 : 0;
}
if (version >= (3, 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.ReadUInt32();
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();
//StreamedResource m_Resource
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, m_Size);
}
else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_Size);
}
m_AudioData = resourceReader;
}
}
public enum FMODSoundType
{
UNKNOWN = 0,
AAC = 1,
AIFF = 2,
ASF = 3,
AT3 = 4,
CDDA = 5,
DLS = 6,
FLAC = 7,
FSB = 8,
GCADPCM = 9,
IT = 10,
MIDI = 11,
MOD = 12,
MPEG = 13,
OGGVORBIS = 14,
PLAYLIST = 15,
RAW = 16,
S3M = 17,
SF2 = 18,
USER = 19,
WAV = 20,
XM = 21,
XMA = 22,
VAG = 23,
AUDIOQUEUE = 24,
XWMA = 25,
BCWAV = 26,
AT9 = 27,
VORBIS = 28,
MEDIA_FOUNDATION = 29
}
public enum AudioCompressionFormat
{
PCM = 0,
Vorbis = 1,
ADPCM = 2,
MP3 = 3,
PSMVAG = 4,
HEVAG = 5,
XMA = 6,
AAC = 7,
GCADPCM = 8,
ATRAC9 = 9
}
}

View File

@@ -0,0 +1,314 @@
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 >= (5, 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 >= (5, 4)) //5.4 and up
{
m_Sgn = reader.ReadVector3();
}
else
{
m_Sgn = reader.ReadVector4();
}
m_Limit = new Limit(reader);
m_Length = reader.ReadSingle();
m_Type = reader.ReadUInt32();
}
}
public class Skeleton
{
public List<Node> m_Node;
public uint[] m_ID;
public Axes[] m_AxesArray;
public Skeleton(ObjectReader reader)
{
int numNodes = reader.ReadInt32();
m_Node = new List<Node>();
for (var i = 0; i < numNodes; i++)
{
m_Node.Add(new Node(reader));
}
m_ID = reader.ReadUInt32Array();
int numAxes = reader.ReadInt32();
var axesList = new List<Axes>();
for (var i = 0; i < numAxes; i++)
{
axesList.Add(new Axes(reader));
}
m_AxesArray = axesList.ToArray();
}
}
public class SkeletonPose
{
public List<xform> m_X;
public SkeletonPose(ObjectReader reader)
{
int numXforms = reader.ReadInt32();
m_X = new List<xform>();
for (var i = 0; i < numXforms; i++)
{
m_X.Add(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 List<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 < (2018, 2)) //2018.2 down
{
int numHandles = reader.ReadInt32();
m_Handles = new List<Handle>();
for (var i = 0; i < numHandles; i++)
{
m_Handles.Add(new Handle(reader));
}
int numColliders = reader.ReadInt32();
var colliderList = new List<Collider>();
for (var i = 0; i < numColliders; i++)
{
colliderList.Add(new Collider(reader));
}
m_ColliderArray = colliderList.ToArray();
}
m_HumanBoneIndex = reader.ReadInt32Array();
m_HumanBoneMass = reader.ReadSingleArray();
if (version < (2018, 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 >= (5, 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 >= (4, 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 >= (4, 3)) //4.3 and up
{
m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array();
}
m_RootMotionBoneIndex = reader.ReadInt32();
m_RootMotionBoneX = new xform(reader);
if (version >= (4, 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 List<KeyValuePair<uint, string>> m_TOS;
public Avatar(ObjectReader reader) : base(reader)
{
m_AvatarSize = reader.ReadUInt32();
m_Avatar = new AvatarConstant(reader);
int numTOS = reader.ReadInt32();
m_TOS = new List<KeyValuePair<uint, string>>();
for (var i = 0; i < numTOS; i++)
{
m_TOS.Add(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;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace AssetStudio
{
public abstract class Behaviour : Component
{
public byte m_Enabled;
public Behaviour() { }
protected Behaviour(ObjectReader reader) : base(reader)
{
m_Enabled = reader.ReadByte();
reader.AlignStream();
}
}
}

View File

@@ -0,0 +1,20 @@
namespace AssetStudio
{
public sealed class BuildSettings : Object
{
public string[] levels;
public string[] scenes;
public BuildSettings(ObjectReader reader) : base(reader)
{
if (reader.version < (5, 1)) //5.1 down
{
levels = reader.ReadStringArray();
}
else
{
scenes = reader.ReadStringArray();
}
}
}
}

View File

@@ -0,0 +1,14 @@
namespace AssetStudio
{
public abstract class Component : EditorExtension
{
public PPtr<GameObject> m_GameObject;
public Component() { }
protected Component(ObjectReader reader) : base(reader)
{
m_GameObject = new PPtr<GameObject>(reader);
}
}
}

View File

@@ -0,0 +1,16 @@
namespace AssetStudio
{
public abstract class EditorExtension : Object
{
protected EditorExtension() { }
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>
}
}
}
}

116
AssetStudio/Classes/Font.cs Normal file
View File

@@ -0,0 +1,116 @@
namespace AssetStudio
{
public sealed class Font : NamedObject
{
public byte[] m_FontData;
public Font(ObjectReader reader) : base(reader)
{
if (version >= (5, 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 (var i = 0; i < m_CharacterRects_size; i++)
{
reader.Position += 44;//CharacterInfo data 41
}
int m_KerningValues_size = reader.ReadInt32();
for (var 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 <= 3)
{
int m_FontCountX = reader.ReadInt32();
int m_FontCountY = reader.ReadInt32();
}
float m_Kerning = reader.ReadSingle();
float m_LineSpacing = reader.ReadSingle();
if (version <= 3)
{
int m_PerCharacterKerning_size = reader.ReadInt32();
for (var 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 (var 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 >= 4)
{
var flipped = reader.ReadBoolean();
reader.AlignStream();
}
}
var m_Texture = new PPtr<Texture>(reader);
int m_KerningValues_size = reader.ReadInt32();
for (var i = 0; i < m_KerningValues_size; i++)
{
int pairfirst = reader.ReadInt16();
int pairsecond = reader.ReadInt16();
float second = reader.ReadSingle();
}
if (version <= 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);
}
}
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Text.Json.Serialization;
namespace AssetStudio
{
public class GLTextureSettings
{
public int m_FilterMode;
public int m_Aniso;
public float m_MipBias;
public int m_WrapMode;
[JsonInclude]
private int m_WrapU { set => m_WrapMode = value; }
public GLTextureSettings() { }
public GLTextureSettings(ObjectReader reader)
{
var version = reader.version;
m_FilterMode = reader.ReadInt32();
m_Aniso = reader.ReadInt32();
m_MipBias = reader.ReadSingle();
if (version >= 2017)//2017.x and up
{
m_WrapMode = reader.ReadInt32(); //m_WrapU
var m_WrapV = reader.ReadInt32();
var m_WrapW = reader.ReadInt32();
}
else
{
m_WrapMode = reader.ReadInt32();
}
}
}
}

View File

@@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public sealed class GameObject : EditorExtension
{
public List<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;
[JsonIgnore]
public CubismModel CubismModel;
public GameObject(ObjectReader reader) : base(reader)
{
var m_ComponentSize = reader.ReadInt32();
m_Components = new List<PPtr<Component>>();
for (var i = 0; i < m_ComponentSize; i++)
{
if (version < (5, 5)) //5.5 down
{
var first = reader.ReadInt32();
}
m_Components.Add(new PPtr<Component>(reader));
}
var m_Layer = reader.ReadInt32();
if (version.IsTuanjie && (version > (2022, 3, 2) || (version == (2022, 3, 2) && version.Build >= 11))) //2022.3.2t11(1.1.3) and up
{
var m_HasEditorInfo = reader.ReadBoolean();
reader.AlignStream();
}
m_Name = reader.ReadAlignedString();
}
}
}

View File

@@ -0,0 +1,711 @@
namespace AssetStudio
{
public enum GraphicsFormat
{
/// <summary>
/// The format is not specified.
/// </summary>
None,
/// <summary>
/// A one-component, 8-bit unsigned normalized format that has a single 8-bit R component stored with sRGB nonlinear encoding.
/// </summary>
R8_SRGB,
/// <summary>
/// A two-component, 16-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_SRGB,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, and an 8-bit B component stored with sRGB nonlinear encoding in byte 2.
/// </summary>
R8G8B8_SRGB,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, an 8-bit B component stored with sRGB nonlinear encoding in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SRGB,
/// <summary>
/// A one-component, 8-bit unsigned normalized format that has a single 8-bit R component.
/// </summary>
R8_UNorm,
/// <summary>
/// A two-component, 16-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_UNorm,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_UNorm,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_UNorm,
/// <summary>
/// A one-component, 8-bit signed normalized format that has a single 8-bit R component.
/// </summary>
R8_SNorm,
/// <summary>
/// A two-component, 16-bit signed normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_SNorm,
/// <summary>
/// A three-component, 24-bit signed normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_SNorm,
/// <summary>
/// A four-component, 32-bit signed normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SNorm,
/// <summary>
/// A one-component, 8-bit unsigned integer format that has a single 8-bit R component.
/// </summary>
R8_UInt,
/// <summary>
/// A two-component, 16-bit unsigned integer format that has an 8-bit R component in byte 0, and an 8-bit G component in byte 1.
/// </summary>
R8G8_UInt,
/// <summary>
/// A three-component, 24-bit unsigned integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_UInt,
/// <summary>
/// A four-component, 32-bit unsigned integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_UInt,
/// <summary>
/// A one-component, 8-bit signed integer format that has a single 8-bit R component.
/// </summary>
R8_SInt,
/// <summary>
/// A two-component, 16-bit signed integer format that has an 8-bit R component in byte 0, and an 8-bit G component in byte 1.
/// </summary>
R8G8_SInt,
/// <summary>
/// A three-component, 24-bit signed integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_SInt,
/// <summary>
/// A four-component, 32-bit signed integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SInt,
/// <summary>
/// A one-component, 16-bit unsigned normalized format that has a single 16-bit R component.
/// </summary>
R16_UNorm,
/// <summary>
/// A two-component, 32-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_UNorm,
/// <summary>
/// A three-component, 48-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_UNorm,
/// <summary>
/// A four-component, 64-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_UNorm,
/// <summary>
/// A one-component, 16-bit signed normalized format that has a single 16-bit R component.
/// </summary>
R16_SNorm,
/// <summary>
/// A two-component, 32-bit signed normalized format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SNorm,
/// <summary>
/// A three-component, 48-bit signed normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SNorm,
/// <summary>
/// A four-component, 64-bit signed normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SNorm,
/// <summary>
/// A one-component, 16-bit unsigned integer format that has a single 16-bit R component.
/// </summary>
R16_UInt,
/// <summary>
/// A two-component, 32-bit unsigned integer format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_UInt,
/// <summary>
/// A three-component, 48-bit unsigned integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_UInt,
/// <summary>
/// A four-component, 64-bit unsigned integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_UInt,
/// <summary>
/// A one-component, 16-bit signed integer format that has a single 16-bit R component.
/// </summary>
R16_SInt,
/// <summary>
/// A two-component, 32-bit signed integer format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SInt,
/// <summary>
/// A three-component, 48-bit signed integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SInt,
/// <summary>
/// A four-component, 64-bit signed integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SInt,
/// <summary>
/// A one-component, 32-bit unsigned integer format that has a single 32-bit R component.
/// </summary>
R32_UInt,
/// <summary>
/// A two-component, 64-bit unsigned integer format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_UInt,
/// <summary>
/// A three-component, 96-bit unsigned integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_UInt,
/// <summary>
/// A four-component, 128-bit unsigned integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_UInt,
/// <summary>
/// A one-component, 32-bit signed integer format that has a single 32-bit R component.
/// </summary>
R32_SInt,
/// <summary>
/// A two-component, 64-bit signed integer format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_SInt,
/// <summary>
/// A three-component, 96-bit signed integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_SInt,
/// <summary>
/// A four-component, 128-bit signed integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_SInt,
/// <summary>
/// A one-component, 16-bit signed floating-point format that has a single 16-bit R component.
/// </summary>
R16_SFloat,
/// <summary>
/// A two-component, 32-bit signed floating-point format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SFloat,
/// <summary>
/// A three-component, 48-bit signed floating-point format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SFloat,
/// <summary>
/// A four-component, 64-bit signed floating-point format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SFloat,
/// <summary>
/// A one-component, 32-bit signed floating-point format that has a single 32-bit R component.
/// </summary>
R32_SFloat,
/// <summary>
/// A two-component, 64-bit signed floating-point format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_SFloat,
/// <summary>
/// A three-component, 96-bit signed floating-point format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_SFloat,
/// <summary>
/// A four-component, 128-bit signed floating-point format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_SFloat,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit B component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, and an 8-bit R component stored with sRGB nonlinear encoding in byte 2.
/// </summary>
B8G8R8_SRGB = 56,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit B component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, an 8-bit R component stored with sRGB nonlinear encoding in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SRGB,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_UNorm,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_UNorm,
/// <summary>
/// A three-component, 24-bit signed normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_SNorm,
/// <summary>
/// A four-component, 32-bit signed normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SNorm,
/// <summary>
/// A three-component, 24-bit unsigned integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2
/// </summary>
B8G8R8_UInt,
/// <summary>
/// A four-component, 32-bit unsigned integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_UInt,
/// <summary>
/// A three-component, 24-bit signed integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_SInt,
/// <summary>
/// A four-component, 32-bit signed integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SInt,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 4-bit R component in bits 12..15, a 4-bit G component in bits 8..11, a 4-bit B component in bits 4..7, and a 4-bit A component in bits 0..3.
/// </summary>
R4G4B4A4_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 4-bit B component in bits 12..15, a 4-bit G component in bits 8..11, a 4-bit R component in bits 4..7, and a 4-bit A component in bits 0..3.
/// </summary>
B4G4R4A4_UNormPack16,
/// <summary>
/// A three-component, 16-bit packed unsigned normalized format that has a 5-bit R component in bits 11..15, a 6-bit G component in bits 5..10, and a 5-bit B component in bits 0..4.
/// </summary>
R5G6B5_UNormPack16,
/// <summary>
/// A three-component, 16-bit packed unsigned normalized format that has a 5-bit B component in bits 11..15, a 6-bit G component in bits 5..10, and a 5-bit R component in bits 0..4.
/// </summary>
B5G6R5_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 5-bit R component in bits 11..15, a 5-bit G component in bits 6..10, a 5-bit B component in bits 1..5, and a 1-bit A component in bit 0.
/// </summary>
R5G5B5A1_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 5-bit B component in bits 11..15, a 5-bit G component in bits 6..10, a 5-bit R component in bits 1..5, and a 1-bit A component in bit 0.
/// </summary>
B5G5R5A1_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 1-bit A component in bit 15, a 5-bit R component in bits 10..14, a 5-bit G component in bits 5..9, and a 5-bit B component in bits 0..4.
/// </summary>
A1R5G5B5_UNormPack16,
/// <summary>
/// A three-component, 32-bit packed unsigned floating-point format that has a 5-bit shared exponent in bits 27..31, a 9-bit B component mantissa in bits 18..26, a 9-bit G component mantissa in bits 9..17, and a 9-bit R component mantissa in bits 0..8.
/// </summary>
E5B9G9R9_UFloatPack32,
/// <summary>
/// A three-component, 32-bit packed unsigned floating-point format that has a 10-bit B component in bits 22..31, an 11-bit G component in bits 11..21, an 11-bit R component in bits 0..10.
/// </summary>
B10G11R11_UFloatPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_UNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned integer format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_UIntPack32,
/// <summary>
/// A four-component, 32-bit packed signed integer format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_SIntPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_UNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned integer format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_UIntPack32,
/// <summary>
/// A four-component, 32-bit packed signed integer format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_SIntPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A2R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion). The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A2R10G10B10_XRUNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion).
/// </summary>
R10G10B10_XRUNormPack32,
/// <summary>
/// A four-component, 64-bit packed unsigned normalized format that has a 10-bit A component in bits 30..39, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A10R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 64-bit packed unsigned normalized format that has a 10-bit A component in bits 30..39, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion). The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A10R10G10B10_XRUNormPack32,
/// <summary>
/// A one-component, 16-bit unsigned normalized format that has a single 16-bit depth component.
/// </summary>
D16_UNorm = 90,
/// <summary>
/// A two-component, 32-bit format that has 24 unsigned normalized bits in the depth component and, optionally: 8 bits that are unused.
/// </summary>
D24_UNorm,
/// <summary>
/// A two-component, 32-bit packed format that has 8 unsigned integer bits in the stencil component, and 24 unsigned normalized bits in the depth component.
/// </summary>
D24_UNorm_S8_UInt,
/// <summary>
/// A one-component, 32-bit signed floating-point format that has 32-bits in the depth component.
/// </summary>
D32_SFloat,
/// <summary>
/// A two-component format that has 32 signed float bits in the depth component and 8 unsigned integer bits in the stencil component. There are optionally: 24-bits that are unused.
/// </summary>
D32_SFloat_S8_UInt,
/// <summary>
/// A one-component, 8-bit unsigned integer format that has 8-bits in the stencil component.
/// </summary>
S8_UInt,
/// <summary>
/// A three-component, block-compressed format (also known as BC1). Each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has a 1 bit alpha channel.
/// </summary>
RGBA_DXT1_SRGB,
/// <summary>
/// A three-component, block-compressed format (also known as BC1). Each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has a 1 bit alpha channel.
/// </summary>
RGBA_DXT1_UNorm,
/// <summary>
/// A four-component, block-compressed format (also known as BC2) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding.
/// </summary>
RGBA_DXT3_SRGB,
/// <summary>
/// A four-component, block-compressed format (also known as BC2) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_DXT3_UNorm,
/// <summary>
/// A four-component, block-compressed format (also known as BC3) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding.
/// </summary>
RGBA_DXT5_SRGB,
/// <summary>
/// A four-component, block-compressed format (also known as BC3) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_DXT5_UNorm,
/// <summary>
/// A one-component, block-compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized red texel data.
/// </summary>
R_BC4_UNorm,
/// <summary>
/// A one-component, block-compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of signed normalized red texel data.
/// </summary>
R_BC4_SNorm,
/// <summary>
/// A two-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_BC5_UNorm,
/// <summary>
/// A two-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_BC5_SNorm,
/// <summary>
/// A three-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned floating-point RGB texel data.
/// </summary>
RGB_BC6H_UFloat,
/// <summary>
/// A three-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed floating-point RGB texel data.
/// </summary>
RGB_BC6H_SFloat,
/// <summary>
/// A four-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_BC7_SRGB,
/// <summary>
/// A four-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_BC7_UNorm,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_2Bpp_SRGB,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_2Bpp_UNorm,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_4Bpp_SRGB,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_4Bpp_UNorm,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_PVRTC_2Bpp_SRGB,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values.
/// </summary>
RGBA_PVRTC_2Bpp_UNorm,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_PVRTC_4Bpp_SRGB,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values.
/// </summary>
RGBA_PVRTC_4Bpp_UNorm,
/// <summary>
/// A three-component, ETC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC_UNorm,
/// <summary>
/// A three-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC2_SRGB,
/// <summary>
/// A three-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC2_UNorm,
/// <summary>
/// A four-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding, and provides 1 bit of alpha.
/// </summary>
RGB_A1_ETC2_SRGB,
/// <summary>
/// A four-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data, and provides 1 bit of alpha.
/// </summary>
RGB_A1_ETC2_UNorm,
/// <summary>
/// A four-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_ETC2_SRGB,
/// <summary>
/// A four-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_ETC2_UNorm,
/// <summary>
/// A one-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized red texel data.
/// </summary>
R_EAC_UNorm,
/// <summary>
/// A one-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of signed normalized red texel data.
/// </summary>
R_EAC_SNorm,
/// <summary>
/// A two-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_EAC_UNorm,
/// <summary>
/// A two-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_EAC_SNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC4X4_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC4X4_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC5X5_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC5X5_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC6X6_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC6X6_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC8X8_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC8X8_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC10X10_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC10X10_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC12X12_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC12X12_UNorm,
/// <summary>
/// YUV 4:2:2 Video resource format.
/// </summary>
YUV2,
/// <summary>
/// GraphicsFormat.YUV2.
/// </summary>
VideoAuto = 144,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC4X4_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC5X5_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC6X6_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC8X8_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC10X10_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC12X12_UFloat,
/// <summary>
/// A two-component, 24-bit format that has 16 unsigned normalized bits in the depth component and 8 unsigned integer bits in the stencil component. Most platforms do not support this format.
/// </summary>
D16_UNorm_S8_UInt,
}
public static class GraphicsFormatExtension
{
public static TextureFormat ToTextureFormat(this GraphicsFormat graphicsFormat)
{
switch (graphicsFormat)
{
case GraphicsFormat.R8_SRGB:
case GraphicsFormat.R8_UInt:
case GraphicsFormat.R8_UNorm:
return TextureFormat.R8;
case GraphicsFormat.R8G8_SRGB:
case GraphicsFormat.R8G8_UInt:
case GraphicsFormat.R8G8_UNorm:
return TextureFormat.RG16;
case GraphicsFormat.R8G8B8_SRGB:
case GraphicsFormat.R8G8B8_UInt:
case GraphicsFormat.R8G8B8_UNorm:
return TextureFormat.RGB24;
case GraphicsFormat.R8G8B8A8_SRGB:
case GraphicsFormat.R8G8B8A8_UInt:
case GraphicsFormat.R8G8B8A8_UNorm:
return TextureFormat.RGBA32;
case GraphicsFormat.R16_UInt:
case GraphicsFormat.R16_UNorm:
return TextureFormat.R16;
case GraphicsFormat.R16G16_UInt:
case GraphicsFormat.R16G16_UNorm:
return TextureFormat.RG32;
case GraphicsFormat.R16G16B16_UInt:
case GraphicsFormat.R16G16B16_UNorm:
return TextureFormat.RGB48;
case GraphicsFormat.R16G16B16A16_UInt:
case GraphicsFormat.R16G16B16A16_UNorm:
return TextureFormat.RGBA64;
case GraphicsFormat.R16_SFloat:
return TextureFormat.RHalf;
case GraphicsFormat.R16G16_SFloat:
return TextureFormat.RGHalf;
case GraphicsFormat.R16G16B16_SFloat: //?
case GraphicsFormat.R16G16B16A16_SFloat:
return TextureFormat.RGBAHalf;
case GraphicsFormat.R32_SFloat:
return TextureFormat.RFloat;
case GraphicsFormat.R32G32_SFloat:
return TextureFormat.RGFloat;
case GraphicsFormat.R32G32B32_SFloat: //?
case GraphicsFormat.R32G32B32A32_SFloat:
return TextureFormat.RGBAFloat;
case GraphicsFormat.B8G8R8A8_SRGB:
case GraphicsFormat.B8G8R8A8_UInt:
case GraphicsFormat.B8G8R8A8_UNorm:
return TextureFormat.BGRA32;
case GraphicsFormat.E5B9G9R9_UFloatPack32:
return TextureFormat.RGB9e5Float;
case GraphicsFormat.RGBA_DXT1_SRGB:
case GraphicsFormat.RGBA_DXT1_UNorm:
return TextureFormat.DXT1;
case GraphicsFormat.RGBA_DXT3_SRGB:
case GraphicsFormat.RGBA_DXT3_UNorm:
return TextureFormat.DXT3;
case GraphicsFormat.RGBA_DXT5_SRGB:
case GraphicsFormat.RGBA_DXT5_UNorm:
return TextureFormat.DXT5;
case GraphicsFormat.R_BC4_UNorm:
return TextureFormat.BC4;
case GraphicsFormat.RG_BC5_UNorm:
return TextureFormat.BC5;
case GraphicsFormat.RGB_BC6H_SFloat:
case GraphicsFormat.RGB_BC6H_UFloat:
return TextureFormat.BC6H;
case GraphicsFormat.RGBA_BC7_SRGB:
case GraphicsFormat.RGBA_BC7_UNorm:
return TextureFormat.BC7;
case GraphicsFormat.RGB_PVRTC_2Bpp_SRGB:
case GraphicsFormat.RGB_PVRTC_2Bpp_UNorm:
case GraphicsFormat.RGBA_PVRTC_2Bpp_SRGB:
case GraphicsFormat.RGBA_PVRTC_2Bpp_UNorm:
return TextureFormat.PVRTC_RGBA2;
case GraphicsFormat.RGB_PVRTC_4Bpp_SRGB:
case GraphicsFormat.RGB_PVRTC_4Bpp_UNorm:
case GraphicsFormat.RGBA_PVRTC_4Bpp_SRGB:
case GraphicsFormat.RGBA_PVRTC_4Bpp_UNorm:
return TextureFormat.PVRTC_RGBA4;
case GraphicsFormat.RGB_ETC_UNorm:
return TextureFormat.ETC_RGB4;
case GraphicsFormat.RGB_ETC2_SRGB:
case GraphicsFormat.RGB_ETC2_UNorm:
return TextureFormat.ETC2_RGB;
case GraphicsFormat.RGB_A1_ETC2_SRGB:
case GraphicsFormat.RGB_A1_ETC2_UNorm:
return TextureFormat.ETC2_RGBA1;
case GraphicsFormat.RGBA_ETC2_SRGB:
case GraphicsFormat.RGBA_ETC2_UNorm:
return TextureFormat.ETC2_RGBA8;
case GraphicsFormat.R_EAC_UNorm:
return TextureFormat.EAC_R;
case GraphicsFormat.R_EAC_SNorm:
return TextureFormat.EAC_R_SIGNED;
case GraphicsFormat.RG_EAC_UNorm:
return TextureFormat.EAC_RG;
case GraphicsFormat.RG_EAC_SNorm:
return TextureFormat.EAC_RG_SIGNED;
case GraphicsFormat.RGBA_ASTC4X4_SRGB:
case GraphicsFormat.RGBA_ASTC4X4_UNorm:
return TextureFormat.ASTC_RGBA_4x4;
case GraphicsFormat.RGBA_ASTC5X5_SRGB:
case GraphicsFormat.RGBA_ASTC5X5_UNorm:
return TextureFormat.ASTC_RGBA_5x5;
case GraphicsFormat.RGBA_ASTC6X6_SRGB:
case GraphicsFormat.RGBA_ASTC6X6_UNorm:
return TextureFormat.ASTC_RGBA_6x6;
case GraphicsFormat.RGBA_ASTC8X8_SRGB:
case GraphicsFormat.RGBA_ASTC8X8_UNorm:
return TextureFormat.ASTC_RGBA_8x8;
case GraphicsFormat.RGBA_ASTC10X10_SRGB:
case GraphicsFormat.RGBA_ASTC10X10_UNorm:
return TextureFormat.ASTC_RGBA_10x10;
case GraphicsFormat.RGBA_ASTC12X12_SRGB:
case GraphicsFormat.RGBA_ASTC12X12_UNorm:
return TextureFormat.ASTC_RGBA_12x12;
case GraphicsFormat.YUV2:
case GraphicsFormat.VideoAuto:
return TextureFormat.YUY2;
default:
return 0;
}
}
}
}

View File

@@ -0,0 +1,138 @@
using System.Collections.Generic;
using System.Text.Json;
namespace AssetStudio
{
public class UnityTexEnv
{
public PPtr<Texture> m_Texture;
public Vector2 m_Scale;
public Vector2 m_Offset;
public UnityTexEnv() { }
public UnityTexEnv(ObjectReader reader)
{
m_Texture = new PPtr<Texture>(reader);
m_Scale = reader.ReadVector2();
m_Offset = reader.ReadVector2();
}
}
public class UnityPropertySheet
{
public List<KeyValuePair<string, UnityTexEnv>> m_TexEnvs;
public List<KeyValuePair<string, int>> m_Ints;
public List<KeyValuePair<string, float>> m_Floats;
public List<KeyValuePair<string, Color>> m_Colors;
public UnityPropertySheet() { }
public UnityPropertySheet(ObjectReader reader)
{
var version = reader.version;
int m_TexEnvsSize = reader.ReadInt32();
m_TexEnvs = new List<KeyValuePair<string, UnityTexEnv>>();
for (var i = 0; i < m_TexEnvsSize; i++)
{
m_TexEnvs.Add(new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader)));
}
if (version >= 2021) //2021.1 and up
{
int m_IntsSize = reader.ReadInt32();
m_Ints = new List<KeyValuePair<string, int>>();
for (var i = 0; i < m_IntsSize; i++)
{
m_Ints.Add(new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32()));
}
}
int m_FloatsSize = reader.ReadInt32();
m_Floats = new List<KeyValuePair<string, float>>();
for (var i = 0; i < m_FloatsSize; i++)
{
m_Floats.Add(new KeyValuePair<string, float>(reader.ReadAlignedString(), reader.ReadSingle()));
}
int m_ColorsSize = reader.ReadInt32();
m_Colors = new List<KeyValuePair<string, Color>>();
for (var i = 0; i < m_ColorsSize; i++)
{
m_Colors.Add(new KeyValuePair<string, Color>(reader.ReadAlignedString(), reader.ReadColor4()));
}
}
}
public sealed class Material : NamedObject
{
public PPtr<Shader> m_Shader;
public UnityPropertySheet m_SavedProperties;
public Material() { }
public Material(ObjectReader reader, byte[] type, JsonSerializerOptions jsonOptions) : base(reader)
{
var parsedMaterial = JsonSerializer.Deserialize<Material>(type, jsonOptions);
m_Shader = parsedMaterial.m_Shader;
m_SavedProperties = parsedMaterial.m_SavedProperties;
}
public Material(ObjectReader reader) : base(reader)
{
m_Shader = new PPtr<Shader>(reader);
if (version == 4 && version.Minor >= 1) //4.1 - 4.7.2
{
var m_ShaderKeywords = reader.ReadStringArray();
}
if (version >= (2021, 2, 18)) //2021.2.18 and up
{
var m_ValidKeywords = reader.ReadStringArray();
var m_InvalidKeywords = reader.ReadStringArray();
}
else if (version >= 5) //5.0 - 2021.2.17
{
var m_ShaderKeywords = reader.ReadAlignedString();
}
if (version >= 5) //5.0 and up
{
var m_LightmapFlags = reader.ReadUInt32();
}
if (version >= (5, 6)) //5.6 and up
{
var m_EnableInstancingVariants = reader.ReadBoolean();
//var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up
reader.AlignStream();
}
if (version >= (4, 3)) //4.3 and up
{
var m_CustomRenderQueue = reader.ReadInt32();
}
if (version >= (5, 1)) //5.1 and up
{
var stringTagMapSize = reader.ReadInt32();
for (var i = 0; i < stringTagMapSize; i++)
{
var first = reader.ReadAlignedString();
var second = reader.ReadAlignedString();
}
}
if (version >= (5, 6)) //5.6 and up
{
var disabledShaderPasses = reader.ReadStringArray();
}
m_SavedProperties = new UnityPropertySheet(reader);
//vector m_BuildTextureStacks 2020 and up
}
}
}

1562
AssetStudio/Classes/Mesh.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
namespace AssetStudio
{
public sealed class MeshFilter : Component
{
public PPtr<Mesh> m_Mesh;
public MeshFilter(ObjectReader reader) : base(reader)
{
m_Mesh = new PPtr<Mesh>(reader);
}
}
}

View File

@@ -0,0 +1,10 @@
namespace AssetStudio
{
public sealed class MeshRenderer : Renderer
{
public MeshRenderer(ObjectReader reader) : base(reader)
{
}
}
}

View File

@@ -0,0 +1,16 @@
namespace AssetStudio
{
public class MonoBehaviour : Behaviour
{
public PPtr<MonoScript> m_Script;
public string m_Name;
public MonoBehaviour() { }
public MonoBehaviour(ObjectReader reader) : base(reader)
{
m_Script = new PPtr<MonoScript>(reader);
m_Name = reader.ReadAlignedString();
}
}
}

View File

@@ -0,0 +1,41 @@
namespace AssetStudio
{
public sealed class MonoScript : NamedObject
{
public string m_ClassName;
public string m_Namespace;
public string m_AssemblyName;
public MonoScript(ObjectReader reader) : base(reader)
{
if (version >= (3, 4)) //3.4 and up
{
var m_ExecutionOrder = reader.ReadInt32();
if (version < 5) //5.0 down
{
var m_PropertiesHash = reader.ReadUInt32();
}
else
{
var m_PropertiesHash = reader.ReadBytes(16);
}
}
if (version < 3) //3.0 down
{
var m_PathName = reader.ReadAlignedString();
}
m_ClassName = reader.ReadAlignedString();
if (version >= 3) //3.0 and up
{
m_Namespace = reader.ReadAlignedString();
}
m_AssemblyName = reader.ReadAlignedString();
if (version < (2018, 2)) //2018.2 down
{
var m_IsEditorScript = reader.ReadBoolean();
}
}
}
}

View File

@@ -0,0 +1,19 @@
namespace AssetStudio
{
public sealed class MovieTexture : Texture
{
public byte[] m_MovieData;
public PPtr<AudioClip> m_AudioClip;
public MovieTexture(ObjectReader reader) : base(reader)
{
if (reader.version < (2019, 3)) //2019.3 down
{
var m_Loop = reader.ReadBoolean();
reader.AlignStream();
m_AudioClip = new PPtr<AudioClip>(reader);
m_MovieData = reader.ReadUInt8Array();
}
}
}
}

View File

@@ -0,0 +1,14 @@
namespace AssetStudio
{
public class NamedObject : EditorExtension
{
public string m_Name;
protected NamedObject() { }
protected NamedObject(ObjectReader reader) : base(reader)
{
m_Name = reader.ReadAlignedString();
}
}
}

View File

@@ -0,0 +1,135 @@
using System.Collections.Specialized;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public class Object
{
[JsonIgnore]
public SerializedFile assetsFile;
[JsonIgnore]
public ObjectReader reader;
public long m_PathID;
[JsonIgnore]
public UnityVersion version;
[JsonIgnore]
public BuildTarget platform;
[JsonConverter(typeof(JsonStringEnumConverter))]
public ClassIDType type;
[JsonIgnore]
public SerializedType serializedType;
public int classID;
public uint byteSize;
[JsonIgnore]
public string Name;
private static readonly JsonSerializerOptions jsonOptions;
static Object()
{
jsonOptions = new JsonSerializerOptions
{
Converters = { new JsonConverterHelper.FloatConverter() },
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,
ReferenceHandler = ReferenceHandler.IgnoreCycles,
PropertyNameCaseInsensitive = true,
IncludeFields = true,
WriteIndented = true,
};
}
public Object() { }
public Object(ObjectReader reader)
{
this.reader = reader;
reader.Reset();
assetsFile = reader.assetsFile;
type = reader.type;
m_PathID = reader.m_PathID;
version = reader.version;
platform = reader.platform;
serializedType = reader.serializedType;
classID = reader.classID;
byteSize = reader.byteSize;
if (platform == BuildTarget.NoTarget)
{
var m_ObjectHideFlags = reader.ReadUInt32();
}
}
public string DumpObject()
{
string str = null;
try
{
if (this is Mesh m_Mesh)
{
m_Mesh.ProcessData();
}
str = JsonSerializer.Deserialize<JsonObject>(JsonSerializer.SerializeToUtf8Bytes(this, GetType(), jsonOptions))
.ToJsonString(jsonOptions).Replace(" ", " ");
}
catch
{
//ignore
}
return str;
}
public string Dump(TypeTree m_Type = null)
{
m_Type = m_Type ?? serializedType?.m_Type;
if (m_Type == null)
return null;
return TypeTreeHelper.ReadTypeString(m_Type, reader);
}
public OrderedDictionary ToType(TypeTree m_Type = null)
{
m_Type = m_Type ?? serializedType?.m_Type;
if (m_Type == null)
return null;
return TypeTreeHelper.ReadType(m_Type, reader);
}
public JsonDocument ToJsonDoc(TypeTree m_Type = null)
{
var typeDict = ToType(m_Type);
try
{
if (typeDict != null)
{
return JsonSerializer.SerializeToDocument(typeDict, jsonOptions);
}
if (this is Mesh m_Mesh)
{
m_Mesh.ProcessData();
}
return JsonSerializer.SerializeToDocument(this, GetType(), jsonOptions);
}
catch
{
//ignore
}
return null;
}
public byte[] GetRawData()
{
reader.Reset();
return reader.ReadBytes((int)byteSize);
}
}
}

143
AssetStudio/Classes/PPtr.cs Normal file
View File

@@ -0,0 +1,143 @@
using System;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public sealed class PPtr<T> where T : Object
{
public int m_FileID;
public long m_PathID;
public string Name => _assetsFile != null && TryGet(out var result) ? result.Name : string.Empty;
private int _index = -2; //-2 - Prepare, -1 - Missing
private SerializedFile _assetsFile;
[JsonIgnore]
public SerializedFile AssetsFile
{
get => _assetsFile;
set => _assetsFile = value;
}
public PPtr(ObjectReader reader)
{
m_FileID = reader.ReadInt32();
m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();
_assetsFile = reader.assetsFile;
}
public PPtr() { }
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, SerializedFile assetsFile = null)
{
_assetsFile = _assetsFile ?? assetsFile;
if (!IsNull && 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, SerializedFile assetsFile = null) where T2 : Object
{
_assetsFile = _assetsFile ?? assetsFile;
if (!IsNull && 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;
}
}

View File

@@ -0,0 +1,49 @@
namespace AssetStudio
{
public sealed class PlayerSettings : Object
{
public string companyName;
public string productName;
public PlayerSettings(ObjectReader reader) : base(reader)
{
if (version >= (3, 0))
{
if (version >= (5, 4)) //5.4.0 and 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 < (5, 3)) //5.3 down
{
if (version < 5) //5.0 down
{
int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics
if (version >= (4, 6)) //4.6 and up
{
var targetIOSGraphics = reader.ReadInt32();
}
}
int targetResolution = reader.ReadInt32();
}
else
{
var useOnDemandResources = reader.ReadBoolean();
reader.AlignStream();
}
if (version >= (3, 5)) //3.5 and up
{
var accelerometerFrequency = reader.ReadInt32();
}
}
companyName = reader.ReadAlignedString();
productName = reader.ReadAlignedString();
}
}
}

View File

@@ -0,0 +1,37 @@
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class PreloadData : NamedObject
{
public List<PPtr<Object>> m_Assets;
public PreloadData(ObjectReader reader) : base(reader)
{
var m_PreloadTableSize = reader.ReadInt32();
m_Assets = new List<PPtr<Object>>();
for (var i = 0; i < m_PreloadTableSize; i++)
{
m_Assets.Add(new PPtr<Object>(reader));
}
/*
if (version[0] >= 5) //5.0 and up
{
var m_DependenciesSize = reader.ReadInt32();
var m_Dependencies = new string[m_DependenciesSize];
for (var i = 0; i < m_DependenciesSize; i++)
{
m_Dependencies[i] = reader.ReadAlignedString();
}
}
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
{
var m_ExplicitDataLayout = reader.ReadBoolean();
}
*/
}
}
}

View File

@@ -0,0 +1,9 @@
namespace AssetStudio
{
public sealed class RectTransform : Transform
{
public RectTransform(ObjectReader reader) : base(reader)
{
}
}
}

View File

@@ -0,0 +1,191 @@
using System.Collections.Generic;
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 List<PPtr<Material>> m_Materials;
public StaticBatchInfo m_StaticBatchInfo;
public uint[] m_SubsetIndices;
protected Renderer(ObjectReader reader) : base(reader)
{
if (version < 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 >= (5, 4)) //5.4 and up
{
var m_Enabled = reader.ReadBoolean();
var m_CastShadows = reader.ReadByte();
var m_ReceiveShadows = reader.ReadByte();
if (version >= (2017, 2)) //2017.2 and up
{
var m_DynamicOccludee = reader.ReadByte();
}
if (version >= 2021) //2021.1 and up
{
var m_StaticShadowCaster = reader.ReadByte();
}
var m_MotionVectors = reader.ReadByte();
var m_LightProbeUsage = reader.ReadByte();
var m_ReflectionProbeUsage = reader.ReadByte();
if (version >= (2019, 3)) //2019.3 and up
{
var m_RayTracingMode = reader.ReadByte();
}
if (version >= 2020) //2020.1 and up
{
var m_RayTraceProcedural = reader.ReadByte();
}
if (version.IsTuanjie) //2022.3.2t3(1.0.0) and up
{
var m_virtualGeometry = reader.ReadByte();
var m_virtualGeometryShadow = reader.ReadByte();
if (version > (2022, 3, 48) || (version == (2022, 3, 48) && version.Build >= 3)) //2022.3.48t3(1.4.0) and up
{
reader.AlignStream();
var m_ShadingRate = reader.ReadByte();
if (version >= (2022, 3, 61)) //2022.3.61t1(1.6.0) and up
{
var m_ForceDisableGRD = reader.ReadByte();
}
}
}
if (version >= (2023, 2)) //2023.2 and up
{
var m_RayTracingAccelStructBuildFlagsOverride = reader.ReadByte();
var m_RayTracingAccelStructBuildFlags = reader.ReadByte();
}
if (version >= (2023, 3)) //2023.3 and up
{
var m_SmallMeshCulling = reader.ReadByte();
}
reader.AlignStream();
if (version >= (6000, 2)) //6000.2 and up
{
var m_ForceMeshLod = reader.ReadInt16();
reader.AlignStream();
var m_MeshLodSelectionBias = reader.ReadSingle();
}
}
else
{
var m_Enabled = reader.ReadBoolean();
reader.AlignStream();
var m_CastShadows = reader.ReadByte();
var m_ReceiveShadows = reader.ReadBoolean();
reader.AlignStream();
}
if (version >= 2018) //2018 and up
{
var m_RenderingLayerMask = reader.ReadUInt32();
}
if (version >= (2018, 3)) //2018.3 and up
{
var m_RendererPriority = reader.ReadInt32();
}
var m_LightmapIndex = reader.ReadUInt16();
var m_LightmapIndexDynamic = reader.ReadUInt16();
}
if (version >= 3) //3.0 and up
{
var m_LightmapTilingOffset = reader.ReadVector4();
}
if (version >= 5) //5.0 and up
{
var m_LightmapTilingOffsetDynamic = reader.ReadVector4();
}
var m_MaterialsSize = reader.ReadInt32();
m_Materials = new List<PPtr<Material>>();
for (var i = 0; i < m_MaterialsSize; i++)
{
m_Materials.Add(new PPtr<Material>(reader));
}
if (version < 3) //3.0 down
{
var m_LightmapTilingOffset = reader.ReadVector4();
}
else //3.0 and up
{
if (version >= (5, 5)) //5.5 and up
{
m_StaticBatchInfo = new StaticBatchInfo(reader);
}
else
{
m_SubsetIndices = reader.ReadUInt32Array();
}
var m_StaticBatchRoot = new PPtr<Transform>(reader);
}
if (version >= (5, 4)) //5.4 and up
{
var m_ProbeAnchor = new PPtr<Transform>(reader);
var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);
}
else if (version >= (3, 5)) //3.5 - 5.3
{
var m_UseLightProbes = reader.ReadBoolean();
reader.AlignStream();
if (version >= 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 >= (4, 3)) //4.3 and up
{
if (version == (4, 3)) //4.3
{
var m_SortingLayer = reader.ReadInt16();
}
else
{
var m_SortingLayerID = reader.ReadInt32();
}
if (version > (5, 6) || (version == (5, 6) && version.Build >= 3)) //5.6.0f3 and up
{
var m_SortingLayer = reader.ReadInt16();
}
var m_SortingOrder = reader.ReadInt16();
reader.AlignStream();
if (version >= (6000, 3)) //6000.3 and up
{
var m_MaskInteraction = reader.ReadInt32();
}
}
}
}
}

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace AssetStudio
{
public class ResourceManager : Object
{
public List<KeyValuePair<string, PPtr<Object>>> m_Container;
public ResourceManager(ObjectReader reader) : base(reader)
{
var m_ContainerSize = reader.ReadInt32();
m_Container = new List<KeyValuePair<string, PPtr<Object>>>();
for (var i = 0; i < m_ContainerSize; i++)
{
m_Container.Add(new KeyValuePair<string, PPtr<Object>>(reader.ReadAlignedString(), new PPtr<Object>(reader)));
}
}
}
}

View File

@@ -0,0 +1,10 @@
namespace AssetStudio
{
public abstract class RuntimeAnimatorController : NamedObject
{
protected RuntimeAnimatorController(ObjectReader reader) : base(reader)
{
}
}
}

View File

@@ -0,0 +1,952 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AssetStudio
{
public class Hash128
{
public byte[] bytes;
public Hash128(BinaryReader reader)
{
bytes = reader.ReadBytes(16);
}
}
public class StructParameter
{
public List<MatrixParameter> m_MatrixParams;
public List<VectorParameter> m_VectorParams;
public StructParameter(BinaryReader reader)
{
var m_NameIndex = reader.ReadInt32();
var m_Index = reader.ReadInt32();
var m_ArraySize = reader.ReadInt32();
var m_StructSize = reader.ReadInt32();
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>();
for (var i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>();
for (var i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
}
}
}
public class SamplerParameter
{
public uint sampler;
public int bindPoint;
public SamplerParameter(BinaryReader reader)
{
sampler = reader.ReadUInt32();
bindPoint = reader.ReadInt32();
}
}
public enum TextureDimension
{
Unknown = -1,
None = 0,
Any = 1,
Tex2D = 2,
Tex3D = 3,
Cube = 4,
Tex2DArray = 5,
CubeArray = 6
};
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
{
Color = 0,
Vector = 1,
Float = 2,
Range = 3,
Texture = 4,
Int = 5
};
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 List<SerializedProperty> m_Props;
public SerializedProperties(BinaryReader reader)
{
int numProps = reader.ReadInt32();
m_Props = new List<SerializedProperty>();
for (var i = 0; i < numProps; i++)
{
m_Props.Add(new SerializedProperty(reader));
}
}
}
public class SerializedShaderFloatValue
{
public float val;
public string name;
public SerializedShaderFloatValue(BinaryReader reader)
{
val = reader.ReadSingle();
name = reader.ReadAlignedString();
}
}
public class SerializedShaderRTBlendState
{
public SerializedShaderFloatValue srcBlend;
public SerializedShaderFloatValue destBlend;
public SerializedShaderFloatValue srcBlendAlpha;
public SerializedShaderFloatValue destBlendAlpha;
public SerializedShaderFloatValue blendOp;
public SerializedShaderFloatValue blendOpAlpha;
public SerializedShaderFloatValue colMask;
public SerializedShaderRTBlendState(BinaryReader reader)
{
srcBlend = new SerializedShaderFloatValue(reader);
destBlend = new SerializedShaderFloatValue(reader);
srcBlendAlpha = new SerializedShaderFloatValue(reader);
destBlendAlpha = new SerializedShaderFloatValue(reader);
blendOp = new SerializedShaderFloatValue(reader);
blendOpAlpha = new SerializedShaderFloatValue(reader);
colMask = new SerializedShaderFloatValue(reader);
}
}
public class SerializedStencilOp
{
public SerializedShaderFloatValue pass;
public SerializedShaderFloatValue fail;
public SerializedShaderFloatValue zFail;
public SerializedShaderFloatValue comp;
public SerializedStencilOp(BinaryReader reader)
{
pass = new SerializedShaderFloatValue(reader);
fail = new SerializedShaderFloatValue(reader);
zFail = new SerializedShaderFloatValue(reader);
comp = new SerializedShaderFloatValue(reader);
}
}
public class SerializedShaderVectorValue
{
public SerializedShaderFloatValue x;
public SerializedShaderFloatValue y;
public SerializedShaderFloatValue z;
public SerializedShaderFloatValue w;
public string name;
public SerializedShaderVectorValue(BinaryReader reader)
{
x = new SerializedShaderFloatValue(reader);
y = new SerializedShaderFloatValue(reader);
z = new SerializedShaderFloatValue(reader);
w = new SerializedShaderFloatValue(reader);
name = reader.ReadAlignedString();
}
}
public enum FogMode
{
Unknown = -1,
Disabled = 0,
Linear = 1,
Exp = 2,
Exp2 = 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 conservative;
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 (var i = 0; i < 8; i++)
{
rtBlend[i] = new SerializedShaderRTBlendState(reader);
}
rtSeparateBlend = reader.ReadBoolean();
reader.AlignStream();
if (version >= (2017, 2)) //2017.2 and up
{
zClip = new SerializedShaderFloatValue(reader);
}
zTest = new SerializedShaderFloatValue(reader);
zWrite = new SerializedShaderFloatValue(reader);
culling = new SerializedShaderFloatValue(reader);
if (version >= 2020) //2020.1 and up
{
conservative = 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 List<ShaderBindChannel> m_Channels;
public uint m_SourceMap;
public ParserBindChannels(BinaryReader reader)
{
int numChannels = reader.ReadInt32();
m_Channels = new List<ShaderBindChannel>();
for (var i = 0; i < numChannels; i++)
{
m_Channels.Add(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 >= (2017, 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 int m_ArraySize;
public BufferBinding(ObjectReader reader)
{
var version = reader.version;
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
if (version >= 2020) //2020.1 and up
{
m_ArraySize = reader.ReadInt32();
}
}
}
public class ConstantBuffer
{
public int m_NameIndex;
public List<MatrixParameter> m_MatrixParams;
public List<VectorParameter> m_VectorParams;
public List<StructParameter> m_StructParams;
public int m_Size;
public bool m_IsPartialCB;
public ConstantBuffer(ObjectReader reader)
{
var version = reader.version;
m_NameIndex = reader.ReadInt32();
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>();
for (var i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
}
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>();
for (var i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
}
if (version >= (2017, 3)) //2017.3 and up
{
int numStructParams = reader.ReadInt32();
m_StructParams = new List<StructParameter>();
for (var i = 0; i < numStructParams; i++)
{
m_StructParams.Add(new StructParameter(reader));
}
}
m_Size = reader.ReadInt32();
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up
|| version >= (2021, 1, 4)) //2021.1.4f1 and up
{
m_IsPartialCB = reader.ReadBoolean();
reader.AlignStream();
}
}
}
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
{
Unknown = 0,
GLLegacy = 1,
GLES31AEP = 2,
GLES31 = 3,
GLES3 = 4,
GLES = 5,
GLCore32 = 6,
GLCore41 = 7,
GLCore43 = 8,
DX9VertexSM20 = 9,
DX9VertexSM30 = 10,
DX9PixelSM20 = 11,
DX9PixelSM30 = 12,
DX10Level9Vertex = 13,
DX10Level9Pixel = 14,
DX11VertexSM40 = 15,
DX11VertexSM50 = 16,
DX11PixelSM40 = 17,
DX11PixelSM50 = 18,
DX11GeometrySM40 = 19,
DX11GeometrySM50 = 20,
DX11HullSM50 = 21,
DX11DomainSM50 = 22,
MetalVS = 23,
MetalFS = 24,
SPIRV = 25,
ConsoleVS = 26,
ConsoleFS = 27,
ConsoleHS = 28,
ConsoleDS = 29,
ConsoleGS = 30,
RayTracing = 31,
PS5NGGC = 32
};
public class SerializedProgramParameters
{
public List<VectorParameter> m_VectorParams;
public List<MatrixParameter> m_MatrixParams;
public List<TextureParameter> m_TextureParams;
public List<BufferBinding> m_BufferParams;
public List<ConstantBuffer> m_ConstantBuffers;
public List<BufferBinding> m_ConstantBufferBindings;
public List<UAVParameter> m_UAVParams;
public List<SamplerParameter> m_Samplers;
public SerializedProgramParameters(ObjectReader reader)
{
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>();
for (var i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>();
for (var i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
}
int numTextureParams = reader.ReadInt32();
m_TextureParams = new List<TextureParameter>();
for (var i = 0; i < numTextureParams; i++)
{
m_TextureParams.Add(new TextureParameter(reader));
}
int numBufferParams = reader.ReadInt32();
m_BufferParams = new List<BufferBinding>();
for (var i = 0; i < numBufferParams; i++)
{
m_BufferParams.Add(new BufferBinding(reader));
}
int numConstantBuffers = reader.ReadInt32();
m_ConstantBuffers = new List<ConstantBuffer>();
for (var i = 0; i < numConstantBuffers; i++)
{
m_ConstantBuffers.Add(new ConstantBuffer(reader));
}
int numConstantBufferBindings = reader.ReadInt32();
m_ConstantBufferBindings = new List<BufferBinding>();
for (var i = 0; i < numConstantBufferBindings; i++)
{
m_ConstantBufferBindings.Add(new BufferBinding(reader));
}
int numUAVParams = reader.ReadInt32();
m_UAVParams = new List<UAVParameter>();
for (var i = 0; i < numUAVParams; i++)
{
m_UAVParams.Add(new UAVParameter(reader));
}
if (reader.version >= 2017) //2017 and up
{
int numSamplers = reader.ReadInt32();
m_Samplers = new List<SamplerParameter>();
for (var i = 0; i < numSamplers; i++)
{
m_Samplers.Add(new SamplerParameter(reader));
}
}
}
}
public class SerializedSubProgram
{
public uint m_BlobIndex;
public ParserBindChannels m_Channels;
public ushort[] m_KeywordIndices;
public sbyte m_ShaderHardwareTier;
public ShaderGpuProgramType m_GpuProgramType;
public SerializedProgramParameters m_Parameters; // nested since 2020.3.2f1 and up; 2021.1.1f1 and up
public SerializedSubProgram(ObjectReader reader)
{
var version = reader.version;
m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader);
if (version.IsInRange(2019, (2021, 2))) //2019 ~2021.1
{
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
var m_LocalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
}
else
{
m_KeywordIndices = reader.ReadUInt16Array();
if (version >= 2017) //2017 and up
{
reader.AlignStream();
}
}
m_ShaderHardwareTier = reader.ReadSByte();
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
reader.AlignStream();
m_Parameters = new SerializedProgramParameters(reader);
if (version >= (2017, 2)) //2017.2 and up
{
if (version >= 2021) //2021.1 and up
{
var m_ShaderRequirements = reader.ReadInt64();
}
else
{
var m_ShaderRequirements = reader.ReadInt32();
}
}
}
}
public class SerializedProgram
{
public List<SerializedSubProgram> m_SubPrograms;
public SerializedProgramParameters m_CommonParameters;
public ushort[] m_SerializedKeywordStateMask;
public SerializedProgram(ObjectReader reader)
{
var version = reader.version;
int numSubPrograms = reader.ReadInt32();
m_SubPrograms = new List<SerializedSubProgram>();
for (var i = 0; i < numSubPrograms; i++)
{
m_SubPrograms.Add(new SerializedSubProgram(reader));
}
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up
|| version >= (2021, 1, 1)) //2021.1.1f1 and up
{
m_CommonParameters = new SerializedProgramParameters(reader);
}
if (version >= (2022, 1)) //2022.1 and up
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
}
public enum PassType
{
Normal = 0,
Use = 1,
Grab = 2
};
public class SerializedPass
{
public List<Hash128> m_EditorDataHash;
public byte[] m_Platforms;
public ushort[] m_LocalKeywordMask;
public ushort[] m_GlobalKeywordMask;
public List<KeyValuePair<string, int>> m_NameIndices;
public PassType m_Type;
public SerializedShaderState m_State;
public uint m_ProgramMask;
public SerializedProgram progVertex;
public SerializedProgram progFragment;
public SerializedProgram progGeometry;
public SerializedProgram progHull;
public SerializedProgram progDomain;
public SerializedProgram progRayTracing;
public bool m_HasInstancingVariant;
public string m_UseName;
public string m_Name;
public string m_TextureName;
public SerializedTagMap m_Tags;
public ushort[] m_SerializedKeywordStateMask;
public SerializedPass(ObjectReader reader)
{
var version = reader.version;
if (version >= (2020, 2)) //2020.2 and up
{
int numEditorDataHash = reader.ReadInt32();
m_EditorDataHash = new List<Hash128>();
for (var i = 0; i < numEditorDataHash; i++)
{
m_EditorDataHash.Add(new Hash128(reader));
}
reader.AlignStream();
m_Platforms = reader.ReadUInt8Array();
reader.AlignStream();
if (version <= (2021, 1)) //2021.1 and down
{
m_LocalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
m_GlobalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
int numIndices = reader.ReadInt32();
m_NameIndices = new List<KeyValuePair<string, int>>();
for (var i = 0; i < numIndices; i++)
{
m_NameIndices.Add(new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32()));
}
m_Type = (PassType)reader.ReadInt32();
m_State = new SerializedShaderState(reader);
m_ProgramMask = reader.ReadUInt32();
progVertex = new SerializedProgram(reader);
progFragment = new SerializedProgram(reader);
progGeometry = new SerializedProgram(reader);
progHull = new SerializedProgram(reader);
progDomain = new SerializedProgram(reader);
if (version >= (2019, 3)) //2019.3 and up
{
progRayTracing = new SerializedProgram(reader);
}
m_HasInstancingVariant = reader.ReadBoolean();
if (version >= 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);
if (version == 2021 && version.Minor >= 2) //2021.2 ~2021.x
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
}
public class SerializedTagMap
{
public List<KeyValuePair<string, string>> tags;
public SerializedTagMap(BinaryReader reader)
{
int numTags = reader.ReadInt32();
tags = new List<KeyValuePair<string, string>>();
for (var i = 0; i < numTags; i++)
{
tags.Add(new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString()));
}
}
}
public class SerializedSubShader
{
public List<SerializedPass> m_Passes;
public SerializedTagMap m_Tags;
public int m_LOD;
public SerializedSubShader(ObjectReader reader)
{
int numPasses = reader.ReadInt32();
m_Passes = new List<SerializedPass>();
for (var i = 0; i < numPasses; i++)
{
m_Passes.Add(new SerializedPass(reader));
}
m_Tags = new SerializedTagMap(reader);
m_LOD = reader.ReadInt32();
}
}
public class SerializedShaderDependency
{
public string from;
public string to;
public SerializedShaderDependency(BinaryReader reader)
{
from = reader.ReadAlignedString();
to = reader.ReadAlignedString();
}
}
public class SerializedCustomEditorForRenderPipeline
{
public string customEditorName;
public string renderPipelineType;
public SerializedCustomEditorForRenderPipeline(BinaryReader reader)
{
customEditorName = reader.ReadAlignedString();
renderPipelineType = reader.ReadAlignedString();
}
}
public class SerializedShader
{
public SerializedProperties m_PropInfo;
public List<SerializedSubShader> m_SubShaders;
public string[] m_KeywordNames;
public byte[] m_KeywordFlags;
public string m_Name;
public string m_CustomEditorName;
public string m_FallbackName;
public List<SerializedShaderDependency> m_Dependencies;
public List<SerializedCustomEditorForRenderPipeline> m_CustomEditorForRenderPipelines;
public bool m_DisableNoSubshadersMessage;
public SerializedShader(ObjectReader reader)
{
var version = reader.version;
m_PropInfo = new SerializedProperties(reader);
int numSubShaders = reader.ReadInt32();
m_SubShaders = new List<SerializedSubShader>();
for (var i = 0; i < numSubShaders; i++)
{
m_SubShaders.Add(new SerializedSubShader(reader));
}
if (version >= (2021, 2)) //2021.2 and up
{
m_KeywordNames = reader.ReadStringArray();
m_KeywordFlags = reader.ReadUInt8Array();
reader.AlignStream();
}
m_Name = reader.ReadAlignedString();
m_CustomEditorName = reader.ReadAlignedString();
m_FallbackName = reader.ReadAlignedString();
int numDependencies = reader.ReadInt32();
m_Dependencies = new List<SerializedShaderDependency>();
for (var i = 0; i < numDependencies; i++)
{
m_Dependencies.Add(new SerializedShaderDependency(reader));
}
if (version >= 2021) //2021.1 and up
{
int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32();
m_CustomEditorForRenderPipelines = new List<SerializedCustomEditorForRenderPipeline>();
for (var i = 0; i < m_CustomEditorForRenderPipelinesSize; i++)
{
m_CustomEditorForRenderPipelines.Add(new SerializedCustomEditorForRenderPipeline(reader));
}
}
m_DisableNoSubshadersMessage = reader.ReadBoolean();
reader.AlignStream();
}
}
public enum ShaderCompilerPlatform
{
None = -1,
GL = 0,
D3D9 = 1,
Xbox360 = 2,
PS3 = 3,
D3D11 = 4,
GLES20 = 5,
NaCl = 6,
Flash = 7,
D3D11_9x = 8,
GLES3Plus = 9,
PSP2 = 10,
PS4 = 11,
XboxOne = 12,
PSM = 13,
Metal = 14,
OpenGLCore = 15,
N3DS = 16,
WiiU = 17,
Vulkan = 18,
Switch = 19,
XboxOneD3D12 = 20,
GameCoreXboxOne = 21,
GameCoreScarlett = 22,
PS5 = 23,
PS5NGGC = 24
};
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 >= (5, 5)) //5.5 and up
{
m_ParsedForm = new SerializedShader(reader);
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
if (version >= (2019, 3)) //2019.3 and up
{
offsets = reader.ReadUInt32ArrayArray();
compressedLengths = reader.ReadUInt32ArrayArray();
decompressedLengths = reader.ReadUInt32ArrayArray();
}
else
{
offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
}
compressedBlob = reader.ReadUInt8Array();
reader.AlignStream();
var m_DependenciesCount = reader.ReadInt32();
for (var i = 0; i < m_DependenciesCount; i++)
{
var m_Dependencies = new PPtr<Shader>(reader);
}
if (version >= 2018)
{
var m_NonModifiableTexturesCount = reader.ReadInt32();
for (var i = 0; i < m_NonModifiableTexturesCount; i++)
{
var first = reader.ReadAlignedString();
var second = new PPtr<Texture>(reader);
}
}
var m_ShaderIsBaked = reader.ReadBoolean();
reader.AlignStream();
}
else
{
m_Script = reader.ReadUInt8Array();
reader.AlignStream();
var m_PathName = reader.ReadAlignedString();
if (version == 5 && version.Minor >= 3) //5.3 - 5.4
{
decompressedSize = reader.ReadUInt32();
m_SubProgramBlob = reader.ReadUInt8Array();
}
}
}
}
}

View File

@@ -0,0 +1,38 @@
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class SkinnedMeshRenderer : Renderer
{
public PPtr<Mesh> m_Mesh;
public List<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 < (2, 6)) //2.6 down
{
var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);
}
m_Mesh = new PPtr<Mesh>(reader);
var numBones = reader.ReadInt32();
m_Bones = new List<PPtr<Transform>>();
for (var b = 0; b < numBones; b++)
{
m_Bones.Add(new PPtr<Transform>(reader));
}
if (version >= (4, 3)) //4.3 and up
{
m_BlendShapeWeights = reader.ReadSingleArray();
}
}
}
}

View File

@@ -0,0 +1,258 @@
using System;
using System.Collections.Generic;
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.ReadAlignedString();
}
}
public enum SpritePackingRotation
{
None = 0,
FlipHorizontal = 1,
FlipVertical = 2,
Rotate180 = 3,
Rotate90 = 4
};
public enum SpritePackingMode
{
Tight = 0,
Rectangle
};
public enum SpriteMeshType
{
FullRect,
Tight
};
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 <= (4, 3)) //4.3 and down
{
uv = reader.ReadVector2();
}
}
}
public class SpriteRenderData
{
public PPtr<Texture2D> texture;
public PPtr<Texture2D> alphaTexture;
public List<SecondarySpriteTexture> secondaryTextures;
public List<SubMesh> m_SubMeshes;
public byte[] m_IndexBuffer;
public VertexData m_VertexData;
public List<SpriteVertex> vertices;
public ushort[] indices;
public Matrix4x4[] m_Bindpose;
public BoneWeights4[] m_SourceSkin;
public Rectf 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);
alphaTexture = version >= (5, 2) ? new PPtr<Texture2D>(reader) : new PPtr<Texture2D>(); //5.2 and up
if (version >= 2019) //2019 and up
{
var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new List<SecondarySpriteTexture>();
for (var i = 0; i < secondaryTexturesSize; i++)
{
secondaryTextures.Add(new SecondarySpriteTexture(reader));
}
}
if (version >= (5, 6)) //5.6 and up
{
var m_SubMeshesSize = reader.ReadInt32();
m_SubMeshes = new List<SubMesh>();
for (var i = 0; i < m_SubMeshesSize; i++)
{
m_SubMeshes.Add(new SubMesh(reader));
}
m_IndexBuffer = reader.ReadUInt8Array();
reader.AlignStream();
m_VertexData = new VertexData(reader);
}
else
{
var verticesSize = reader.ReadInt32();
vertices = new List<SpriteVertex>();
for (var i = 0; i < verticesSize; i++)
{
vertices.Add(new SpriteVertex(reader));
}
indices = reader.ReadUInt16Array();
reader.AlignStream();
}
if (version >= 2018) //2018 and up
{
m_Bindpose = reader.ReadMatrixArray();
if (version < (2018, 2)) //2018.2 down
{
var m_SourceSkinSize = reader.ReadInt32();
reader.ThrowIfTooLarge(m_SourceSkinSize * 32f);
m_SourceSkin = new BoneWeights4[m_SourceSkinSize];
for (var i = 0; i < m_SourceSkinSize; i++)
{
m_SourceSkin[i] = new BoneWeights4(reader);
}
}
}
textureRect = new Rectf(reader);
textureRectOffset = reader.ReadVector2();
if (version >= (5, 6)) //5.6 and up
{
atlasRectOffset = reader.ReadVector2();
}
settingsRaw = new SpriteSettings(reader);
if (version >= (4, 5)) //4.5 and up
{
uvTransform = reader.ReadVector4();
}
if (version >= 2017) //2017 and up
{
downscaleMultiplier = reader.ReadSingle();
}
}
}
public class Rectf
{
public float x;
public float y;
public float width;
public float height;
public Rectf(BinaryReader reader)
{
x = reader.ReadSingle();
y = reader.ReadSingle();
width = reader.ReadSingle();
height = reader.ReadSingle();
}
}
public sealed class Sprite : NamedObject
{
public Rectf m_Rect;
public Vector2 m_Offset;
public Vector4 m_Border;
public float m_PixelsToUnits;
public Vector2 m_Pivot = new Vector2(0.5f, 0.5f);
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 = new Rectf(reader);
m_Offset = reader.ReadVector2();
if (version >= (4, 5)) //4.5 and up
{
m_Border = reader.ReadVector4();
}
m_PixelsToUnits = reader.ReadSingle();
if (version >= (5, 4, 2)
|| version == (5, 4, 1) && version.IsPatch && version.Build >= 3) //5.4.1p3 and up
{
m_Pivot = reader.ReadVector2();
}
m_Extrude = reader.ReadUInt32();
if (version >= (5, 3)) //5.3 and up
{
m_IsPolygon = reader.ReadBoolean();
reader.AlignStream();
}
if (version >= 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 >= 2017) //2017 and up
{
var m_PhysicsShapeSize = reader.ReadInt32();
var physicsShapeList = new List<Vector2[]>();
for (var i = 0; i < m_PhysicsShapeSize; i++)
{
physicsShapeList.Add(reader.ReadVector2Array());
}
m_PhysicsShape = physicsShapeList.ToArray();
}
*/
//vector m_Bones 2018 and up
}
}
}

View File

@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public class SpriteAtlasData
{
public PPtr<Texture2D> texture;
public PPtr<Texture2D> alphaTexture;
public Rectf textureRect;
public Vector2 textureRectOffset;
public Vector2 atlasRectOffset;
public Vector4 uvTransform;
public float downscaleMultiplier;
public SpriteSettings settingsRaw;
public List<SecondarySpriteTexture> secondaryTextures;
public SpriteAtlasData(ObjectReader reader)
{
var version = reader.version;
texture = new PPtr<Texture2D>(reader);
alphaTexture = new PPtr<Texture2D>(reader);
textureRect = new Rectf(reader);
textureRectOffset = reader.ReadVector2();
if (version >= (2017, 2)) //2017.2 and up
{
atlasRectOffset = reader.ReadVector2();
}
uvTransform = reader.ReadVector4();
downscaleMultiplier = reader.ReadSingle();
settingsRaw = new SpriteSettings(reader);
if (version >= (2020, 2)) //2020.2 and up
{
var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new List<SecondarySpriteTexture>();
for (var i = 0; i < secondaryTexturesSize; i++)
{
secondaryTextures.Add(new SecondarySpriteTexture(reader));
}
reader.AlignStream();
}
}
}
public sealed class SpriteAtlas : NamedObject
{
public List<PPtr<Sprite>> m_PackedSprites;
[JsonConverter(typeof(JsonConverterHelper.RenderDataMapConverter))]
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
public bool m_IsVariant;
public SpriteAtlas(ObjectReader reader) : base(reader)
{
var m_PackedSpritesSize = reader.ReadInt32();
m_PackedSprites = new List<PPtr<Sprite>>();
for (var i = 0; i < m_PackedSpritesSize; i++)
{
m_PackedSprites.Add(new PPtr<Sprite>(reader));
}
var m_PackedSpriteNamesToIndex = reader.ReadStringArray();
var m_RenderDataMapSize = reader.ReadInt32();
m_RenderDataMap = new Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData>();
for (var 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);
}
var m_Tag = reader.ReadAlignedString();
m_IsVariant = reader.ReadBoolean();
reader.AlignStream();
}
}
}

View File

@@ -0,0 +1,27 @@
namespace AssetStudio
{
public class StreamingInfo
{
public long offset; //ulong
public uint size;
public string path;
public StreamingInfo() { }
public StreamingInfo(ObjectReader reader)
{
var version = reader.version;
if (version >= 2020) //2020.1 and up
{
offset = reader.ReadInt64();
}
else
{
offset = reader.ReadUInt32();
}
size = reader.ReadUInt32();
path = reader.ReadAlignedString();
}
}
}

View File

@@ -0,0 +1,12 @@
namespace AssetStudio
{
public sealed class TextAsset : NamedObject
{
public byte[] m_Script;
public TextAsset(ObjectReader reader) : base(reader)
{
m_Script = reader.ReadUInt8Array();
}
}
}

View File

@@ -0,0 +1,25 @@
namespace AssetStudio
{
public abstract class Texture : NamedObject
{
protected Texture() { }
protected Texture(ObjectReader reader) : base(reader)
{
if (version >= (2017, 3)) //2017.3 and up
{
if (version < (2023, 2)) //2023.2 down
{
var m_ForcedFallbackFormat = reader.ReadInt32();
var m_DownscaleFallback = reader.ReadBoolean();
}
if (version >= (2020, 2)) //2020.2 and up
{
var m_IsAlphaChannelOptional = reader.ReadBoolean();
}
reader.AlignStream();
}
}
}
}

View File

@@ -0,0 +1,242 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public sealed class Texture2D : Texture
{
public int m_Width;
public int m_Height;
public uint m_CompleteImageSize;
public TextureFormat m_TextureFormat;
public bool m_MipMap;
public int m_MipCount;
public GLTextureSettings m_TextureSettings;
public int m_ImageCount;
public byte[] m_PlatformBlob;
[JsonPropertyName("image data")]
public ResourceReader image_data;
public StreamingInfo m_StreamData;
public StreamingInfo m_DataStreamData; //Tuanjie
public Texture2D() { }
public Texture2D(Texture2DArray m_Texture2DArray, int layer) // Texture2DArrayImage
{
reader = m_Texture2DArray.reader;
assetsFile = m_Texture2DArray.assetsFile;
version = m_Texture2DArray.version;
platform = m_Texture2DArray.platform;
m_Name = $"{m_Texture2DArray.m_Name}_{layer + 1}";
type = ClassIDType.Texture2DArrayImage;
m_PathID = m_Texture2DArray.m_PathID;
m_Width = m_Texture2DArray.m_Width;
m_Height = m_Texture2DArray.m_Height;
m_TextureFormat = m_Texture2DArray.m_Format.ToTextureFormat();
m_MipCount = m_Texture2DArray.m_MipCount;
m_TextureSettings = m_Texture2DArray.m_TextureSettings;
m_StreamData = m_Texture2DArray.m_StreamData;
m_PlatformBlob = Array.Empty<byte>();
m_MipMap = m_MipCount > 1;
m_ImageCount = 1;
//var imgActualDataSize = GetImageDataSize(m_TextureFormat);
//var mipmapSize = (int)(m_Texture2DArray.m_DataSize / m_Texture2DArray.m_Depth - imgActualDataSize);
m_CompleteImageSize = (uint)(m_Texture2DArray.m_DataSize / m_Texture2DArray.m_Depth);
var offset = layer * m_CompleteImageSize + m_Texture2DArray.image_data.Offset;
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, offset, m_CompleteImageSize)
: new ResourceReader(reader, offset, m_CompleteImageSize);
byteSize = (uint)(m_Width * m_Height) * 4;
}
public Texture2D(ObjectReader reader, byte[] type, JsonSerializerOptions jsonOptions) : base(reader)
{
var parsedTex2d = JsonSerializer.Deserialize<Texture2D>(type, jsonOptions);
m_Width = parsedTex2d.m_Width;
m_Height = parsedTex2d.m_Height;
m_CompleteImageSize = parsedTex2d.m_CompleteImageSize;
m_TextureFormat = parsedTex2d.m_TextureFormat;
m_MipMap = parsedTex2d.m_MipMap;
m_MipCount = parsedTex2d.m_MipCount;
m_ImageCount = parsedTex2d.m_ImageCount;
m_TextureSettings = parsedTex2d.m_TextureSettings;
m_StreamData = parsedTex2d.m_StreamData;
m_PlatformBlob = parsedTex2d.m_PlatformBlob ?? Array.Empty<byte>();
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, parsedTex2d.image_data.Offset, parsedTex2d.image_data.Size);
}
public Texture2D(ObjectReader reader) : base(reader)
{
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
m_CompleteImageSize = reader.ReadUInt32();
if (version >= 2020) //2020.1 and up
{
var m_MipsStripped = reader.ReadInt32();
}
if (version.IsTuanjie && (version > (2022, 3, 2) || version.Build >= 8)) //2022.3.2t8(1.1.0) and up
{
var m_WebStreaming = reader.ReadBoolean();
reader.AlignStream();
var m_PriorityLevel = reader.ReadInt32();
var m_UploadedMode = reader.ReadInt32();
m_DataStreamData = new StreamingInfo //sample is needed
{
offset = 0,
size = reader.ReadUInt32(),
path = reader.ReadAlignedString()
};
}
m_TextureFormat = (TextureFormat)reader.ReadInt32();
if (version.IsTuanjie && version >= (2022, 3, 62)) //2022.3.62t1(1.7.0) and up
{
var m_TextureManagerMultiFormatSettingSize = reader.ReadInt32();
reader.Position += m_TextureManagerMultiFormatSettingSize; //skip byte[] m_TextureManagerMultiFormatSetting
reader.AlignStream();
}
if (version < (5, 2)) //5.2 down
{
m_MipMap = reader.ReadBoolean();
}
else
{
m_MipCount = reader.ReadInt32();
}
if (version >= (2, 6)) //2.6.0 and up
{
var m_IsReadable = reader.ReadBoolean();
}
if (version >= 2020) //2020.1 and up
{
var m_IsPreProcessed = reader.ReadBoolean();
}
if (version >= (2019, 3)) //2019.3 and up
{
if (version >= (2022, 2)) //2022.2 and up
{
var m_IgnoreMipmapLimit = reader.ReadBoolean();
reader.AlignStream();
}
else
{
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
}
}
if (version.IsInRange(3, (5, 5))) //3.0.0 - 5.4
{
var m_ReadAllowed = reader.ReadBoolean();
}
if (version >= (2022, 2)) //2022.2 and up
{
var m_MipmapLimitGroupName = reader.ReadAlignedString();
}
if (version >= (2018, 2)) //2018.2 and up
{
var m_StreamingMipmaps = reader.ReadBoolean();
}
reader.AlignStream();
if (version >= (2018, 2)) //2018.2 and up
{
var m_StreamingMipmapsPriority = reader.ReadInt32();
}
m_ImageCount = reader.ReadInt32();
var m_TextureDimension = reader.ReadInt32();
m_TextureSettings = new GLTextureSettings(reader);
if (version >= 3) //3.0 and up
{
var m_LightmapFormat = reader.ReadInt32();
}
if (version >= (3, 5)) //3.5.0 and up
{
var m_ColorSpace = reader.ReadInt32();
}
if (version >= (2020, 2)) //2020.2 and up
{
m_PlatformBlob = reader.ReadUInt8Array();
reader.AlignStream();
}
else
{
m_PlatformBlob = Array.Empty<byte>();
}
var image_data_size = reader.ReadInt32();
if (image_data_size == 0 && version >= (5, 3))//5.3.0 and up
{
m_StreamData = new StreamingInfo(reader);
}
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
}
// https://docs.unity3d.com/2023.3/Documentation/Manual/class-TextureImporterOverride.html
private int GetImageDataSize(TextureFormat textureFormat)
{
var imgDataSize = m_Width * m_Height;
switch (textureFormat)
{
case TextureFormat.ASTC_RGBA_5x5:
// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/
imgDataSize = (int)(MathF.Floor((m_Width + 4) / 5f) * MathF.Floor((m_Height + 4) / 5f) * 16);
break;
case TextureFormat.ASTC_RGBA_6x6:
imgDataSize = (int)(MathF.Floor((m_Width + 5) / 6f) * MathF.Floor((m_Height + 5) / 6f) * 16);
break;
case TextureFormat.ASTC_RGBA_8x8:
imgDataSize = (int)(MathF.Floor((m_Width + 7) / 8f) * MathF.Floor((m_Height + 7) / 8f) * 16);
break;
case TextureFormat.ASTC_RGBA_10x10:
imgDataSize = (int)(MathF.Floor((m_Width + 9) / 10f) * MathF.Floor((m_Height + 9) / 10f) * 16);
break;
case TextureFormat.ASTC_RGBA_12x12:
imgDataSize = (int)(MathF.Floor((m_Width + 11) / 12f) * MathF.Floor((m_Height + 11) / 12f) * 16);
break;
case TextureFormat.DXT1:
case TextureFormat.EAC_R:
case TextureFormat.EAC_R_SIGNED:
case TextureFormat.ATC_RGB4:
case TextureFormat.ETC_RGB4:
case TextureFormat.ETC2_RGB:
case TextureFormat.ETC2_RGBA1:
case TextureFormat.PVRTC_RGBA4:
imgDataSize /= 2;
break;
case TextureFormat.PVRTC_RGBA2:
imgDataSize /= 4;
break;
case TextureFormat.R16:
case TextureFormat.RGB565:
imgDataSize *= 2;
break;
case TextureFormat.RGB24:
imgDataSize *= 3;
break;
case TextureFormat.RG32:
case TextureFormat.RGBA32:
case TextureFormat.ARGB32:
case TextureFormat.BGRA32:
case TextureFormat.RGB9e5Float:
imgDataSize *= 4;
break;
case TextureFormat.RGB48:
imgDataSize *= 6;
break;
case TextureFormat.RGBAHalf:
case TextureFormat.RGBA64:
imgDataSize *= 8;
break;
}
return imgDataSize;
}
}
}

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public sealed class Texture2DArray : Texture
{
public int m_Width;
public int m_Height;
public int m_Depth;
public GraphicsFormat m_Format;
public int m_MipCount;
public uint m_DataSize;
public GLTextureSettings m_TextureSettings;
public int m_ColorSpace;
[JsonPropertyName("image data")]
public ResourceReader image_data;
public StreamingInfo m_StreamData;
public List<Texture2D> TextureList;
public Texture2DArray() { }
public Texture2DArray(ObjectReader reader) : base(reader)
{
if (version >= 2019) //2019 and up
{
m_ColorSpace = reader.ReadInt32();
m_Format = (GraphicsFormat)reader.ReadInt32();
}
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
m_Depth = reader.ReadInt32();
if (version < 2019) //2019 down
{
m_Format = (GraphicsFormat)reader.ReadInt32();
}
m_MipCount = reader.ReadInt32();
if (version >= (2023, 2)) //2023.2 and up
{
var m_MipsStripped = reader.ReadInt32();
}
m_DataSize = reader.ReadUInt32();
m_TextureSettings = new GLTextureSettings(reader);
if (version < 2019) //2019 down
{
m_ColorSpace = reader.ReadInt32();
}
if (version >= (2020, 2)) //2020.2 and up
{
var m_UsageMode = reader.ReadInt32();
}
var m_IsReadable = reader.ReadBoolean();
if (version > (2023, 2)) //2023.2 and up
{
var m_IgnoreMipmapLimit = reader.ReadBoolean();
reader.AlignStream();
var m_MipmapLimitGroupName = reader.ReadAlignedString();
}
else
{
reader.AlignStream();
}
var image_data_size = reader.ReadInt32();
if (image_data_size == 0 && version >= (5, 6)) //5.6 and up
{
m_StreamData = new StreamingInfo(reader);
}
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, (int)m_StreamData.size)
: new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
TextureList = new List<Texture2D>();
}
public Texture2DArray(ObjectReader reader, byte[] type, JsonSerializerOptions jsonOptions) : base(reader)
{
var parsedTex2dArray = JsonSerializer.Deserialize<Texture2DArray>(type, jsonOptions);
m_Width = parsedTex2dArray.m_Width;
m_Height = parsedTex2dArray.m_Height;
m_Depth = parsedTex2dArray.m_Depth;
m_Format = parsedTex2dArray.m_Format;
m_MipCount = parsedTex2dArray.m_MipCount;
m_DataSize = parsedTex2dArray.m_DataSize;
m_TextureSettings = parsedTex2dArray.m_TextureSettings;
m_StreamData = parsedTex2dArray.m_StreamData;
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, parsedTex2dArray.image_data.Offset, parsedTex2dArray.image_data.Size);
TextureList = new List<Texture2D>();
}
}
}

View File

@@ -0,0 +1,282 @@
namespace AssetStudio
{
public enum TextureFormat
{
/// <summary>
/// Alpha-only texture format, 8 bit integer.
/// </summary>
Alpha8 = 1,
/// <summary>
/// A 16 bits/pixel texture format. Texture stores color with an alpha channel.
/// </summary>
ARGB4444,
/// <summary>
/// Three channel (RGB) texture format, 8-bits unsigned integer per channel.
/// </summary>
RGB24,
/// <summary>
/// Four channel (RGBA) texture format, 8-bits unsigned integer per channel.
/// </summary>
RGBA32,
/// <summary>
/// Color with alpha texture format, 8-bits per channel.
/// </summary>
ARGB32,
/// <summary>
/// </summary>
ARGBFloat,
/// <summary>
/// A 16 bit color texture format.
/// </summary>
RGB565,
/// <summary>
/// </summary>
BGR24,
/// <summary>
/// Single channel (R) texture format, 16 bit integer.
/// </summary>
R16,
/// <summary>
/// Compressed color texture format.
/// </summary>
DXT1,
/// <summary>
/// </summary>
DXT3,
/// <summary>
/// Compressed color with alpha channel texture format.
/// </summary>
DXT5,
/// <summary>
/// Color and alpha texture format, 4 bit per channel.
/// </summary>
RGBA4444,
/// <summary>
/// Color with alpha texture format, 8-bits per channel.
/// </summary>
BGRA32,
/// <summary>
/// Scalar (R) texture format, 16 bit floating point.
/// </summary>
RHalf,
/// <summary>
/// Two color (RG) texture format, 16 bit floating point per channel.
/// </summary>
RGHalf,
/// <summary>
/// RGB color and alpha texture format, 16 bit floating point per channel.
/// </summary>
RGBAHalf,
/// <summary>
/// Scalar (R) texture format, 32 bit floating point.
/// </summary>
RFloat,
/// <summary>
/// Two color (RG) texture format, 32 bit floating point per channel.
/// </summary>
RGFloat,
/// <summary>
/// RGB color and alpha texture format, 32-bit floats per channel.
/// </summary>
RGBAFloat,
/// <summary>
/// A format that uses the YUV color space and is often used for video encoding or playback.
/// </summary>
YUY2,
/// <summary>
/// RGB HDR format, with 9 bit mantissa per channel and a 5 bit shared exponent.
/// </summary>
RGB9e5Float,
/// <summary>
/// </summary>
RGBFloat,
/// <summary>
/// HDR compressed color texture format.
/// </summary>
BC6H,
/// <summary>
/// High quality compressed color texture format.
/// </summary>
BC7,
/// <summary>
/// Compressed one channel (R) texture format.
/// </summary>
BC4,
/// <summary>
/// Compressed two-channel (RG) texture format.
/// </summary>
BC5,
/// <summary>
/// Compressed color texture format with Crunch compression for smaller storage sizes.
/// </summary>
DXT1Crunched,
/// <summary>
/// Compressed color with alpha channel texture format with Crunch compression for smaller storage sizes.
/// </summary>
DXT5Crunched,
/// <summary>
/// PowerVR (iOS) 2 bits/pixel compressed color texture format.
/// </summary>
PVRTC_RGB2,
/// <summary>
/// PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format.
/// </summary>
PVRTC_RGBA2,
/// <summary>
/// PowerVR (iOS) 4 bits/pixel compressed color texture format.
/// </summary>
PVRTC_RGB4,
/// <summary>
/// PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format.
/// </summary>
PVRTC_RGBA4,
/// <summary>
/// ETC (GLES2.0) 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC_RGB4,
/// <summary>
/// ATC (ATITC) 4 bits/pixel compressed RGB texture format.
/// </summary>
ATC_RGB4,
/// <summary>
/// ATC (ATITC) 8 bits/pixel compressed RGB texture format.
/// </summary>
ATC_RGBA8,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 4 bits/pixel compressed unsigned single-channel texture format.
/// </summary>
EAC_R = 41,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 4 bits/pixel compressed signed single-channel texture format.
/// </summary>
EAC_R_SIGNED,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 8 bits/pixel compressed unsigned dual-channel (RG) texture format.
/// </summary>
EAC_RG,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 8 bits/pixel compressed signed dual-channel (RG) texture format.
/// </summary>
EAC_RG_SIGNED,
/// <summary>
/// ETC2 (GL ES 3.0) 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC2_RGB,
/// <summary>
/// ETC2 (GL ES 3.0) 4 bits/pixel RGB+1-bit alpha texture format.
/// </summary>
ETC2_RGBA1,
/// <summary>
/// ETC2 (GL ES 3.0) 8 bits/pixel compressed RGBA texture format.
/// </summary>
ETC2_RGBA8,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_12x12,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_12x12,
/// <summary>
/// ETC 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC_RGB4_3DS,
/// <summary>
/// ETC 4 bits/pixel RGB + 4 bits/pixel Alpha compressed texture format.
/// </summary>
ETC_RGBA8_3DS,
/// <summary>
/// Two color (RG) texture format, 8-bits per channel.
/// </summary>
RG16,
/// <summary>
/// Single channel (R) texture format, 8 bit integer.
/// </summary>
R8,
/// <summary>
/// Compressed color texture format with Crunch compression for smaller storage sizes.
/// </summary>
ETC_RGB4Crunched,
/// <summary>
/// Compressed color with alpha channel texture format using Crunch compression for smaller storage sizes.
/// </summary>
ETC2_RGBA8Crunched,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGB(A) texture format.
/// </summary>
ASTC_HDR_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_12x12,
/// <summary>
/// Two channel (RG) texture format, 16-bits unsigned integer per channel.
/// </summary>
RG32,
/// <summary>
/// Three channel (RGB) texture format, 16-bits unsigned integer per channel.
/// </summary>
RGB48,
/// <summary>
/// Four channel (RGBA) texture format, 16-bits unsigned integer per channel.
/// </summary>
RGBA64,
}
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
namespace AssetStudio
{
public class Transform : Component
{
public Quaternion m_LocalRotation;
public Vector3 m_LocalPosition;
public Vector3 m_LocalScale;
public List<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 List<PPtr<Transform>>();
for (var i = 0; i < m_ChildrenCount; i++)
{
m_Children.Add(new PPtr<Transform>(reader));
}
m_Father = new PPtr<Transform>(reader);
}
}
}

View File

@@ -0,0 +1,76 @@
using System.IO;
namespace AssetStudio
{
public class StreamedResource
{
public string m_Source;
public long m_Offset; //ulong
public long m_Size; //ulong
public StreamedResource(BinaryReader reader)
{
m_Source = reader.ReadAlignedString();
m_Offset = reader.ReadInt64();
m_Size = reader.ReadInt64();
}
}
public sealed class VideoClip : NamedObject
{
public ResourceReader m_VideoData;
public string m_OriginalPath;
public StreamedResource m_ExternalResources;
public uint Width;
public uint Height;
public double m_FrameRate;
public int m_Format;
public bool m_HasSplitAlpha;
public VideoClip(ObjectReader reader) : base(reader)
{
m_OriginalPath = reader.ReadAlignedString();
var m_ProxyWidth = reader.ReadUInt32();
var m_ProxyHeight = reader.ReadUInt32();
Width = reader.ReadUInt32();
Height = reader.ReadUInt32();
if (version >= (2017, 2)) //2017.2 and up
{
var m_PixelAspecRatioNum = reader.ReadUInt32();
var m_PixelAspecRatioDen = reader.ReadUInt32();
}
m_FrameRate = reader.ReadDouble();
var m_FrameCount = reader.ReadUInt64();
m_Format = reader.ReadInt32();
var m_AudioChannelCount = reader.ReadUInt16Array();
reader.AlignStream();
var m_AudioSampleRate = reader.ReadUInt32Array();
var m_AudioLanguage = reader.ReadStringArray();
if (version >= 2020) //2020.1 and up
{
var m_VideoShadersSize = reader.ReadInt32();
for (var i = 0; i < m_VideoShadersSize; i++)
{
var m_VideoShaders = new PPtr<Shader>(reader);
}
}
m_ExternalResources = new StreamedResource(reader);
m_HasSplitAlpha = reader.ReadBoolean();
if (version >= 2020) //2020.1 and up
{
var m_sRGB = reader.ReadBoolean();
}
ResourceReader resourceReader;
if (!string.IsNullOrEmpty(m_ExternalResources.m_Source))
{
resourceReader = new ResourceReader(m_ExternalResources.m_Source, assetsFile, m_ExternalResources.m_Offset, m_ExternalResources.m_Size);
}
else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_ExternalResources.m_Size);
}
m_VideoData = resourceReader;
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
namespace AssetStudio
{
// Represents set with 16 base colors using ANSI escape codes, which should be supported in most terminals
// (well, except for windows editions before windows 10)
public static class ColorConsole
{
public static readonly string
Black = "\u001b[30m",
Red = "\u001b[31m",
Green = "\u001b[32m",
Yellow = "\u001b[33m", //remapped to ~BrightWhite in Windows PowerShell 6
Blue = "\u001b[34m",
Magenta = "\u001b[35m", //remapped to ~Blue in Windows PowerShell 6
Cyan = "\u001b[36m",
White = "\u001b[37m",
BrightBlack = "\u001b[30;1m",
BrightRed = "\u001b[31;1m",
BrightGreen = "\u001b[32;1m",
BrightYellow = "\u001b[33;1m",
BrightBlue = "\u001b[34;1m",
BrightMagenta = "\u001b[35;1m",
BrightCyan = "\u001b[36;1m",
BrightWhite = "\u001b[37;1m";
private static readonly string Reset = "\u001b[0m";
public static string Color(this string str, string ansiColor)
{
if (!ColorConsoleHelper.isAnsiCodesSupported)
return str;
return $"{ansiColor}{str}{Reset}";
}
public static string ColorIf(this string str, bool isTrue, string ansiColor, string defaultAnsiColor = null)
{
if (isTrue)
return str.Color(ansiColor);
if (defaultAnsiColor != null)
return str.Color(defaultAnsiColor);
return str;
}
public static void AnsiCodesTest()
{
Console.WriteLine("ANSI escape codes test");
Console.WriteLine($"Supported: {ColorConsoleHelper.isAnsiCodesSupported}");
Console.WriteLine("\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m");
Console.WriteLine("\u001b[34m E \u001b[35m F \u001b[36m G \u001b[37m H \u001b[0m");
Console.WriteLine("\u001b[30;1m A \u001b[31;1m B \u001b[32;1m C \u001b[33;1m D \u001b[0m");
Console.WriteLine("\u001b[34;1m E \u001b[35;1m F \u001b[36;1m G \u001b[37;1m H \u001b[0m");
}
}
}

View File

@@ -0,0 +1,57 @@
// Based on code by tomzorz (https://gist.github.com/tomzorz/6142d69852f831fb5393654c90a1f22e)
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
internal static class ColorConsoleHelper
{
public static readonly bool isAnsiCodesSupported;
private const int STD_OUTPUT_HANDLE = -11;
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
[DllImport("kernel32.dll")]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll")]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(int nStdHandle);
static ColorConsoleHelper()
{
var isWin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
if (isWin)
{
isAnsiCodesSupported = TryEnableVTMode();
if (!isAnsiCodesSupported)
{
//Check for bash terminal emulator. E.g., Git Bash, Cmder
isAnsiCodesSupported = Environment.GetEnvironmentVariable("TERM") != null;
}
}
else
{
isAnsiCodesSupported = true;
}
}
// Enable support for ANSI escape codes
// (but probably only suitable for windows 10+)
// https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
private static bool TryEnableVTMode()
{
var iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (!GetConsoleMode(iStdOut, out uint outConsoleMode))
{
return false;
}
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
return SetConsoleMode(iStdOut, outConsoleMode);
}
}
}

123
AssetStudio/CommonString.cs Normal file
View File

@@ -0,0 +1,123 @@
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"},
{1161, "Hash128"},
{1169, "RenderingLayerMask"},
{1188, "fixed_array"},
{1200, "EntityId"},
};
}
}

133
AssetStudio/CubismMoc.cs Normal file
View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace AssetStudio
{
public enum CubismSDKVersion : byte
{
V30 = 1,
V33,
V40,
V42,
V50
}
public sealed class CubismMoc : IDisposable
{
public CubismSDKVersion Version { get; }
public string VersionDescription { get; }
public float CanvasWidth { get; }
public float CanvasHeight { get; }
public float CentralPosX { get; }
public float CentralPosY { get; }
public float PixelPerUnit { get; }
public uint PartCount { get; }
public uint ParamCount { get; }
public HashSet<string> PartNames { get; }
public HashSet<string> ParamNames { get; }
private byte[] modelData;
private int modelDataSize;
private bool isBigEndian;
public CubismMoc(MonoBehaviour moc)
{
var reader = moc.reader;
reader.Reset();
reader.Position += 28; //PPtr<GameObject> m_GameObject, m_Enabled, PPtr<MonoScript>
reader.ReadAlignedString(); //m_Name
modelDataSize = (int)reader.ReadUInt32();
modelData = BigArrayPool<byte>.Shared.Rent(modelDataSize);
_ = reader.Read(modelData, 0, modelDataSize);
var sdkVer = modelData[4];
if (Enum.IsDefined(typeof(CubismSDKVersion), sdkVer))
{
Version = (CubismSDKVersion)sdkVer;
VersionDescription = ParseVersion();
}
else
{
var msg = $"Unknown SDK version ({sdkVer})";
VersionDescription = msg;
Version = 0;
Logger.Warning($"Live2D model \"{moc.m_Name}\": " + msg);
return;
}
isBigEndian = BitConverter.ToBoolean(modelData, 5);
var modelDataSpan = new ReadOnlySpan<byte>(modelData, 0, modelDataSize);
//offsets
var countInfoTableOffset = (int)modelDataSpan.ReadUInt32(64, isBigEndian);
var canvasInfoOffset = (int)modelDataSpan.ReadUInt32(68, isBigEndian);
var partIdsOffset = modelDataSpan.ReadUInt32(76, isBigEndian);
var parameterIdsOffset = modelDataSpan.ReadUInt32(264, isBigEndian);
//canvas
PixelPerUnit = modelDataSpan.ReadSingle(canvasInfoOffset, isBigEndian);
CentralPosX = modelDataSpan.ReadSingle(canvasInfoOffset + 4, isBigEndian);
CentralPosY = modelDataSpan.ReadSingle(canvasInfoOffset + 8, isBigEndian);
CanvasWidth = modelDataSpan.ReadSingle(canvasInfoOffset + 12, isBigEndian);
CanvasHeight = modelDataSpan.ReadSingle(canvasInfoOffset + 16, isBigEndian);
//model
PartCount = modelDataSpan.ReadUInt32(countInfoTableOffset, isBigEndian);
ParamCount = modelDataSpan.ReadUInt32(countInfoTableOffset + 20, isBigEndian);
PartNames = ReadMocStrings(modelDataSpan, (int)partIdsOffset, (int)PartCount);
ParamNames = ReadMocStrings(modelDataSpan, (int)parameterIdsOffset, (int)ParamCount);
}
public void SaveMoc3(string savePath)
{
if (!savePath.EndsWith(".moc3"))
savePath += ".moc3";
using (var file = File.OpenWrite(savePath))
{
file.Write(modelData, 0, modelDataSize);
}
}
private string ParseVersion()
{
switch (Version)
{
case CubismSDKVersion.V30: return "SDK3.0/Cubism3.0(3.2)";
case CubismSDKVersion.V33: return "SDK3.3/Cubism3.3";
case CubismSDKVersion.V40: return "SDK4.0/Cubism4.0";
case CubismSDKVersion.V42: return "SDK4.2/Cubism4.2";
case CubismSDKVersion.V50: return "SDK5.0/Cubism5.0";
default: return "";
}
}
private static HashSet<string> ReadMocStrings(ReadOnlySpan<byte> data, int index, int count)
{
const int strLen = 64;
var strHashSet = new HashSet<string>();
for (var i = 0; i < count; i++)
{
if (index + i * strLen <= data.Length)
{
var str = data.Slice(index + i * strLen, strLen).ReadStringToNull();
strHashSet.Add(str);
}
}
return strHashSet;
}
private void Dispose(bool disposing)
{
if (disposing)
{
BigArrayPool<byte>.Shared.Return(modelData, clearArray: true);
}
}
public void Dispose()
{
Dispose(true);
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace AssetStudio
{
public class CubismModel
{
public string Name { get; set; }
public string Container { get; set; }
public MonoBehaviour CubismModelMono { get; set; }
public MonoBehaviour PhysicsController { get; set; }
public MonoBehaviour FadeController { get; set; }
public MonoBehaviour ExpressionController { get; set; }
public List<MonoBehaviour> RenderTextureList { get; set; }
public List<MonoBehaviour> ParamDisplayInfoList { get; set; }
public List<MonoBehaviour> PartDisplayInfoList { get; set; }
public List<MonoBehaviour> PosePartList { get; set; }
public List<AnimationClip> ClipMotionList { get; set; }
public GameObject ModelGameObject { get; set; }
public CubismModel(GameObject m_GameObject)
{
Name = m_GameObject.m_Name;
ModelGameObject = m_GameObject;
RenderTextureList = new List<MonoBehaviour>();
ParamDisplayInfoList = new List<MonoBehaviour>();
PartDisplayInfoList = new List<MonoBehaviour>();
PosePartList = new List<MonoBehaviour>();
ClipMotionList = new List<AnimationClip>();
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Buffers.Binary;
namespace AssetStudio.CustomOptions.Asmo
{
public class OptionsFile
{
private static readonly byte[] OptionsFileSign = new byte[] { 0x41, 0x53, 0x4D, 0x4F }; //ASMO
public static readonly string Extension = ".asmo";
public byte[] Signature { get; private set; } = OptionsFileSign;
public short Version { get; private set; } = 1;
public short Reserved { get; set; }
public uint DataCrc { get; set; }
public int DataSize { get; set; }
public byte[] Data { get; set; }
public OptionsFile() { }
public OptionsFile(EndianBinaryReader reader)
{
Signature = reader.ReadBytes(4);
Version = reader.ReadInt16();
Reserved = reader.ReadInt16();
DataCrc = reader.ReadUInt32();
DataSize = reader.ReadInt32();
CheckHeader(reader.BaseStream.Length);
Data = reader.ReadBytes(DataSize);
}
public void CheckHeader(long fileLength)
{
if (!Signature.AsSpan().SequenceEqual(OptionsFileSign))
throw new NotSupportedException("Incorrect options file signature.");
if (Version != 1)
throw new NotSupportedException("Incorrect options file version.");
if (DataSize <= 0 || DataSize > fileLength)
throw new NotSupportedException("Incorrect data size.");
}
public byte[] ToByteArray()
{
var buffer = new byte[16 + DataSize];
OptionsFileSign.AsSpan().CopyTo(buffer);
BinaryPrimitives.WriteInt16BigEndian(buffer.AsSpan(4), Version);
BinaryPrimitives.WriteInt16BigEndian(buffer.AsSpan(6), Reserved);
BinaryPrimitives.WriteUInt32BigEndian(buffer.AsSpan(8), DataCrc);
BinaryPrimitives.WriteInt32BigEndian(buffer.AsSpan(12), DataSize);
Data.AsSpan().CopyTo(buffer.AsSpan(16));
return buffer;
}
}
}

View File

@@ -0,0 +1,40 @@
namespace AssetStudio.CustomOptions
{
public class CustomBundleOptions
{
private CompressionType _customBlockCompression = CompressionType.Auto;
private CompressionType _customBlockInfoCompression = CompressionType.Auto;
private bool _decompressToDisk;
public ImportOptions Options;
public CompressionType CustomBlockCompression
{
get => _customBlockCompression;
set => _customBlockCompression = SetOption(nameof(CustomBlockCompression), value);
}
public CompressionType CustomBlockInfoCompression
{
get => _customBlockInfoCompression;
set => _customBlockInfoCompression = SetOption(nameof(CustomBlockInfoCompression), value);
}
public bool DecompressToDisk
{
get => _decompressToDisk;
set => _decompressToDisk = SetOption(nameof(DecompressToDisk), value);
}
public CustomBundleOptions() { }
public CustomBundleOptions(ImportOptions importOptions)
{
Options = importOptions;
}
private static T SetOption<T>(string option, T value)
{
Logger.Info($"- {option}: {value}");
return value;
}
}
}

View File

@@ -0,0 +1,94 @@
using AssetStudio.CustomOptions.Asmo;
using SevenZip;
using System;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio.CustomOptions
{
public class ImportOptions
{
private static JsonSerializerOptions jsonOptions;
private static string fileName = "ImportOptions";
private UnityVersion _customUnityVer;
public CustomBundleOptions BundleOptions { get; set; }
public UnityVersion CustomUnityVersion { get => _customUnityVer; set => SetUnityVersion(value); }
static ImportOptions()
{
jsonOptions = new JsonSerializerOptions
{
ReferenceHandler = ReferenceHandler.Preserve,
IncludeFields = true,
};
}
public ImportOptions()
{
BundleOptions = new CustomBundleOptions(this);
CustomUnityVersion = null;
}
public static ImportOptions FromOptionsFile(OptionsFile optionsFile)
{
if (optionsFile.Reserved != 0)
{
Logger.Debug("Skipped. Not an import options file.");
return null;
}
var utf8Bytes = Convert.FromBase64String(Encoding.ASCII.GetString(optionsFile.Data));
var dataCrc = CRC.CalculateDigest(utf8Bytes, 0, (uint)utf8Bytes.Length);
if (optionsFile.DataCrc != dataCrc)
throw new IOException("Options file data is corrupted.");
return JsonSerializer.Deserialize<ImportOptions>(utf8Bytes, jsonOptions);
}
public void SaveToFile(string outputFolder)
{
var utf8Bytes = JsonSerializer.SerializeToUtf8Bytes(this, jsonOptions);
var dataCrc = CRC.CalculateDigest(utf8Bytes, 0, (uint)utf8Bytes.Length);
var base64String = Convert.ToBase64String(utf8Bytes);
var optionsFile = new OptionsFile
{
DataCrc = dataCrc,
DataSize = base64String.Length,
Data = Encoding.ASCII.GetBytes(base64String),
};
var unityVer = _customUnityVer != null
? $"_{_customUnityVer}"
: "";
var path = Path.Combine(outputFolder, $"{fileName}{unityVer}{OptionsFile.Extension}");
File.WriteAllBytes(path, optionsFile.ToByteArray());
Logger.Info($"Options file saved to \"{path}\"");
}
private void SetUnityVersion(UnityVersion value)
{
if (_customUnityVer == value)
return;
if (value == null)
{
_customUnityVer = null;
Logger.Info("- Specified Unity version: None");
return;
}
if (string.IsNullOrEmpty(value.BuildType))
{
throw new NotSupportedException("Specified Unity version is not in a correct format.\n" +
"Specify full Unity version, including letters at the end.\n" +
"Example: 2017.4.39f1");
}
_customUnityVer = value;
Logger.Info($"- Specified Unity version: {_customUnityVer}");
}
}
}

View File

@@ -0,0 +1,129 @@
using System;
using System.Buffers.Binary;
using System.IO;
namespace AssetStudio
{
public class EndianBinaryReader : BinaryReader
{
private readonly byte[] buffer;
public EndianType Endian;
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
{
Endian = endian;
buffer = new byte[8];
}
public long Position
{
get => BaseStream.Position;
set => BaseStream.Position = value;
}
public override short ReadInt16()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 2);
return BinaryPrimitives.ReadInt16BigEndian(buffer);
}
return base.ReadInt16();
}
public override int ReadInt32()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
return BinaryPrimitives.ReadInt32BigEndian(buffer);
}
return base.ReadInt32();
}
public override long ReadInt64()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
return BinaryPrimitives.ReadInt64BigEndian(buffer);
}
return base.ReadInt64();
}
public override ushort ReadUInt16()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 2);
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
}
return base.ReadUInt16();
}
public override uint ReadUInt32()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
}
return base.ReadUInt32();
}
public override ulong ReadUInt64()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
}
return base.ReadUInt64();
}
#if NETFRAMEWORK
public override float ReadSingle()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
buffer.AsSpan(0, 4).Reverse();
return BitConverter.ToSingle(buffer, 0);
}
return base.ReadSingle();
}
public override double ReadDouble()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
buffer.AsSpan().Reverse();
return BitConverter.ToDouble(buffer, 0);
}
return base.ReadDouble();
}
#else
public override float ReadSingle()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
return BinaryPrimitives.ReadSingleBigEndian(buffer);
}
return base.ReadSingle();
}
public override double ReadDouble()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
return BinaryPrimitives.ReadDoubleBigEndian(buffer);
}
return base.ReadDouble();
}
#endif
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Buffers.Binary;
using System.Text;
namespace AssetStudio
{
public static class EndianSpanReader
{
public static uint ReadUInt32(this Span<byte> data, int start, bool isBigEndian)
{
return ReadUInt32((ReadOnlySpan<byte>)data, start, isBigEndian);
}
public static uint ReadUInt32(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadUInt32BigEndian(data.Slice(start))
: BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(start));
}
public static long ReadUInt16(this Span<byte> data, int start, bool isBigEndian)
{
return ReadUInt16((ReadOnlySpan<byte>)data, start, isBigEndian);
}
public static uint ReadUInt16(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadUInt16BigEndian(data.Slice(start))
: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(start));
}
public static long ReadInt64(this Span<byte> data, int start, bool isBigEndian)
{
return ReadInt64((ReadOnlySpan<byte>)data, start, isBigEndian);
}
public static long ReadInt64(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadInt64BigEndian(data.Slice(start))
: BinaryPrimitives.ReadInt64LittleEndian(data.Slice(start));
}
public static float ReadSingle(this Span<byte> data, int start, bool isBigEndian)
{
return ReadSingle((ReadOnlySpan<byte>)data, start, isBigEndian);
}
#if NETFRAMEWORK
public static float ReadSingle(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
var bytes = data.Slice(start, 4).ToArray();
if ((isBigEndian && BitConverter.IsLittleEndian) || (!isBigEndian && !BitConverter.IsLittleEndian))
bytes.AsSpan().Reverse();
return BitConverter.ToSingle(bytes, 0);
}
#else
public static float ReadSingle(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadSingleBigEndian(data[start..])
: BinaryPrimitives.ReadSingleLittleEndian(data[start..]);
}
#endif
public static string ReadStringToNull(this Span<byte> data, int maxLength = 32767)
{
return ReadStringToNull((ReadOnlySpan<byte>)data, maxLength);
}
public static string ReadStringToNull(this ReadOnlySpan<byte> data, int maxLength = 32767)
{
Span<byte> bytes = stackalloc byte[maxLength];
var count = 0;
while (count != data.Length && count < maxLength)
{
var b = data[count];
if (b == 0)
{
break;
}
bytes[count] = b;
count++;
}
bytes = bytes.Slice(0, count);
#if NETFRAMEWORK
return Encoding.UTF8.GetString(bytes.ToArray());
#else
return Encoding.UTF8.GetString(bytes);
#endif
}
}
}

14
AssetStudio/EndianType.cs Normal file
View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
{
public enum EndianType
{
LittleEndian,
BigEndian
}
}

Some files were not shown because too many files have changed in this diff Show More