Compare commits

...

23 Commits

Author SHA1 Message Date
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
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
scriptkitz 0e1a886e0b 修正UV导出计算错误问题。 (#891) 2021-12-11 15:48:54 +08:00
41 changed files with 1046 additions and 725 deletions
+57
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
@@ -6,7 +6,8 @@
<Version>0.16.0.0</Version> <Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion> <AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion> <FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2020-2021; Copyright © hozuki 2020</Copyright> <Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
</Project> </Project>
+3 -1
View File
@@ -5,7 +5,8 @@
<Version>0.16.0.0</Version> <Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion> <AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion> <FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright> <Copyright>Copyright © Perfare 2018-2022</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' "> <ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
@@ -14,6 +15,7 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' "> <ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="System.Memory" Version="4.5.4" /> <PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" /> <PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" />
</ItemGroup> </ItemGroup>
+144 -24
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using static AssetStudio.ImportHelper; using static AssetStudio.ImportHelper;
@@ -17,6 +18,7 @@ namespace AssetStudio
private List<string> importFiles = new List<string>(); private List<string> importFiles = new List<string>();
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
public void LoadFiles(params string[] files) public void LoadFiles(params string[] files)
@@ -53,6 +55,7 @@ namespace AssetStudio
importFiles.Clear(); importFiles.Clear();
importFilesHash.Clear(); importFilesHash.Clear();
noexistFiles.Clear();
assetsFileListHash.Clear(); assetsFileListHash.Clear();
ReadAssets(); ReadAssets();
@@ -84,6 +87,9 @@ namespace AssetStudio
case FileType.BrotliFile: case FileType.BrotliFile:
LoadFile(DecompressBrotli(reader)); LoadFile(DecompressBrotli(reader));
break; break;
case FileType.ZipFile:
LoadZipFile(reader);
break;
} }
} }
@@ -91,7 +97,7 @@ namespace AssetStudio
{ {
if (!assetsFileListHash.Contains(reader.FileName)) if (!assetsFileListHash.Contains(reader.FileName))
{ {
Logger.Info($"Loading {reader.FileName}"); Logger.Info($"Loading {reader.FullPath}");
try try
{ {
var assetsFile = new SerializedFile(reader, this); var assetsFile = new SerializedFile(reader, this);
@@ -106,31 +112,38 @@ namespace AssetStudio
if (!importFilesHash.Contains(sharedFileName)) if (!importFilesHash.Contains(sharedFileName))
{ {
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName); var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
if (!File.Exists(sharedFilePath)) if (!noexistFiles.Contains(sharedFilePath))
{ {
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories); if (!File.Exists(sharedFilePath))
if (findFiles.Length > 0)
{ {
sharedFilePath = findFiles[0]; var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
}
}
if (File.Exists(sharedFilePath))
{
importFiles.Add(sharedFilePath);
importFilesHash.Add(sharedFileName);
}
else
{
noexistFiles.Add(sharedFilePath);
} }
}
if (File.Exists(sharedFilePath))
{
importFiles.Add(sharedFilePath);
importFilesHash.Add(sharedFileName);
} }
} }
} }
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Error($"Error while reading assets file {reader.FileName}", e); Logger.Error($"Error while reading assets file {reader.FullPath}", e);
reader.Dispose(); reader.Dispose();
} }
} }
else else
{ {
Logger.Info($"Skipping {reader.FullPath}");
reader.Dispose(); reader.Dispose();
} }
} }
@@ -143,7 +156,7 @@ namespace AssetStudio
{ {
var assetsFile = new SerializedFile(reader, this); var assetsFile = new SerializedFile(reader, this);
assetsFile.originalPath = originalPath; assetsFile.originalPath = originalPath;
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.kUnknown_7) if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
{ {
assetsFile.SetVersion(unityVersion); assetsFile.SetVersion(unityVersion);
} }
@@ -153,15 +166,17 @@ namespace AssetStudio
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Error($"Error while reading assets file {reader.FileName} from {Path.GetFileName(originalPath)}", e); Logger.Error($"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}", e);
resourceFileReaders.Add(reader.FileName, reader); resourceFileReaders.Add(reader.FileName, reader);
} }
} }
else
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
} }
private void LoadBundleFile(FileReader reader, string originalPath = null) private void LoadBundleFile(FileReader reader, string originalPath = null)
{ {
Logger.Info("Loading " + reader.FileName); Logger.Info("Loading " + reader.FullPath);
try try
{ {
var bundleFile = new BundleFile(reader); var bundleFile = new BundleFile(reader);
@@ -181,7 +196,7 @@ namespace AssetStudio
} }
catch (Exception e) catch (Exception e)
{ {
var str = $"Error while reading bundle file {reader.FileName}"; var str = $"Error while reading bundle file {reader.FullPath}";
if (originalPath != null) if (originalPath != null)
{ {
str += $" from {Path.GetFileName(originalPath)}"; str += $" from {Path.GetFileName(originalPath)}";
@@ -196,7 +211,7 @@ namespace AssetStudio
private void LoadWebFile(FileReader reader) private void LoadWebFile(FileReader reader)
{ {
Logger.Info("Loading " + reader.FileName); Logger.Info("Loading " + reader.FullPath);
try try
{ {
var webFile = new WebFile(reader); var webFile = new WebFile(reader);
@@ -223,7 +238,107 @@ namespace AssetStudio
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Error($"Error while reading web file {reader.FileName}", e); Logger.Error($"Error while reading web file {reader.FullPath}", e);
}
finally
{
reader.Dispose();
}
}
private void LoadZipFile(FileReader reader)
{
Logger.Info("Loading " + 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
foreach (string basePath in splitFiles)
{
try
{
Stream splitStream = new MemoryStream();
int i = 0;
while (true)
{
string path = $"{basePath}.split{i++}";
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);
LoadFile(entryReader);
}
catch (Exception e)
{
Logger.Error($"Error while reading zip split file {basePath}", e);
}
}
// load all entries
foreach (ZipArchiveEntry entry in archive.Entries)
{
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);
LoadFile(entryReader);
if (entryReader.FileType == FileType.ResourceFile)
{
entryReader.Position = 0;
if (!resourceFileReaders.ContainsKey(entry.Name))
{
resourceFileReaders.Add(entry.Name, entryReader);
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading zip entry {entry.FullName}", e);
}
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading zip file {reader.FileName}", e);
} }
finally finally
{ {
@@ -373,6 +488,7 @@ namespace AssetStudio
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine("Unable to load object") sb.AppendLine("Unable to load object")
.AppendLine($"Assets {assetsFile.fileName}") .AppendLine($"Assets {assetsFile.fileName}")
.AppendLine($"Path {assetsFile.originalPath}")
.AppendLine($"Type {objectReader.type}") .AppendLine($"Type {objectReader.type}")
.AppendLine($"PathID {objectInfo.m_PathID}") .AppendLine($"PathID {objectInfo.m_PathID}")
.Append(e); .Append(e);
@@ -424,10 +540,6 @@ namespace AssetStudio
} }
else if (obj is SpriteAtlas m_SpriteAtlas) else if (obj is SpriteAtlas m_SpriteAtlas)
{ {
if (m_SpriteAtlas.m_IsVariant)
{
continue;
}
foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites) foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)
{ {
if (m_PackedSprite.TryGet(out var m_Sprite)) if (m_PackedSprite.TryGet(out var m_Sprite))
@@ -436,6 +548,14 @@ namespace AssetStudio
{ {
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas); m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
} }
else
{
m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);
if (m_SpriteAtlaOld.m_IsVariant)
{
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
}
} }
} }
} }
@@ -443,4 +563,4 @@ namespace AssetStudio
} }
} }
} }
} }
+6 -1
View File
@@ -8,7 +8,8 @@ namespace AssetStudio
public enum BuildTarget public enum BuildTarget
{ {
NoTarget = -2, NoTarget = -2,
DashboardWidget = 1, AnyPlayer = -1,
ValidPlayer = 1,
StandaloneOSX = 2, StandaloneOSX = 2,
StandaloneOSXPPC = 3, StandaloneOSXPPC = 3,
StandaloneOSXIntel = 4, StandaloneOSXIntel = 4,
@@ -19,8 +20,10 @@ namespace AssetStudio
iOS = 9, iOS = 9,
PS3, PS3,
XBOX360, XBOX360,
Broadcom = 12,
Android = 13, Android = 13,
StandaloneGLESEmu = 14, StandaloneGLESEmu = 14,
StandaloneGLES20Emu = 15,
NaCl = 16, NaCl = 16,
StandaloneLinux = 17, StandaloneLinux = 17,
FlashPlayer = 18, FlashPlayer = 18,
@@ -48,6 +51,8 @@ namespace AssetStudio
GameCoreXboxSeries, GameCoreXboxSeries,
GameCoreXboxOne, GameCoreXboxOne,
PS5, PS5,
EmbeddedLinux,
QNX,
UnknownPlatform = 9999 UnknownPlatform = 9999
} }
} }
+55 -19
View File
@@ -1,9 +1,36 @@
using K4os.Compression.LZ4; using K4os.Compression.LZ4;
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace AssetStudio namespace AssetStudio
{ {
[Flags]
public enum ArchiveFlags
{
CompressionTypeMask = 0x3f,
BlocksAndDirectoryInfoCombined = 0x40,
BlocksInfoAtTheEnd = 0x80,
OldWebPluginCompatibility = 0x100,
BlockInfoNeedPaddingAtStart = 0x200
}
[Flags]
public enum StorageBlockFlags
{
CompressionTypeMask = 0x3f,
Streamed = 0x40
}
public enum CompressionType
{
None,
Lzma,
Lz4,
Lz4HC,
Lzham
}
public class BundleFile public class BundleFile
{ {
public class Header public class Header
@@ -15,14 +42,14 @@ namespace AssetStudio
public long size; public long size;
public uint compressedBlocksInfoSize; public uint compressedBlocksInfoSize;
public uint uncompressedBlocksInfoSize; public uint uncompressedBlocksInfoSize;
public uint flags; public ArchiveFlags flags;
} }
public class StorageBlock public class StorageBlock
{ {
public uint compressedSize; public uint compressedSize;
public uint uncompressedSize; public uint uncompressedSize;
public ushort flags; public StorageBlockFlags flags;
} }
public class Node public class Node
@@ -77,7 +104,6 @@ namespace AssetStudio
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader) private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
{ {
var isCompressed = m_Header.signature == "UnityWeb";
if (m_Header.version >= 4) if (m_Header.version >= 4)
{ {
var hash = reader.ReadBytes(16); var hash = reader.ReadBytes(16);
@@ -94,7 +120,6 @@ namespace AssetStudio
{ {
compressedSize = reader.ReadUInt32(), compressedSize = reader.ReadUInt32(),
uncompressedSize = reader.ReadUInt32(), uncompressedSize = reader.ReadUInt32(),
flags = (ushort)(isCompressed ? 1 : 0)
}; };
if (i == levelCount - 1) if (i == levelCount - 1)
{ {
@@ -131,10 +156,11 @@ namespace AssetStudio
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream) private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
{ {
var isCompressed = m_Header.signature == "UnityWeb";
foreach (var blockInfo in m_BlocksInfo) foreach (var blockInfo in m_BlocksInfo)
{ {
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize); var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
if (blockInfo.flags == 1) if (isCompressed)
{ {
using (var memoryStream = new MemoryStream(uncompressedBytes)) using (var memoryStream = new MemoryStream(uncompressedBytes))
{ {
@@ -194,7 +220,7 @@ namespace AssetStudio
m_Header.size = reader.ReadInt64(); m_Header.size = reader.ReadInt64();
m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32(); m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
m_Header.flags = reader.ReadUInt32(); m_Header.flags = (ArchiveFlags)reader.ReadUInt32();
if (m_Header.signature != "UnityFS") if (m_Header.signature != "UnityFS")
{ {
reader.ReadByte(); reader.ReadByte();
@@ -208,27 +234,28 @@ namespace AssetStudio
{ {
reader.AlignStream(16); reader.AlignStream(16);
} }
if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
{ {
var position = reader.Position; var position = reader.Position;
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize; reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
reader.Position = position; reader.Position = position;
} }
else //0x40 kArchiveBlocksAndDirectoryInfoCombined else //0x40 BlocksAndDirectoryInfoCombined
{ {
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
} }
MemoryStream blocksInfoUncompresseddStream; MemoryStream blocksInfoUncompresseddStream;
var uncompressedSize = m_Header.uncompressedBlocksInfoSize; var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
switch (compressionType)
{ {
default: //None case CompressionType.None:
{ {
blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes); blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
break; break;
} }
case 1: //LZMA case CompressionType.Lzma:
{ {
blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize)); blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes)) using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
@@ -238,8 +265,8 @@ namespace AssetStudio
blocksInfoUncompresseddStream.Position = 0; blocksInfoUncompresseddStream.Position = 0;
break; break;
} }
case 2: //LZ4 case CompressionType.Lz4:
case 3: //LZ4HC case CompressionType.Lz4HC:
{ {
var uncompressedBytes = new byte[uncompressedSize]; var uncompressedBytes = new byte[uncompressedSize];
var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes); var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
@@ -250,6 +277,8 @@ namespace AssetStudio
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes); blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
break; break;
} }
default:
throw new IOException($"Unsupported compression type {compressionType}");
} }
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream)) using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
{ {
@@ -262,7 +291,7 @@ namespace AssetStudio
{ {
uncompressedSize = blocksInfoReader.ReadUInt32(), uncompressedSize = blocksInfoReader.ReadUInt32(),
compressedSize = blocksInfoReader.ReadUInt32(), compressedSize = blocksInfoReader.ReadUInt32(),
flags = blocksInfoReader.ReadUInt16() flags = (StorageBlockFlags)blocksInfoReader.ReadUInt16()
}; };
} }
@@ -279,26 +308,31 @@ namespace AssetStudio
}; };
} }
} }
if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
{
reader.AlignStream(16);
}
} }
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream) private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
{ {
foreach (var blockInfo in m_BlocksInfo) foreach (var blockInfo in m_BlocksInfo)
{ {
switch (blockInfo.flags & 0x3F) //kStorageBlockCompressionTypeMask var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
switch (compressionType)
{ {
default: //None case CompressionType.None:
{ {
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize); reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
break; break;
} }
case 1: //LZMA case CompressionType.Lzma:
{ {
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize); SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
break; break;
} }
case 2: //LZ4 case CompressionType.Lz4:
case 3: //LZ4HC case CompressionType.Lz4HC:
{ {
var compressedSize = (int)blockInfo.compressedSize; var compressedSize = (int)blockInfo.compressedSize;
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize); var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
@@ -315,6 +349,8 @@ namespace AssetStudio
BigArrayPool<byte>.Shared.Return(uncompressedBytes); BigArrayPool<byte>.Shared.Return(uncompressedBytes);
break; break;
} }
default:
throw new IOException($"Unsupported compression type {compressionType}");
} }
} }
blocksStream.Position = 0; blocksStream.Position = 0;
+9 -4
View File
@@ -797,6 +797,7 @@ namespace AssetStudio
public ClassIDType typeID; public ClassIDType typeID;
public byte customType; public byte customType;
public byte isPPtrCurve; public byte isPPtrCurve;
public byte isIntCurve;
public GenericBinding() { } public GenericBinding() { }
@@ -816,6 +817,10 @@ namespace AssetStudio
} }
customType = reader.ReadByte(); customType = reader.ReadByte();
isPPtrCurve = reader.ReadByte(); isPPtrCurve = reader.ReadByte();
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{
isIntCurve = reader.ReadByte();
}
reader.AlignStream(); reader.AlignStream();
} }
} }
@@ -909,9 +914,9 @@ namespace AssetStudio
public enum AnimationType public enum AnimationType
{ {
kLegacy = 1, Legacy = 1,
kGeneric = 2, Generic = 2,
kHumanoid = 3 Humanoid = 3
}; };
public sealed class AnimationClip : NamedObject public sealed class AnimationClip : NamedObject
@@ -945,7 +950,7 @@ namespace AssetStudio
else if (version[0] >= 4)//4.0 and up else if (version[0] >= 4)//4.0 and up
{ {
m_AnimationType = (AnimationType)reader.ReadInt32(); m_AnimationType = (AnimationType)reader.ReadInt32();
if (m_AnimationType == AnimationType.kLegacy) if (m_AnimationType == AnimationType.Legacy)
m_Legacy = true; m_Legacy = true;
} }
else else
+39 -22
View File
@@ -9,7 +9,7 @@ namespace AssetStudio
public sealed class AudioClip : NamedObject public sealed class AudioClip : NamedObject
{ {
public int m_Format; public int m_Format;
public AudioType m_Type; public FMODSoundType m_Type;
public bool m_3D; public bool m_3D;
public bool m_UseHardware; public bool m_UseHardware;
@@ -36,7 +36,7 @@ namespace AssetStudio
if (version[0] < 5) if (version[0] < 5)
{ {
m_Format = reader.ReadInt32(); m_Format = reader.ReadInt32();
m_Type = (AudioType)reader.ReadInt32(); m_Type = (FMODSoundType)reader.ReadInt32();
m_3D = reader.ReadBoolean(); m_3D = reader.ReadBoolean();
m_UseHardware = reader.ReadBoolean(); m_UseHardware = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
@@ -92,34 +92,51 @@ namespace AssetStudio
} }
} }
public enum AudioType public enum FMODSoundType
{ {
UNKNOWN, UNKNOWN = 0,
ACC, ACC = 1,
AIFF, AIFF = 2,
ASF = 3,
AT3 = 4,
CDDA = 5,
DLS = 6,
FLAC = 7,
FSB = 8,
GCADPCM = 9,
IT = 10, IT = 10,
MIDI = 11,
MOD = 12, MOD = 12,
MPEG, MPEG = 13,
OGGVORBIS, OGGVORBIS = 14,
PLAYLIST = 15,
RAW = 16,
S3M = 17, S3M = 17,
SF2 = 18,
USER = 19,
WAV = 20, WAV = 20,
XM, XM = 21,
XMA, XMA = 22,
VAG, VAG = 23,
AUDIOQUEUE AUDIOQUEUE = 24,
XWMA = 25,
BCWAV = 26,
AT9 = 27,
VORBIS = 28,
MEDIA_FOUNDATION = 29
} }
public enum AudioCompressionFormat public enum AudioCompressionFormat
{ {
PCM, PCM = 0,
Vorbis, Vorbis = 1,
ADPCM, ADPCM = 2,
MP3, MP3 = 3,
VAG, PSMVAG = 4,
HEVAG, HEVAG = 5,
XMA, XMA = 6,
AAC, AAC = 7,
GCADPCM, GCADPCM = 8,
ATRAC9 ATRAC9 = 9
} }
} }
+10 -1
View File
@@ -74,9 +74,18 @@ namespace AssetStudio
var m_ShaderKeywords = reader.ReadStringArray(); var m_ShaderKeywords = reader.ReadStringArray();
} }
if (version[0] >= 5) //5.0 and up if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 and up
{
var m_ValidKeywords = reader.ReadStringArray();
var m_InvalidKeywords = reader.ReadStringArray();
}
else if (version[0] >= 5) //5.0 ~ 2021.2
{ {
var m_ShaderKeywords = reader.ReadAlignedString(); var m_ShaderKeywords = reader.ReadAlignedString();
}
if (version[0] >= 5) //5.0 and up
{
var m_LightmapFlags = reader.ReadUInt32(); var m_LightmapFlags = reader.ReadUInt32();
} }
+105 -100
View File
@@ -396,14 +396,14 @@ namespace AssetStudio
} }
} }
public enum GfxPrimitiveType : int public enum GfxPrimitiveType
{ {
kPrimitiveTriangles = 0, Triangles = 0,
kPrimitiveTriangleStrip = 1, TriangleStrip = 1,
kPrimitiveQuads = 2, Quads = 2,
kPrimitiveLines = 3, Lines = 3,
kPrimitiveLineStrip = 4, LineStrip = 4,
kPrimitivePoints = 5, Points = 5
}; };
public class SubMesh public class SubMesh
@@ -651,6 +651,11 @@ namespace AssetStudio
int m_MeshUsageFlags = reader.ReadInt32(); int m_MeshUsageFlags = reader.ReadInt32();
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{
int m_CookingOptions = reader.ReadInt32();
}
if (version[0] >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
var m_BakedConvexCollisionMesh = reader.ReadUInt8Array(); var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
@@ -1060,7 +1065,7 @@ namespace AssetStudio
} }
var indexCount = m_SubMesh.indexCount; var indexCount = m_SubMesh.indexCount;
var topology = m_SubMesh.topology; var topology = m_SubMesh.topology;
if (topology == GfxPrimitiveType.kPrimitiveTriangles) if (topology == GfxPrimitiveType.Triangles)
{ {
for (int i = 0; i < indexCount; i += 3) for (int i = 0; i < indexCount; i += 3)
{ {
@@ -1069,7 +1074,7 @@ namespace AssetStudio
m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]); m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);
} }
} }
else if (version[0] < 4 || topology == GfxPrimitiveType.kPrimitiveTriangleStrip) else if (version[0] < 4 || topology == GfxPrimitiveType.TriangleStrip)
{ {
// de-stripify : // de-stripify :
uint triIndex = 0; uint triIndex = 0;
@@ -1100,7 +1105,7 @@ namespace AssetStudio
//fix indexCount //fix indexCount
m_SubMesh.indexCount = triIndex; m_SubMesh.indexCount = triIndex;
} }
else if (topology == GfxPrimitiveType.kPrimitiveQuads) else if (topology == GfxPrimitiveType.Quads)
{ {
for (int q = 0; q < indexCount; q += 4) for (int q = 0; q < indexCount; q += 4)
{ {
@@ -1193,44 +1198,44 @@ namespace AssetStudio
{ {
public enum VertexChannelFormat public enum VertexChannelFormat
{ {
kChannelFormatFloat, Float,
kChannelFormatFloat16, Float16,
kChannelFormatColor, Color,
kChannelFormatByte, Byte,
kChannelFormatUInt32 UInt32
} }
public enum VertexFormat2017 public enum VertexFormat2017
{ {
kVertexFormatFloat, Float,
kVertexFormatFloat16, Float16,
kVertexFormatColor, Color,
kVertexFormatUNorm8, UNorm8,
kVertexFormatSNorm8, SNorm8,
kVertexFormatUNorm16, UNorm16,
kVertexFormatSNorm16, SNorm16,
kVertexFormatUInt8, UInt8,
kVertexFormatSInt8, SInt8,
kVertexFormatUInt16, UInt16,
kVertexFormatSInt16, SInt16,
kVertexFormatUInt32, UInt32,
kVertexFormatSInt32 SInt32
} }
public enum VertexFormat public enum VertexFormat
{ {
kVertexFormatFloat, Float,
kVertexFormatFloat16, Float16,
kVertexFormatUNorm8, UNorm8,
kVertexFormatSNorm8, SNorm8,
kVertexFormatUNorm16, UNorm16,
kVertexFormatSNorm16, SNorm16,
kVertexFormatUInt8, UInt8,
kVertexFormatSInt8, SInt8,
kVertexFormatUInt16, UInt16,
kVertexFormatSInt16, SInt16,
kVertexFormatUInt32, UInt32,
kVertexFormatSInt32 SInt32
} }
public static VertexFormat ToVertexFormat(int format, int[] version) public static VertexFormat ToVertexFormat(int format, int[] version)
@@ -1239,16 +1244,16 @@ namespace AssetStudio
{ {
switch ((VertexChannelFormat)format) switch ((VertexChannelFormat)format)
{ {
case VertexChannelFormat.kChannelFormatFloat: case VertexChannelFormat.Float:
return VertexFormat.kVertexFormatFloat; return VertexFormat.Float;
case VertexChannelFormat.kChannelFormatFloat16: case VertexChannelFormat.Float16:
return VertexFormat.kVertexFormatFloat16; return VertexFormat.Float16;
case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4 case VertexChannelFormat.Color: //in 4.x is size 4
return VertexFormat.kVertexFormatUNorm8; return VertexFormat.UNorm8;
case VertexChannelFormat.kChannelFormatByte: case VertexChannelFormat.Byte:
return VertexFormat.kVertexFormatUInt8; return VertexFormat.UInt8;
case VertexChannelFormat.kChannelFormatUInt32: //in 5.x case VertexChannelFormat.UInt32: //in 5.x
return VertexFormat.kVertexFormatUInt32; return VertexFormat.UInt32;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
} }
@@ -1257,31 +1262,31 @@ namespace AssetStudio
{ {
switch ((VertexFormat2017)format) switch ((VertexFormat2017)format)
{ {
case VertexFormat2017.kVertexFormatFloat: case VertexFormat2017.Float:
return VertexFormat.kVertexFormatFloat; return VertexFormat.Float;
case VertexFormat2017.kVertexFormatFloat16: case VertexFormat2017.Float16:
return VertexFormat.kVertexFormatFloat16; return VertexFormat.Float16;
case VertexFormat2017.kVertexFormatColor: case VertexFormat2017.Color:
case VertexFormat2017.kVertexFormatUNorm8: case VertexFormat2017.UNorm8:
return VertexFormat.kVertexFormatUNorm8; return VertexFormat.UNorm8;
case VertexFormat2017.kVertexFormatSNorm8: case VertexFormat2017.SNorm8:
return VertexFormat.kVertexFormatSNorm8; return VertexFormat.SNorm8;
case VertexFormat2017.kVertexFormatUNorm16: case VertexFormat2017.UNorm16:
return VertexFormat.kVertexFormatUNorm16; return VertexFormat.UNorm16;
case VertexFormat2017.kVertexFormatSNorm16: case VertexFormat2017.SNorm16:
return VertexFormat.kVertexFormatSNorm16; return VertexFormat.SNorm16;
case VertexFormat2017.kVertexFormatUInt8: case VertexFormat2017.UInt8:
return VertexFormat.kVertexFormatUInt8; return VertexFormat.UInt8;
case VertexFormat2017.kVertexFormatSInt8: case VertexFormat2017.SInt8:
return VertexFormat.kVertexFormatSInt8; return VertexFormat.SInt8;
case VertexFormat2017.kVertexFormatUInt16: case VertexFormat2017.UInt16:
return VertexFormat.kVertexFormatUInt16; return VertexFormat.UInt16;
case VertexFormat2017.kVertexFormatSInt16: case VertexFormat2017.SInt16:
return VertexFormat.kVertexFormatSInt16; return VertexFormat.SInt16;
case VertexFormat2017.kVertexFormatUInt32: case VertexFormat2017.UInt32:
return VertexFormat.kVertexFormatUInt32; return VertexFormat.UInt32;
case VertexFormat2017.kVertexFormatSInt32: case VertexFormat2017.SInt32:
return VertexFormat.kVertexFormatSInt32; return VertexFormat.SInt32;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
} }
@@ -1297,20 +1302,20 @@ namespace AssetStudio
{ {
switch (format) switch (format)
{ {
case VertexFormat.kVertexFormatFloat: case VertexFormat.Float:
case VertexFormat.kVertexFormatUInt32: case VertexFormat.UInt32:
case VertexFormat.kVertexFormatSInt32: case VertexFormat.SInt32:
return 4u; return 4u;
case VertexFormat.kVertexFormatFloat16: case VertexFormat.Float16:
case VertexFormat.kVertexFormatUNorm16: case VertexFormat.UNorm16:
case VertexFormat.kVertexFormatSNorm16: case VertexFormat.SNorm16:
case VertexFormat.kVertexFormatUInt16: case VertexFormat.UInt16:
case VertexFormat.kVertexFormatSInt16: case VertexFormat.SInt16:
return 2u; return 2u;
case VertexFormat.kVertexFormatUNorm8: case VertexFormat.UNorm8:
case VertexFormat.kVertexFormatSNorm8: case VertexFormat.SNorm8:
case VertexFormat.kVertexFormatUInt8: case VertexFormat.UInt8:
case VertexFormat.kVertexFormatSInt8: case VertexFormat.SInt8:
return 1u; return 1u;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
@@ -1319,7 +1324,7 @@ namespace AssetStudio
public static bool IsIntFormat(VertexFormat format) public static bool IsIntFormat(VertexFormat format)
{ {
return format >= VertexFormat.kVertexFormatUInt8; return format >= VertexFormat.UInt8;
} }
public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format) public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
@@ -1331,22 +1336,22 @@ namespace AssetStudio
{ {
switch (format) switch (format)
{ {
case VertexFormat.kVertexFormatFloat: case VertexFormat.Float:
result[i] = BitConverter.ToSingle(inputBytes, i * 4); result[i] = BitConverter.ToSingle(inputBytes, i * 4);
break; break;
case VertexFormat.kVertexFormatFloat16: case VertexFormat.Float16:
result[i] = Half.ToHalf(inputBytes, i * 2); result[i] = Half.ToHalf(inputBytes, i * 2);
break; break;
case VertexFormat.kVertexFormatUNorm8: case VertexFormat.UNorm8:
result[i] = inputBytes[i] / 255f; result[i] = inputBytes[i] / 255f;
break; break;
case VertexFormat.kVertexFormatSNorm8: case VertexFormat.SNorm8:
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f); result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
break; break;
case VertexFormat.kVertexFormatUNorm16: case VertexFormat.UNorm16:
result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f; result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
break; break;
case VertexFormat.kVertexFormatSNorm16: case VertexFormat.SNorm16:
result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f); result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
break; break;
} }
@@ -1363,16 +1368,16 @@ namespace AssetStudio
{ {
switch (format) switch (format)
{ {
case VertexFormat.kVertexFormatUInt8: case VertexFormat.UInt8:
case VertexFormat.kVertexFormatSInt8: case VertexFormat.SInt8:
result[i] = inputBytes[i]; result[i] = inputBytes[i];
break; break;
case VertexFormat.kVertexFormatUInt16: case VertexFormat.UInt16:
case VertexFormat.kVertexFormatSInt16: case VertexFormat.SInt16:
result[i] = BitConverter.ToInt16(inputBytes, i * 2); result[i] = BitConverter.ToInt16(inputBytes, i * 2);
break; break;
case VertexFormat.kVertexFormatUInt32: case VertexFormat.UInt32:
case VertexFormat.kVertexFormatSInt32: case VertexFormat.SInt32:
result[i] = BitConverter.ToInt32(inputBytes, i * 4); result[i] = BitConverter.ToInt32(inputBytes, i * 4);
break; break;
} }
+1 -1
View File
@@ -13,7 +13,7 @@ namespace AssetStudio
public PPtr(ObjectReader reader) public PPtr(ObjectReader reader)
{ {
m_FileID = reader.ReadInt32(); m_FileID = reader.ReadInt32();
m_PathID = reader.m_Version < SerializedFileFormatVersion.kUnknown_14 ? reader.ReadInt32() : reader.ReadInt64(); m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();
assetsFile = reader.assetsFile; assetsFile = reader.assetsFile;
} }
+103 -92
View File
@@ -56,15 +56,14 @@ namespace AssetStudio
} }
public enum TextureDimension public enum TextureDimension
{ {
kTexDimUnknown = -1, Unknown = -1,
kTexDimNone = 0, None = 0,
kTexDimAny = 1, Any = 1,
kTexDim2D = 2, Tex2D = 2,
kTexDim3D = 3, Tex3D = 3,
kTexDimCUBE = 4, Cube = 4,
kTexDim2DArray = 5, Tex2DArray = 5,
kTexDimCubeArray = 6, CubeArray = 6
kTexDimForce32Bit = 2147483647
}; };
public class SerializedTextureProperty public class SerializedTextureProperty
@@ -81,11 +80,12 @@ namespace AssetStudio
public enum SerializedPropertyType public enum SerializedPropertyType
{ {
kColor = 0, Color = 0,
kVector = 1, Vector = 1,
kFloat = 2, Float = 2,
kRange = 3, Range = 3,
kTexture = 4 Texture = 4,
Int = 5
}; };
public class SerializedProperty public class SerializedProperty
@@ -195,11 +195,11 @@ namespace AssetStudio
public enum FogMode public enum FogMode
{ {
kFogUnknown = -1, Unknown = -1,
kFogDisabled = 0, Disabled = 0,
kFogLinear = 1, Linear = 1,
kFogExp = 2, Exp = 2,
kFogExp2 = 3 Exp2 = 3
}; };
public class SerializedShaderState public class SerializedShaderState
@@ -428,6 +428,7 @@ namespace AssetStudio
if ((version[0] == 2020 && version[1] > 3) || if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up (version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
{ {
@@ -453,38 +454,39 @@ namespace AssetStudio
public enum ShaderGpuProgramType public enum ShaderGpuProgramType
{ {
kShaderGpuProgramUnknown = 0, Unknown = 0,
kShaderGpuProgramGLLegacy = 1, GLLegacy = 1,
kShaderGpuProgramGLES31AEP = 2, GLES31AEP = 2,
kShaderGpuProgramGLES31 = 3, GLES31 = 3,
kShaderGpuProgramGLES3 = 4, GLES3 = 4,
kShaderGpuProgramGLES = 5, GLES = 5,
kShaderGpuProgramGLCore32 = 6, GLCore32 = 6,
kShaderGpuProgramGLCore41 = 7, GLCore41 = 7,
kShaderGpuProgramGLCore43 = 8, GLCore43 = 8,
kShaderGpuProgramDX9VertexSM20 = 9, DX9VertexSM20 = 9,
kShaderGpuProgramDX9VertexSM30 = 10, DX9VertexSM30 = 10,
kShaderGpuProgramDX9PixelSM20 = 11, DX9PixelSM20 = 11,
kShaderGpuProgramDX9PixelSM30 = 12, DX9PixelSM30 = 12,
kShaderGpuProgramDX10Level9Vertex = 13, DX10Level9Vertex = 13,
kShaderGpuProgramDX10Level9Pixel = 14, DX10Level9Pixel = 14,
kShaderGpuProgramDX11VertexSM40 = 15, DX11VertexSM40 = 15,
kShaderGpuProgramDX11VertexSM50 = 16, DX11VertexSM50 = 16,
kShaderGpuProgramDX11PixelSM40 = 17, DX11PixelSM40 = 17,
kShaderGpuProgramDX11PixelSM50 = 18, DX11PixelSM50 = 18,
kShaderGpuProgramDX11GeometrySM40 = 19, DX11GeometrySM40 = 19,
kShaderGpuProgramDX11GeometrySM50 = 20, DX11GeometrySM50 = 20,
kShaderGpuProgramDX11HullSM50 = 21, DX11HullSM50 = 21,
kShaderGpuProgramDX11DomainSM50 = 22, DX11DomainSM50 = 22,
kShaderGpuProgramMetalVS = 23, MetalVS = 23,
kShaderGpuProgramMetalFS = 24, MetalFS = 24,
kShaderGpuProgramSPIRV = 25, SPIRV = 25,
kShaderGpuProgramConsoleVS = 26, ConsoleVS = 26,
kShaderGpuProgramConsoleFS = 27, ConsoleFS = 27,
kShaderGpuProgramConsoleHS = 28, ConsoleHS = 28,
kShaderGpuProgramConsoleDS = 29, ConsoleDS = 29,
kShaderGpuProgramConsoleGS = 30, ConsoleGS = 30,
kShaderGpuProgramRayTracing = 31, RayTracing = 31,
PS5NGGC = 32
}; };
public class SerializedProgramParameters public class SerializedProgramParameters
@@ -604,8 +606,9 @@ namespace AssetStudio
if ((version[0] == 2020 && version[1] > 3) || if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
{ {
m_Parameters = new SerializedProgramParameters(reader); m_Parameters = new SerializedProgramParameters(reader);
} }
@@ -689,6 +692,7 @@ namespace AssetStudio
{ {
public SerializedSubProgram[] m_SubPrograms; public SerializedSubProgram[] m_SubPrograms;
public SerializedProgramParameters m_CommonParameters; public SerializedProgramParameters m_CommonParameters;
public ushort[] m_SerializedKeywordStateMask;
public SerializedProgram(ObjectReader reader) public SerializedProgram(ObjectReader reader)
{ {
@@ -703,19 +707,26 @@ namespace AssetStudio
if ((version[0] == 2020 && version[1] > 3) || if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
{ {
m_CommonParameters = new SerializedProgramParameters(reader); m_CommonParameters = new SerializedProgramParameters(reader);
} }
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
}
} }
} }
public enum PassType public enum PassType
{ {
kPassTypeNormal = 0, Normal = 0,
kPassTypeUse = 1, Use = 1,
kPassTypeGrab = 2 Grab = 2
}; };
public class SerializedPass public class SerializedPass
@@ -794,7 +805,7 @@ namespace AssetStudio
m_Name = reader.ReadAlignedString(); m_Name = reader.ReadAlignedString();
m_TextureName = reader.ReadAlignedString(); m_TextureName = reader.ReadAlignedString();
m_Tags = new SerializedTagMap(reader); m_Tags = new SerializedTagMap(reader);
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x
{ {
m_SerializedKeywordStateMask = reader.ReadUInt16Array(); m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream(); reader.AlignStream();
@@ -922,32 +933,32 @@ namespace AssetStudio
public enum ShaderCompilerPlatform public enum ShaderCompilerPlatform
{ {
kShaderCompPlatformNone = -1, None = -1,
kShaderCompPlatformGL = 0, GL = 0,
kShaderCompPlatformD3D9 = 1, D3D9 = 1,
kShaderCompPlatformXbox360 = 2, Xbox360 = 2,
kShaderCompPlatformPS3 = 3, PS3 = 3,
kShaderCompPlatformD3D11 = 4, D3D11 = 4,
kShaderCompPlatformGLES20 = 5, GLES20 = 5,
kShaderCompPlatformNaCl = 6, NaCl = 6,
kShaderCompPlatformFlash = 7, Flash = 7,
kShaderCompPlatformD3D11_9x = 8, D3D11_9x = 8,
kShaderCompPlatformGLES3Plus = 9, GLES3Plus = 9,
kShaderCompPlatformPSP2 = 10, PSP2 = 10,
kShaderCompPlatformPS4 = 11, PS4 = 11,
kShaderCompPlatformXboxOne = 12, XboxOne = 12,
kShaderCompPlatformPSM = 13, PSM = 13,
kShaderCompPlatformMetal = 14, Metal = 14,
kShaderCompPlatformOpenGLCore = 15, OpenGLCore = 15,
kShaderCompPlatformN3DS = 16, N3DS = 16,
kShaderCompPlatformWiiU = 17, WiiU = 17,
kShaderCompPlatformVulkan = 18, Vulkan = 18,
kShaderCompPlatformSwitch = 19, Switch = 19,
kShaderCompPlatformXboxOneD3D12 = 20, XboxOneD3D12 = 20,
kShaderCompPlatformGameCoreXboxOne = 21, GameCoreXboxOne = 21,
kShaderCompPlatformGameCoreScarlett = 22, GameCoreScarlett = 22,
kShaderCompPlatformPS5 = 23, PS5 = 23,
kShaderCompPlatformPS5NGGC = 24, PS5NGGC = 24
}; };
public class Shader : NamedObject public class Shader : NamedObject
@@ -959,9 +970,9 @@ namespace AssetStudio
//5.5 and up //5.5 and up
public SerializedShader m_ParsedForm; public SerializedShader m_ParsedForm;
public ShaderCompilerPlatform[] platforms; public ShaderCompilerPlatform[] platforms;
public uint[] offsets; public uint[][] offsets;
public uint[] compressedLengths; public uint[][] compressedLengths;
public uint[] decompressedLengths; public uint[][] decompressedLengths;
public byte[] compressedBlob; public byte[] compressedBlob;
public Shader(ObjectReader reader) : base(reader) public Shader(ObjectReader reader) : base(reader)
@@ -972,15 +983,15 @@ namespace AssetStudio
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray(); platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{ {
offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); offsets = reader.ReadUInt32ArrayArray();
compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); compressedLengths = reader.ReadUInt32ArrayArray();
decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); decompressedLengths = reader.ReadUInt32ArrayArray();
} }
else else
{ {
offsets = reader.ReadUInt32Array(); offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
compressedLengths = reader.ReadUInt32Array(); compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
decompressedLengths = reader.ReadUInt32Array(); decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
} }
compressedBlob = reader.ReadUInt8Array(); compressedBlob = reader.ReadUInt8Array();
reader.AlignStream(); reader.AlignStream();
+9 -9
View File
@@ -18,23 +18,23 @@ namespace AssetStudio
public enum SpritePackingRotation public enum SpritePackingRotation
{ {
kSPRNone = 0, None = 0,
kSPRFlipHorizontal = 1, FlipHorizontal = 1,
kSPRFlipVertical = 2, FlipVertical = 2,
kSPRRotate180 = 3, Rotate180 = 3,
kSPRRotate90 = 4 Rotate90 = 4
}; };
public enum SpritePackingMode public enum SpritePackingMode
{ {
kSPMTight = 0, Tight = 0,
kSPMRectangle Rectangle
}; };
public enum SpriteMeshType public enum SpriteMeshType
{ {
kSpriteMeshTypeFullRect, FullRect,
kSpriteMeshTypeTight Tight
}; };
public class SpriteSettings public class SpriteSettings
+11 -7
View File
@@ -151,10 +151,13 @@ namespace AssetStudio
RGB24, RGB24,
RGBA32, RGBA32,
ARGB32, ARGB32,
RGB565 = 7, ARGBFloat,
R16 = 9, RGB565,
BGR24,
R16,
DXT1, DXT1,
DXT5 = 12, DXT3,
DXT5,
RGBA4444, RGBA4444,
BGRA32, BGRA32,
RHalf, RHalf,
@@ -165,11 +168,12 @@ namespace AssetStudio
RGBAFloat, RGBAFloat,
YUY2, YUY2,
RGB9e5Float, RGB9e5Float,
BC4 = 26, RGBFloat,
BC5, BC6H,
BC6H = 24,
BC7, BC7,
DXT1Crunched = 28, BC4,
BC5,
DXT1Crunched,
DXT5Crunched, DXT5Crunched,
PVRTC_RGB2, PVRTC_RGB2,
PVRTC_RGBA2, PVRTC_RGBA2,
+8 -5
View File
@@ -11,6 +11,8 @@ namespace AssetStudio
private static readonly byte[] gzipMagic = { 0x1f, 0x8b }; private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 }; private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 };
private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 };
public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
@@ -36,7 +38,7 @@ namespace AssetStudio
return FileType.WebFile; return FileType.WebFile;
default: default:
{ {
var magic = ReadBytes(2); byte[] magic = ReadBytes(2);
Position = 0; Position = 0;
if (gzipMagic.SequenceEqual(magic)) if (gzipMagic.SequenceEqual(magic))
{ {
@@ -53,10 +55,11 @@ namespace AssetStudio
{ {
return FileType.AssetsFile; return FileType.AssetsFile;
} }
else magic = ReadBytes(4);
{ Position = 0;
return FileType.ResourceFile; if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
} return FileType.ZipFile;
return FileType.ResourceFile;
} }
} }
} }
+2 -1
View File
@@ -13,6 +13,7 @@ namespace AssetStudio
WebFile, WebFile,
ResourceFile, ResourceFile,
GZipFile, GZipFile,
BrotliFile BrotliFile,
ZipFile
} }
} }
+22
View File
@@ -73,6 +73,28 @@ namespace AssetStudio
return null; return null;
} }
public ImportedFrame FindRelativeFrameWithPath(string path)
{
var subs = path.Split(new[] { '/' }, 2);
foreach (var child in children)
{
if (child.Name == subs[0])
{
if (subs.Length == 1)
{
return child;
}
else
{
var result = child.FindRelativeFrameWithPath(subs[1]);
if (result != null)
return result;
}
}
}
return null;
}
public ImportedFrame FindFrame(string name) public ImportedFrame FindFrame(string name)
{ {
if (Name == name) if (Name == name)
-17
View File
@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public interface IProgress
{
void Report(int value);
}
public sealed class DummyProgress : IProgress
{
public void Report(int value) { }
}
}
+4 -2
View File
@@ -1,8 +1,10 @@
namespace AssetStudio using System;
namespace AssetStudio
{ {
public static class Progress public static class Progress
{ {
public static IProgress Default = new DummyProgress(); public static IProgress<int> Default = new Progress<int>();
private static int preValue; private static int preValue;
public static void Reset() public static void Reset()
+28 -28
View File
@@ -45,7 +45,7 @@ namespace AssetStudio
header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32(); header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32();
header.m_DataOffset = reader.ReadUInt32(); header.m_DataOffset = reader.ReadUInt32();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_9) if (header.m_Version >= SerializedFileFormatVersion.Unknown_9)
{ {
header.m_Endianess = reader.ReadByte(); header.m_Endianess = reader.ReadByte();
header.m_Reserved = reader.ReadBytes(3); header.m_Reserved = reader.ReadBytes(3);
@@ -57,7 +57,7 @@ namespace AssetStudio
m_FileEndianess = reader.ReadByte(); m_FileEndianess = reader.ReadByte();
} }
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport) if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
{ {
header.m_MetadataSize = reader.ReadUInt32(); header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadInt64(); header.m_FileSize = reader.ReadInt64();
@@ -70,12 +70,12 @@ namespace AssetStudio
{ {
reader.Endian = EndianType.LittleEndian; reader.Endian = EndianType.LittleEndian;
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7) if (header.m_Version >= SerializedFileFormatVersion.Unknown_7)
{ {
unityVersion = reader.ReadStringToNull(); unityVersion = reader.ReadStringToNull();
SetVersion(unityVersion); SetVersion(unityVersion);
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_8) if (header.m_Version >= SerializedFileFormatVersion.Unknown_8)
{ {
m_TargetPlatform = (BuildTarget)reader.ReadInt32(); m_TargetPlatform = (BuildTarget)reader.ReadInt32();
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform)) if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
@@ -83,7 +83,7 @@ namespace AssetStudio
m_TargetPlatform = BuildTarget.UnknownPlatform; m_TargetPlatform = BuildTarget.UnknownPlatform;
} }
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes) if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
{ {
m_EnableTypeTree = reader.ReadBoolean(); m_EnableTypeTree = reader.ReadBoolean();
} }
@@ -96,7 +96,7 @@ namespace AssetStudio
m_Types.Add(ReadSerializedType(false)); m_Types.Add(ReadSerializedType(false));
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7 && header.m_Version < SerializedFileFormatVersion.kUnknown_14) if (header.m_Version >= SerializedFileFormatVersion.Unknown_7 && header.m_Version < SerializedFileFormatVersion.Unknown_14)
{ {
bigIDEnabled = reader.ReadInt32(); bigIDEnabled = reader.ReadInt32();
} }
@@ -113,7 +113,7 @@ namespace AssetStudio
{ {
objectInfo.m_PathID = reader.ReadInt64(); objectInfo.m_PathID = reader.ReadInt64();
} }
else if (header.m_Version < SerializedFileFormatVersion.kUnknown_14) else if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
{ {
objectInfo.m_PathID = reader.ReadInt32(); objectInfo.m_PathID = reader.ReadInt32();
} }
@@ -123,7 +123,7 @@ namespace AssetStudio
objectInfo.m_PathID = reader.ReadInt64(); objectInfo.m_PathID = reader.ReadInt64();
} }
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport) if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
objectInfo.byteStart = reader.ReadInt64(); objectInfo.byteStart = reader.ReadInt64();
else else
objectInfo.byteStart = reader.ReadUInt32(); objectInfo.byteStart = reader.ReadUInt32();
@@ -131,7 +131,7 @@ namespace AssetStudio
objectInfo.byteStart += header.m_DataOffset; objectInfo.byteStart += header.m_DataOffset;
objectInfo.byteSize = reader.ReadUInt32(); objectInfo.byteSize = reader.ReadUInt32();
objectInfo.typeID = reader.ReadInt32(); objectInfo.typeID = reader.ReadInt32();
if (header.m_Version < SerializedFileFormatVersion.kRefactoredClassId) if (header.m_Version < SerializedFileFormatVersion.RefactoredClassId)
{ {
objectInfo.classID = reader.ReadUInt16(); objectInfo.classID = reader.ReadUInt16();
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID); objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
@@ -142,24 +142,24 @@ namespace AssetStudio
objectInfo.serializedType = type; objectInfo.serializedType = type;
objectInfo.classID = type.classID; objectInfo.classID = type.classID;
} }
if (header.m_Version < SerializedFileFormatVersion.kHasScriptTypeIndex) if (header.m_Version < SerializedFileFormatVersion.HasScriptTypeIndex)
{ {
objectInfo.isDestroyed = reader.ReadUInt16(); objectInfo.isDestroyed = reader.ReadUInt16();
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.kRefactorTypeData) if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.RefactorTypeData)
{ {
var m_ScriptTypeIndex = reader.ReadInt16(); var m_ScriptTypeIndex = reader.ReadInt16();
if (objectInfo.serializedType != null) if (objectInfo.serializedType != null)
objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex; objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;
} }
if (header.m_Version == SerializedFileFormatVersion.kSupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.kRefactoredClassId) if (header.m_Version == SerializedFileFormatVersion.SupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.RefactoredClassId)
{ {
objectInfo.stripped = reader.ReadByte(); objectInfo.stripped = reader.ReadByte();
} }
m_Objects.Add(objectInfo); m_Objects.Add(objectInfo);
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex) if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex)
{ {
int scriptCount = reader.ReadInt32(); int scriptCount = reader.ReadInt32();
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount); m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
@@ -167,7 +167,7 @@ namespace AssetStudio
{ {
var m_ScriptType = new LocalSerializedObjectIdentifier(); var m_ScriptType = new LocalSerializedObjectIdentifier();
m_ScriptType.localSerializedFileIndex = reader.ReadInt32(); m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
if (header.m_Version < SerializedFileFormatVersion.kUnknown_14) if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
{ {
m_ScriptType.localIdentifierInFile = reader.ReadInt32(); m_ScriptType.localIdentifierInFile = reader.ReadInt32();
} }
@@ -185,11 +185,11 @@ namespace AssetStudio
for (int i = 0; i < externalsCount; i++) for (int i = 0; i < externalsCount; i++)
{ {
var m_External = new FileIdentifier(); var m_External = new FileIdentifier();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_6) if (header.m_Version >= SerializedFileFormatVersion.Unknown_6)
{ {
var tempEmpty = reader.ReadStringToNull(); var tempEmpty = reader.ReadStringToNull();
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5) if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)
{ {
m_External.guid = new Guid(reader.ReadBytes(16)); m_External.guid = new Guid(reader.ReadBytes(16));
m_External.type = reader.ReadInt32(); m_External.type = reader.ReadInt32();
@@ -199,7 +199,7 @@ namespace AssetStudio
m_Externals.Add(m_External); m_Externals.Add(m_External);
} }
if (header.m_Version >= SerializedFileFormatVersion.kSupportsRefObject) if (header.m_Version >= SerializedFileFormatVersion.SupportsRefObject)
{ {
int refTypesCount = reader.ReadInt32(); int refTypesCount = reader.ReadInt32();
m_RefTypes = new List<SerializedType>(refTypesCount); m_RefTypes = new List<SerializedType>(refTypesCount);
@@ -209,7 +209,7 @@ namespace AssetStudio
} }
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5) if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)
{ {
userInformation = reader.ReadStringToNull(); userInformation = reader.ReadStringToNull();
} }
@@ -235,23 +235,23 @@ namespace AssetStudio
type.classID = reader.ReadInt32(); type.classID = reader.ReadInt32();
if (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId) if (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId)
{ {
type.m_IsStrippedType = reader.ReadBoolean(); type.m_IsStrippedType = reader.ReadBoolean();
} }
if (header.m_Version >= SerializedFileFormatVersion.kRefactorTypeData) if (header.m_Version >= SerializedFileFormatVersion.RefactorTypeData)
{ {
type.m_ScriptTypeIndex = reader.ReadInt16(); type.m_ScriptTypeIndex = reader.ReadInt16();
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes) if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
{ {
if (isRefType && type.m_ScriptTypeIndex >= 0) if (isRefType && type.m_ScriptTypeIndex >= 0)
{ {
type.m_ScriptID = reader.ReadBytes(16); type.m_ScriptID = reader.ReadBytes(16);
} }
else if ((header.m_Version < SerializedFileFormatVersion.kRefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId && type.classID == 114)) else if ((header.m_Version < SerializedFileFormatVersion.RefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId && type.classID == 114))
{ {
type.m_ScriptID = reader.ReadBytes(16); type.m_ScriptID = reader.ReadBytes(16);
} }
@@ -262,7 +262,7 @@ namespace AssetStudio
{ {
type.m_Type = new TypeTree(); type.m_Type = new TypeTree();
type.m_Type.m_Nodes = new List<TypeTreeNode>(); type.m_Type.m_Nodes = new List<TypeTreeNode>();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_12 || header.m_Version == SerializedFileFormatVersion.kUnknown_10) if (header.m_Version >= SerializedFileFormatVersion.Unknown_12 || header.m_Version == SerializedFileFormatVersion.Unknown_10)
{ {
TypeTreeBlobRead(type.m_Type); TypeTreeBlobRead(type.m_Type);
} }
@@ -270,7 +270,7 @@ namespace AssetStudio
{ {
ReadTypeTree(type.m_Type); ReadTypeTree(type.m_Type);
} }
if (header.m_Version >= SerializedFileFormatVersion.kStoresTypeDependencies) if (header.m_Version >= SerializedFileFormatVersion.StoresTypeDependencies)
{ {
if (isRefType) if (isRefType)
{ {
@@ -296,17 +296,17 @@ namespace AssetStudio
typeTreeNode.m_Type = reader.ReadStringToNull(); typeTreeNode.m_Type = reader.ReadStringToNull();
typeTreeNode.m_Name = reader.ReadStringToNull(); typeTreeNode.m_Name = reader.ReadStringToNull();
typeTreeNode.m_ByteSize = reader.ReadInt32(); typeTreeNode.m_ByteSize = reader.ReadInt32();
if (header.m_Version == SerializedFileFormatVersion.kUnknown_2) if (header.m_Version == SerializedFileFormatVersion.Unknown_2)
{ {
var variableCount = reader.ReadInt32(); var variableCount = reader.ReadInt32();
} }
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3) if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
{ {
typeTreeNode.m_Index = reader.ReadInt32(); typeTreeNode.m_Index = reader.ReadInt32();
} }
typeTreeNode.m_TypeFlags = reader.ReadInt32(); typeTreeNode.m_TypeFlags = reader.ReadInt32();
typeTreeNode.m_Version = reader.ReadInt32(); typeTreeNode.m_Version = reader.ReadInt32();
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3) if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
{ {
typeTreeNode.m_MetaFlag = reader.ReadInt32(); typeTreeNode.m_MetaFlag = reader.ReadInt32();
} }
@@ -334,7 +334,7 @@ namespace AssetStudio
typeTreeNode.m_ByteSize = reader.ReadInt32(); typeTreeNode.m_ByteSize = reader.ReadInt32();
typeTreeNode.m_Index = reader.ReadInt32(); typeTreeNode.m_Index = reader.ReadInt32();
typeTreeNode.m_MetaFlag = reader.ReadInt32(); typeTreeNode.m_MetaFlag = reader.ReadInt32();
if (header.m_Version >= SerializedFileFormatVersion.kTypeTreeNodeWithTypeFlags) if (header.m_Version >= SerializedFileFormatVersion.TypeTreeNodeWithTypeFlags)
{ {
typeTreeNode.m_RefTypeHash = reader.ReadUInt64(); typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
} }
+21 -21
View File
@@ -8,80 +8,80 @@ namespace AssetStudio
{ {
public enum SerializedFileFormatVersion public enum SerializedFileFormatVersion
{ {
kUnsupported = 1, Unsupported = 1,
kUnknown_2 = 2, Unknown_2 = 2,
kUnknown_3 = 3, Unknown_3 = 3,
/// <summary> /// <summary>
/// 1.2.0 to 2.0.0 /// 1.2.0 to 2.0.0
/// </summary> /// </summary>
kUnknown_5 = 5, Unknown_5 = 5,
/// <summary> /// <summary>
/// 2.1.0 to 2.6.1 /// 2.1.0 to 2.6.1
/// </summary> /// </summary>
kUnknown_6 = 6, Unknown_6 = 6,
/// <summary> /// <summary>
/// 3.0.0b /// 3.0.0b
/// </summary> /// </summary>
kUnknown_7 = 7, Unknown_7 = 7,
/// <summary> /// <summary>
/// 3.0.0 to 3.4.2 /// 3.0.0 to 3.4.2
/// </summary> /// </summary>
kUnknown_8 = 8, Unknown_8 = 8,
/// <summary> /// <summary>
/// 3.5.0 to 4.7.2 /// 3.5.0 to 4.7.2
/// </summary> /// </summary>
kUnknown_9 = 9, Unknown_9 = 9,
/// <summary> /// <summary>
/// 5.0.0aunk1 /// 5.0.0aunk1
/// </summary> /// </summary>
kUnknown_10 = 10, Unknown_10 = 10,
/// <summary> /// <summary>
/// 5.0.0aunk2 /// 5.0.0aunk2
/// </summary> /// </summary>
kHasScriptTypeIndex = 11, HasScriptTypeIndex = 11,
/// <summary> /// <summary>
/// 5.0.0aunk3 /// 5.0.0aunk3
/// </summary> /// </summary>
kUnknown_12 = 12, Unknown_12 = 12,
/// <summary> /// <summary>
/// 5.0.0aunk4 /// 5.0.0aunk4
/// </summary> /// </summary>
kHasTypeTreeHashes = 13, HasTypeTreeHashes = 13,
/// <summary> /// <summary>
/// 5.0.0unk /// 5.0.0unk
/// </summary> /// </summary>
kUnknown_14 = 14, Unknown_14 = 14,
/// <summary> /// <summary>
/// 5.0.1 to 5.4.0 /// 5.0.1 to 5.4.0
/// </summary> /// </summary>
kSupportsStrippedObject = 15, SupportsStrippedObject = 15,
/// <summary> /// <summary>
/// 5.5.0a /// 5.5.0a
/// </summary> /// </summary>
kRefactoredClassId = 16, RefactoredClassId = 16,
/// <summary> /// <summary>
/// 5.5.0unk to 2018.4 /// 5.5.0unk to 2018.4
/// </summary> /// </summary>
kRefactorTypeData = 17, RefactorTypeData = 17,
/// <summary> /// <summary>
/// 2019.1a /// 2019.1a
/// </summary> /// </summary>
kRefactorShareableTypeTreeData = 18, RefactorShareableTypeTreeData = 18,
/// <summary> /// <summary>
/// 2019.1unk /// 2019.1unk
/// </summary> /// </summary>
kTypeTreeNodeWithTypeFlags = 19, TypeTreeNodeWithTypeFlags = 19,
/// <summary> /// <summary>
/// 2019.2 /// 2019.2
/// </summary> /// </summary>
kSupportsRefObject = 20, SupportsRefObject = 20,
/// <summary> /// <summary>
/// 2019.3 to 2019.4 /// 2019.3 to 2019.4
/// </summary> /// </summary>
kStoresTypeDependencies = 21, StoresTypeDependencies = 21,
/// <summary> /// <summary>
/// 2020.1 to x /// 2020.1 to x
/// </summary> /// </summary>
kLargeFilesSupport = 22 LargeFilesSupport = 22
} }
} }
+12 -5
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Text; using System.Text;
@@ -39,9 +40,11 @@ namespace AssetStudio
value = reader.ReadSByte(); value = reader.ReadSByte();
break; break;
case "UInt8": case "UInt8":
case "char":
value = reader.ReadByte(); value = reader.ReadByte();
break; break;
case "char":
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
break;
case "short": case "short":
case "SInt16": case "SInt16":
value = reader.ReadInt16(); value = reader.ReadInt16();
@@ -81,7 +84,8 @@ namespace AssetStudio
append = false; append = false;
var str = reader.ReadAlignedString(); var str = reader.ReadAlignedString();
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str); sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
i += 3; var toSkip = GetNodes(m_Nodes, i);
i += toSkip.Count - 1;
break; break;
case "map": case "map":
{ {
@@ -190,9 +194,11 @@ namespace AssetStudio
value = reader.ReadSByte(); value = reader.ReadSByte();
break; break;
case "UInt8": case "UInt8":
case "char":
value = reader.ReadByte(); value = reader.ReadByte();
break; break;
case "char":
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
break;
case "short": case "short":
case "SInt16": case "SInt16":
value = reader.ReadInt16(); value = reader.ReadInt16();
@@ -230,7 +236,8 @@ namespace AssetStudio
break; break;
case "string": case "string":
value = reader.ReadAlignedString(); value = reader.ReadAlignedString();
i += 3; var toSkip = GetNodes(m_Nodes, i);
i += toSkip.Count - 1;
break; break;
case "map": case "map":
{ {
@@ -6,7 +6,8 @@
<Version>0.16.0.0</Version> <Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion> <AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion> <FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021; Copyright © hozuki 2020</Copyright> <Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+2 -1
View File
@@ -8,7 +8,8 @@
<Version>0.16.0.0</Version> <Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion> <AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion> <FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright> <Copyright>Copyright © Perfare 2018-2022</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+40 -37
View File
@@ -107,7 +107,7 @@ namespace AssetStudioGUI
logger = new GUILogger(StatusStripUpdate); logger = new GUILogger(StatusStripUpdate);
Logger.Default = logger; Logger.Default = logger;
Progress.Default = new GUIProgress(SetProgressBarValue); Progress.Default = new Progress<int>(SetProgressBarValue);
Studio.StatusStripUpdate = StatusStripUpdate; Studio.StatusStripUpdate = StatusStripUpdate;
} }
@@ -141,7 +141,7 @@ namespace AssetStudioGUI
private async void loadFile_Click(object sender, EventArgs e) private async void loadFile_Click(object sender, EventArgs e)
{ {
openFileDialog1.InitialDirectory = openDirectoryBackup; openFileDialog1.InitialDirectory = openDirectoryBackup;
if (openFileDialog1.ShowDialog() == DialogResult.OK) if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{ {
ResetForm(); ResetForm();
openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]); openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
@@ -167,7 +167,7 @@ namespace AssetStudioGUI
private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e) private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e)
{ {
if (openFileDialog1.ShowDialog() == DialogResult.OK) if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{ {
var saveFolderDialog = new OpenFolderDialog(); var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.Title = "Select the save folder"; saveFolderDialog.Title = "Select the save folder";
@@ -222,10 +222,6 @@ namespace AssetStudioGUI
sceneTreeView.BeginUpdate(); sceneTreeView.BeginUpdate();
sceneTreeView.Nodes.AddRange(treeNodeCollection.ToArray()); sceneTreeView.Nodes.AddRange(treeNodeCollection.ToArray());
foreach (var node in treeNodeCollection)
{
node.HideCheckBox();
}
sceneTreeView.EndUpdate(); sceneTreeView.EndUpdate();
treeNodeCollection.Clear(); treeNodeCollection.Clear();
@@ -461,7 +457,7 @@ namespace AssetStudioGUI
private void showExpOpt_Click(object sender, EventArgs e) private void showExpOpt_Click(object sender, EventArgs e)
{ {
var exportOpt = new ExportOptions(); var exportOpt = new ExportOptions();
exportOpt.ShowDialog(); exportOpt.ShowDialog(this);
} }
private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
@@ -759,7 +755,7 @@ namespace AssetStudioGUI
var image = m_Texture2D.ConvertToImage(true); var image = m_Texture2D.ConvertToImage(true);
if (image != null) if (image != null)
{ {
var bitmap = new DirectBitmap(image.ConvertToBgra32Bytes(), m_Texture2D.m_Width, m_Texture2D.m_Height); var bitmap = new DirectBitmap(image.ConvertToBytes(), m_Texture2D.m_Width, m_Texture2D.m_Height);
image.Dispose(); image.Dispose();
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}"; assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
switch (m_Texture2D.m_TextureSettings.m_FilterMode) switch (m_Texture2D.m_TextureSettings.m_FilterMode)
@@ -820,40 +816,40 @@ namespace AssetStudioGUI
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case AudioType.ACC: case FMODSoundType.ACC:
assetItem.InfoText += "Acc"; assetItem.InfoText += "Acc";
break; break;
case AudioType.AIFF: case FMODSoundType.AIFF:
assetItem.InfoText += "AIFF"; assetItem.InfoText += "AIFF";
break; break;
case AudioType.IT: case FMODSoundType.IT:
assetItem.InfoText += "Impulse tracker"; assetItem.InfoText += "Impulse tracker";
break; break;
case AudioType.MOD: case FMODSoundType.MOD:
assetItem.InfoText += "Protracker / Fasttracker MOD"; assetItem.InfoText += "Protracker / Fasttracker MOD";
break; break;
case AudioType.MPEG: case FMODSoundType.MPEG:
assetItem.InfoText += "MP2/MP3 MPEG"; assetItem.InfoText += "MP2/MP3 MPEG";
break; break;
case AudioType.OGGVORBIS: case FMODSoundType.OGGVORBIS:
assetItem.InfoText += "Ogg vorbis"; assetItem.InfoText += "Ogg vorbis";
break; break;
case AudioType.S3M: case FMODSoundType.S3M:
assetItem.InfoText += "ScreamTracker 3"; assetItem.InfoText += "ScreamTracker 3";
break; break;
case AudioType.WAV: case FMODSoundType.WAV:
assetItem.InfoText += "Microsoft WAV"; assetItem.InfoText += "Microsoft WAV";
break; break;
case AudioType.XM: case FMODSoundType.XM:
assetItem.InfoText += "FastTracker 2 XM"; assetItem.InfoText += "FastTracker 2 XM";
break; break;
case AudioType.XMA: case FMODSoundType.XMA:
assetItem.InfoText += "Xbox360 XMA"; assetItem.InfoText += "Xbox360 XMA";
break; break;
case AudioType.VAG: case FMODSoundType.VAG:
assetItem.InfoText += "PlayStation Portable ADPCM"; assetItem.InfoText += "PlayStation Portable ADPCM";
break; break;
case AudioType.AUDIOQUEUE: case FMODSoundType.AUDIOQUEUE:
assetItem.InfoText += "iPhone"; assetItem.InfoText += "iPhone";
break; break;
default: default:
@@ -877,7 +873,7 @@ namespace AssetStudioGUI
case AudioCompressionFormat.MP3: case AudioCompressionFormat.MP3:
assetItem.InfoText += "MP3"; assetItem.InfoText += "MP3";
break; break;
case AudioCompressionFormat.VAG: case AudioCompressionFormat.PSMVAG:
assetItem.InfoText += "PlayStation Portable ADPCM"; assetItem.InfoText += "PlayStation Portable ADPCM";
break; break;
case AudioCompressionFormat.HEVAG: case AudioCompressionFormat.HEVAG:
@@ -1167,7 +1163,7 @@ namespace AssetStudioGUI
var image = m_Sprite.GetImage(); var image = m_Sprite.GetImage();
if (image != null) if (image != null)
{ {
var bitmap = new DirectBitmap(image.ConvertToBgra32Bytes(), image.Width, image.Height); var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);
image.Dispose(); image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n"; assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
PreviewTexture(bitmap); PreviewTexture(bitmap);
@@ -1384,25 +1380,32 @@ namespace AssetStudioGUI
{ {
var gameObjects = new List<GameObject>(); var gameObjects = new List<GameObject>();
GetSelectedParentNode(sceneTreeView.Nodes, gameObjects); GetSelectedParentNode(sceneTreeView.Nodes, gameObjects);
var saveFileDialog = new SaveFileDialog(); if (gameObjects.Count > 0)
saveFileDialog.FileName = gameObjects[0].m_Name + " (merge).fbx";
saveFileDialog.AddExtension = false;
saveFileDialog.Filter = "Fbx file (*.fbx)|*.fbx";
saveFileDialog.InitialDirectory = saveDirectoryBackup;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{ {
saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName); var saveFileDialog = new SaveFileDialog();
var exportPath = saveFileDialog.FileName; saveFileDialog.FileName = gameObjects[0].m_Name + " (merge).fbx";
List<AssetItem> animationList = null; saveFileDialog.AddExtension = false;
if (animation) saveFileDialog.Filter = "Fbx file (*.fbx)|*.fbx";
saveFileDialog.InitialDirectory = saveDirectoryBackup;
if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
{ {
animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList(); saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName);
if (animationList.Count == 0) var exportPath = saveFileDialog.FileName;
List<AssetItem> animationList = null;
if (animation)
{ {
animationList = null; animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList();
if (animationList.Count == 0)
{
animationList = null;
}
} }
ExportObjectsMergeWithAnimationClip(exportPath, gameObjects, animationList);
} }
ExportObjectsMergeWithAnimationClip(exportPath, gameObjects, animationList); }
else
{
StatusStripUpdate("No Object selected for export.");
} }
} }
} }
@@ -7,11 +7,6 @@ namespace AssetStudioGUI
{ {
public GameObject gameObject; public GameObject gameObject;
public GameObjectTreeNode(string name)
{
Text = name;
}
public GameObjectTreeNode(GameObject gameObject) public GameObjectTreeNode(GameObject gameObject)
{ {
this.gameObject = gameObject; this.gameObject = gameObject;
@@ -14,12 +14,12 @@ namespace AssetStudioGUI
internal DialogResult ShowDialog(IWin32Window owner = null) internal DialogResult ShowDialog(IWin32Window owner = null)
{ {
#if NETFRAMEWORK //#if NETFRAMEWORK
if (Environment.OSVersion.Version.Major >= 6) if (Environment.OSVersion.Version.Major >= 6)
{ {
return ShowVistaDialog(owner); return ShowVistaDialog(owner);
} }
#endif //#endif
return ShowFolderBrowserDialog(owner); return ShowFolderBrowserDialog(owner);
} }
@@ -1,48 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace AssetStudioGUI
{
internal static class TreeViewExtensions
{
private const int TVIF_STATE = 0x8;
private const int TVIS_STATEIMAGEMASK = 0xF000;
private const int TV_FIRST = 0x1100;
private const int TVM_SETITEM = TV_FIRST + 63;
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
private struct TVITEM
{
public int mask;
public IntPtr hItem;
public int state;
public int stateMask;
[MarshalAs(UnmanagedType.LPTStr)]
public string lpszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref TVITEM lParam);
/// <summary>
/// Hides the checkbox for the specified node on a TreeView control.
/// </summary>
public static void HideCheckBox(this TreeNode node)
{
var tvi = new TVITEM
{
hItem = node.Handle,
mask = TVIF_STATE,
stateMask = TVIS_STATEIMAGEMASK,
state = 0
};
SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
}
}
}
+1
View File
@@ -152,6 +152,7 @@ namespace AssetStudioGUI
#region UV #region UV
if (m_Mesh.m_UV0?.Length > 0) if (m_Mesh.m_UV0?.Length > 0)
{ {
c = 4;
if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2) if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
{ {
c = 2; c = 2;
-23
View File
@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AssetStudio;
namespace AssetStudioGUI
{
class GUIProgress : IProgress
{
private Action<int> action;
public GUIProgress(Action<int> action)
{
this.action = action;
}
public void Report(int value)
{
action(value);
}
}
}
+10 -9
View File
@@ -265,7 +265,7 @@ namespace AssetStudioGUI
Progress.Reset(); Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList) foreach (var assetsFile in assetsManager.assetsFileList)
{ {
var fileNode = new GameObjectTreeNode(assetsFile.fileName); //RootNode var fileNode = new TreeNode(assetsFile.fileName); //RootNode
foreach (var obj in assetsFile.Objects) foreach (var obj in assetsFile.Objects)
{ {
@@ -307,11 +307,12 @@ namespace AssetStudioGUI
{ {
if (m_Father.m_GameObject.TryGet(out var parentGameObject)) if (m_Father.m_GameObject.TryGet(out var parentGameObject))
{ {
if (!treeNodeDictionary.TryGetValue(parentGameObject, out parentNode)) if (!treeNodeDictionary.TryGetValue(parentGameObject, out var parentGameObjectNode))
{ {
parentNode = new GameObjectTreeNode(parentGameObject); parentGameObjectNode = new GameObjectTreeNode(parentGameObject);
treeNodeDictionary.Add(parentGameObject, parentNode); treeNodeDictionary.Add(parentGameObject, parentGameObjectNode);
} }
parentNode = parentGameObjectNode;
} }
} }
} }
@@ -514,7 +515,7 @@ namespace AssetStudioGUI
var count = nodes.Cast<TreeNode>().Sum(x => x.Nodes.Count); var count = nodes.Cast<TreeNode>().Sum(x => x.Nodes.Count);
int k = 0; int k = 0;
Progress.Reset(); Progress.Reset();
foreach (GameObjectTreeNode node in nodes) foreach (TreeNode node in nodes)
{ {
//遍历一级子节点 //遍历一级子节点
foreach (GameObjectTreeNode j in node.Nodes) foreach (GameObjectTreeNode j in node.Nodes)
@@ -635,7 +636,7 @@ namespace AssetStudioGUI
} }
else else
{ {
StatusStripUpdate("No Object can be exported."); StatusStripUpdate("No Object selected for export.");
} }
}); });
} }
@@ -667,11 +668,11 @@ namespace AssetStudioGUI
public static void GetSelectedParentNode(TreeNodeCollection nodes, List<GameObject> gameObjects) public static void GetSelectedParentNode(TreeNodeCollection nodes, List<GameObject> gameObjects)
{ {
foreach (GameObjectTreeNode i in nodes) foreach (TreeNode i in nodes)
{ {
if (i.Checked) if (i is GameObjectTreeNode gameObjectTreeNode && i.Checked)
{ {
gameObjects.Add(i.gameObject); gameObjects.Add(gameObjectTreeNode.gameObject);
} }
else else
{ {
+2 -1
View File
@@ -5,7 +5,8 @@
<Version>0.16.0.0</Version> <Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion> <AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion> <FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright> <Copyright>Copyright © Perfare 2018-2022</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+20 -20
View File
@@ -94,29 +94,29 @@ namespace AssetStudio
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case AudioType.ACC: case FMODSoundType.ACC:
return ".m4a"; return ".m4a";
case AudioType.AIFF: case FMODSoundType.AIFF:
return ".aif"; return ".aif";
case AudioType.IT: case FMODSoundType.IT:
return ".it"; return ".it";
case AudioType.MOD: case FMODSoundType.MOD:
return ".mod"; return ".mod";
case AudioType.MPEG: case FMODSoundType.MPEG:
return ".mp3"; return ".mp3";
case AudioType.OGGVORBIS: case FMODSoundType.OGGVORBIS:
return ".ogg"; return ".ogg";
case AudioType.S3M: case FMODSoundType.S3M:
return ".s3m"; return ".s3m";
case AudioType.WAV: case FMODSoundType.WAV:
return ".wav"; return ".wav";
case AudioType.XM: case FMODSoundType.XM:
return ".xm"; return ".xm";
case AudioType.XMA: case FMODSoundType.XMA:
return ".wav"; return ".wav";
case AudioType.VAG: case FMODSoundType.VAG:
return ".vag"; return ".vag";
case AudioType.AUDIOQUEUE: case FMODSoundType.AUDIOQUEUE:
return ".fsb"; return ".fsb";
} }
@@ -133,7 +133,7 @@ namespace AssetStudio
return ".fsb"; return ".fsb";
case AudioCompressionFormat.MP3: case AudioCompressionFormat.MP3:
return ".fsb"; return ".fsb";
case AudioCompressionFormat.VAG: case AudioCompressionFormat.PSMVAG:
return ".fsb"; return ".fsb";
case AudioCompressionFormat.HEVAG: case AudioCompressionFormat.HEVAG:
return ".fsb"; return ".fsb";
@@ -159,13 +159,13 @@ namespace AssetStudio
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case AudioType.AIFF: case FMODSoundType.AIFF:
case AudioType.IT: case FMODSoundType.IT:
case AudioType.MOD: case FMODSoundType.MOD:
case AudioType.S3M: case FMODSoundType.S3M:
case AudioType.XM: case FMODSoundType.XM:
case AudioType.XMA: case FMODSoundType.XMA:
case AudioType.AUDIOQUEUE: case FMODSoundType.AUDIOQUEUE:
return true; return true;
default: default:
return false; return false;
+1 -1
View File
@@ -43,7 +43,7 @@ namespace AssetStudio
return stream; return stream;
} }
public static byte[] ConvertToBgra32Bytes(this Image<Bgra32> image) public static byte[] ConvertToBytes<TPixel>(this Image<TPixel> image) where TPixel : unmanaged, IPixel<TPixel>
{ {
if (image.TryGetSinglePixelSpan(out var pixelSpan)) if (image.TryGetSinglePixelSpan(out var pixelSpan))
{ {
+3 -8
View File
@@ -1063,26 +1063,21 @@ namespace AssetStudio
else else
{ {
transformName = strs.Last(); transformName = strs.Last();
var parentFrameName = strs[strs.Length - 2]; var parentFramePath = path.Substring(0, path.LastIndexOf('/'));
parentFrame = RootFrame.FindChild(parentFrameName); parentFrame = RootFrame.FindRelativeFrameWithPath(parentFramePath);
//var parentFramePath = path.Substring(0, path.LastIndexOf('/'));
//parentFrame = RootFrame.FindFrameByPath(parentFramePath);
} }
var skeletonPose = avatar.m_Avatar.m_DefaultPose; var skeletonPose = avatar.m_Avatar.m_DefaultPose;
var xform = skeletonPose.m_X[i]; var xform = skeletonPose.m_X[i];
var frame = RootFrame.FindChild(transformName); var frame = RootFrame.FindChild(transformName);
if (frame != null) if (frame != null)
{ {
SetFrame(frame, xform.t, xform.q, xform.s); SetFrame(frame, xform.t, xform.q, xform.s);
parentFrame.AddChild(frame);
} }
else else
{ {
frame = CreateFrame(transformName, xform.t, xform.q, xform.s); frame = CreateFrame(transformName, xform.t, xform.q, xform.s);
parentFrame.AddChild(frame);
} }
parentFrame.AddChild(frame);
} }
} }
+190 -159
View File
@@ -19,6 +19,7 @@ namespace AssetStudio
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{ {
var program = new ShaderProgram(blobReader, shader.version); var program = new ShaderProgram(blobReader, shader.version);
program.Read(blobReader, 0);
return header + program.Export(Encoding.UTF8.GetString(shader.m_Script)); return header + program.Export(Encoding.UTF8.GetString(shader.m_Script));
} }
} }
@@ -33,16 +34,25 @@ namespace AssetStudio
private static string ConvertSerializedShader(Shader shader) private static string ConvertSerializedShader(Shader shader)
{ {
var shaderPrograms = new ShaderProgram[shader.platforms.Length]; var length = shader.platforms.Length;
for (var i = 0; i < shader.platforms.Length; i++) var shaderPrograms = new ShaderProgram[length];
for (var i = 0; i < length; i++)
{ {
var compressedBytes = new byte[shader.compressedLengths[i]]; for (var j = 0; j < shader.offsets[i].Length; j++)
Buffer.BlockCopy(shader.compressedBlob, (int)shader.offsets[i], compressedBytes, 0, (int)shader.compressedLengths[i]);
var decompressedBytes = new byte[shader.decompressedLengths[i]];
LZ4Codec.Decode(compressedBytes, decompressedBytes);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{ {
shaderPrograms[i] = new ShaderProgram(blobReader, shader.version); var offset = shader.offsets[i][j];
var compressedLength = shader.compressedLengths[i][j];
var decompressedLength = shader.decompressedLengths[i][j];
var decompressedBytes = new byte[decompressedLength];
LZ4Codec.Decode(shader.compressedBlob, (int)offset, (int)compressedLength, decompressedBytes, 0, (int)decompressedLength);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
if (j == 0)
{
shaderPrograms[i] = new ShaderProgram(blobReader, shader.version);
}
shaderPrograms[i].Read(blobReader, j);
}
} }
} }
@@ -99,17 +109,17 @@ namespace AssetStudio
var sb = new StringBuilder(); var sb = new StringBuilder();
switch (m_Passe.m_Type) switch (m_Passe.m_Type)
{ {
case PassType.kPassTypeNormal: case PassType.Normal:
sb.Append(" Pass "); sb.Append(" Pass ");
break; break;
case PassType.kPassTypeUse: case PassType.Use:
sb.Append(" UsePass "); sb.Append(" UsePass ");
break; break;
case PassType.kPassTypeGrab: case PassType.Grab:
sb.Append(" GrabPass "); sb.Append(" GrabPass ");
break; break;
} }
if (m_Passe.m_Type == PassType.kPassTypeUse) if (m_Passe.m_Type == PassType.Use)
{ {
sb.Append($"\"{m_Passe.m_UseName}\"\n"); sb.Append($"\"{m_Passe.m_UseName}\"\n");
} }
@@ -117,7 +127,7 @@ namespace AssetStudio
{ {
sb.Append("{\n"); sb.Append("{\n");
if (m_Passe.m_Type == PassType.kPassTypeGrab) if (m_Passe.m_Type == PassType.Grab)
{ {
if (!string.IsNullOrEmpty(m_Passe.m_TextureName)) if (!string.IsNullOrEmpty(m_Passe.m_TextureName))
{ {
@@ -348,7 +358,7 @@ namespace AssetStudio
sb.Append(" }\n"); sb.Append(" }\n");
} }
if (m_State.fogMode != FogMode.kFogUnknown || if (m_State.fogMode != FogMode.Unknown ||
m_State.fogColor.x.val != 0f || m_State.fogColor.x.val != 0f ||
m_State.fogColor.y.val != 0f || m_State.fogColor.y.val != 0f ||
m_State.fogColor.z.val != 0f || m_State.fogColor.z.val != 0f ||
@@ -358,21 +368,21 @@ namespace AssetStudio
m_State.fogEnd.val != 0f) m_State.fogEnd.val != 0f)
{ {
sb.Append(" Fog {\n"); sb.Append(" Fog {\n");
if (m_State.fogMode != FogMode.kFogUnknown) if (m_State.fogMode != FogMode.Unknown)
{ {
sb.Append(" Mode "); sb.Append(" Mode ");
switch (m_State.fogMode) switch (m_State.fogMode)
{ {
case FogMode.kFogDisabled: case FogMode.Disabled:
sb.Append("Off"); sb.Append("Off");
break; break;
case FogMode.kFogLinear: case FogMode.Linear:
sb.Append("Linear"); sb.Append("Linear");
break; break;
case FogMode.kFogExp: case FogMode.Exp:
sb.Append("Exp"); sb.Append("Exp");
break; break;
case FogMode.kFogExp2: case FogMode.Exp2:
sb.Append("Exp2"); sb.Append("Exp2");
break; break;
} }
@@ -664,37 +674,37 @@ namespace AssetStudio
sb.Append($"{m_Prop.m_Name} (\"{m_Prop.m_Description}\", "); sb.Append($"{m_Prop.m_Name} (\"{m_Prop.m_Description}\", ");
switch (m_Prop.m_Type) switch (m_Prop.m_Type)
{ {
case SerializedPropertyType.kColor: case SerializedPropertyType.Color:
sb.Append("Color"); sb.Append("Color");
break; break;
case SerializedPropertyType.kVector: case SerializedPropertyType.Vector:
sb.Append("Vector"); sb.Append("Vector");
break; break;
case SerializedPropertyType.kFloat: case SerializedPropertyType.Float:
sb.Append("Float"); sb.Append("Float");
break; break;
case SerializedPropertyType.kRange: case SerializedPropertyType.Range:
sb.Append($"Range({m_Prop.m_DefValue[1]}, {m_Prop.m_DefValue[2]})"); sb.Append($"Range({m_Prop.m_DefValue[1]}, {m_Prop.m_DefValue[2]})");
break; break;
case SerializedPropertyType.kTexture: case SerializedPropertyType.Texture:
switch (m_Prop.m_DefTexture.m_TexDim) switch (m_Prop.m_DefTexture.m_TexDim)
{ {
case TextureDimension.kTexDimAny: case TextureDimension.Any:
sb.Append("any"); sb.Append("any");
break; break;
case TextureDimension.kTexDim2D: case TextureDimension.Tex2D:
sb.Append("2D"); sb.Append("2D");
break; break;
case TextureDimension.kTexDim3D: case TextureDimension.Tex3D:
sb.Append("3D"); sb.Append("3D");
break; break;
case TextureDimension.kTexDimCUBE: case TextureDimension.Cube:
sb.Append("Cube"); sb.Append("Cube");
break; break;
case TextureDimension.kTexDim2DArray: case TextureDimension.Tex2DArray:
sb.Append("2DArray"); sb.Append("2DArray");
break; break;
case TextureDimension.kTexDimCubeArray: case TextureDimension.CubeArray:
sb.Append("CubeArray"); sb.Append("CubeArray");
break; break;
} }
@@ -703,15 +713,15 @@ namespace AssetStudio
sb.Append(") = "); sb.Append(") = ");
switch (m_Prop.m_Type) switch (m_Prop.m_Type)
{ {
case SerializedPropertyType.kColor: case SerializedPropertyType.Color:
case SerializedPropertyType.kVector: case SerializedPropertyType.Vector:
sb.Append($"({m_Prop.m_DefValue[0]},{m_Prop.m_DefValue[1]},{m_Prop.m_DefValue[2]},{m_Prop.m_DefValue[3]})"); sb.Append($"({m_Prop.m_DefValue[0]},{m_Prop.m_DefValue[1]},{m_Prop.m_DefValue[2]},{m_Prop.m_DefValue[3]})");
break; break;
case SerializedPropertyType.kFloat: case SerializedPropertyType.Float:
case SerializedPropertyType.kRange: case SerializedPropertyType.Range:
sb.Append(m_Prop.m_DefValue[0]); sb.Append(m_Prop.m_DefValue[0]);
break; break;
case SerializedPropertyType.kTexture: case SerializedPropertyType.Texture:
sb.Append($"\"{m_Prop.m_DefTexture.m_DefaultName}\" {{ }}"); sb.Append($"\"{m_Prop.m_DefTexture.m_DefaultName}\" {{ }}");
break; break;
default: default:
@@ -725,64 +735,65 @@ namespace AssetStudio
{ {
switch (platform) switch (platform)
{ {
case ShaderCompilerPlatform.kShaderCompPlatformGL: case ShaderCompilerPlatform.GL:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLLegacy; return programType == ShaderGpuProgramType.GLLegacy;
case ShaderCompilerPlatform.kShaderCompPlatformD3D9: case ShaderCompilerPlatform.D3D9:
return programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20 return programType == ShaderGpuProgramType.DX9VertexSM20
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30 || programType == ShaderGpuProgramType.DX9VertexSM30
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20 || programType == ShaderGpuProgramType.DX9PixelSM20
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30; || programType == ShaderGpuProgramType.DX9PixelSM30;
case ShaderCompilerPlatform.kShaderCompPlatformXbox360: case ShaderCompilerPlatform.Xbox360:
case ShaderCompilerPlatform.kShaderCompPlatformPS3: case ShaderCompilerPlatform.PS3:
case ShaderCompilerPlatform.kShaderCompPlatformPSP2: case ShaderCompilerPlatform.PSP2:
case ShaderCompilerPlatform.kShaderCompPlatformPS4: case ShaderCompilerPlatform.PS4:
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne: case ShaderCompilerPlatform.XboxOne:
case ShaderCompilerPlatform.kShaderCompPlatformN3DS: case ShaderCompilerPlatform.N3DS:
case ShaderCompilerPlatform.kShaderCompPlatformWiiU: case ShaderCompilerPlatform.WiiU:
case ShaderCompilerPlatform.kShaderCompPlatformSwitch: case ShaderCompilerPlatform.Switch:
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12: case ShaderCompilerPlatform.XboxOneD3D12:
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne: case ShaderCompilerPlatform.GameCoreXboxOne:
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett: case ShaderCompilerPlatform.GameCoreScarlett:
case ShaderCompilerPlatform.kShaderCompPlatformPS5: case ShaderCompilerPlatform.PS5:
case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC: return programType == ShaderGpuProgramType.ConsoleVS
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS || programType == ShaderGpuProgramType.ConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS || programType == ShaderGpuProgramType.ConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS || programType == ShaderGpuProgramType.ConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS || programType == ShaderGpuProgramType.ConsoleGS;
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; case ShaderCompilerPlatform.PS5NGGC:
case ShaderCompilerPlatform.kShaderCompPlatformD3D11: return programType == ShaderGpuProgramType.PS5NGGC;
return programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40 case ShaderCompilerPlatform.D3D11:
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50 return programType == ShaderGpuProgramType.DX11VertexSM40
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40 || programType == ShaderGpuProgramType.DX11VertexSM50
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50 || programType == ShaderGpuProgramType.DX11PixelSM40
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40 || programType == ShaderGpuProgramType.DX11PixelSM50
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50 || programType == ShaderGpuProgramType.DX11GeometrySM40
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50 || programType == ShaderGpuProgramType.DX11GeometrySM50
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50; || programType == ShaderGpuProgramType.DX11HullSM50
case ShaderCompilerPlatform.kShaderCompPlatformGLES20: || programType == ShaderGpuProgramType.DX11DomainSM50;
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES; case ShaderCompilerPlatform.GLES20:
case ShaderCompilerPlatform.kShaderCompPlatformNaCl: //Obsolete return programType == ShaderGpuProgramType.GLES;
case ShaderCompilerPlatform.NaCl: //Obsolete
throw new NotSupportedException(); throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformFlash: //Obsolete case ShaderCompilerPlatform.Flash: //Obsolete
throw new NotSupportedException(); throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x: case ShaderCompilerPlatform.D3D11_9x:
return programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex return programType == ShaderGpuProgramType.DX10Level9Vertex
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel; || programType == ShaderGpuProgramType.DX10Level9Pixel;
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus: case ShaderCompilerPlatform.GLES3Plus:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES31AEP return programType == ShaderGpuProgramType.GLES31AEP
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES31 || programType == ShaderGpuProgramType.GLES31
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES3; || programType == ShaderGpuProgramType.GLES3;
case ShaderCompilerPlatform.kShaderCompPlatformPSM: //Unknown case ShaderCompilerPlatform.PSM: //Unknown
throw new NotSupportedException(); throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformMetal: case ShaderCompilerPlatform.Metal:
return programType == ShaderGpuProgramType.kShaderGpuProgramMetalVS return programType == ShaderGpuProgramType.MetalVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramMetalFS; || programType == ShaderGpuProgramType.MetalFS;
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore: case ShaderCompilerPlatform.OpenGLCore:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLCore32 return programType == ShaderGpuProgramType.GLCore32
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore41 || programType == ShaderGpuProgramType.GLCore41
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore43; || programType == ShaderGpuProgramType.GLCore43;
case ShaderCompilerPlatform.kShaderCompPlatformVulkan: case ShaderCompilerPlatform.Vulkan:
return programType == ShaderGpuProgramType.kShaderGpuProgramSPIRV; return programType == ShaderGpuProgramType.SPIRV;
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
} }
@@ -792,55 +803,55 @@ namespace AssetStudio
{ {
switch (platform) switch (platform)
{ {
case ShaderCompilerPlatform.kShaderCompPlatformGL: case ShaderCompilerPlatform.GL:
return "openGL"; return "openGL";
case ShaderCompilerPlatform.kShaderCompPlatformD3D9: case ShaderCompilerPlatform.D3D9:
return "d3d9"; return "d3d9";
case ShaderCompilerPlatform.kShaderCompPlatformXbox360: case ShaderCompilerPlatform.Xbox360:
return "xbox360"; return "xbox360";
case ShaderCompilerPlatform.kShaderCompPlatformPS3: case ShaderCompilerPlatform.PS3:
return "ps3"; return "ps3";
case ShaderCompilerPlatform.kShaderCompPlatformD3D11: case ShaderCompilerPlatform.D3D11:
return "d3d11"; return "d3d11";
case ShaderCompilerPlatform.kShaderCompPlatformGLES20: case ShaderCompilerPlatform.GLES20:
return "gles"; return "gles";
case ShaderCompilerPlatform.kShaderCompPlatformNaCl: case ShaderCompilerPlatform.NaCl:
return "glesdesktop"; return "glesdesktop";
case ShaderCompilerPlatform.kShaderCompPlatformFlash: case ShaderCompilerPlatform.Flash:
return "flash"; return "flash";
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x: case ShaderCompilerPlatform.D3D11_9x:
return "d3d11_9x"; return "d3d11_9x";
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus: case ShaderCompilerPlatform.GLES3Plus:
return "gles3"; return "gles3";
case ShaderCompilerPlatform.kShaderCompPlatformPSP2: case ShaderCompilerPlatform.PSP2:
return "psp2"; return "psp2";
case ShaderCompilerPlatform.kShaderCompPlatformPS4: case ShaderCompilerPlatform.PS4:
return "ps4"; return "ps4";
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne: case ShaderCompilerPlatform.XboxOne:
return "xboxone"; return "xboxone";
case ShaderCompilerPlatform.kShaderCompPlatformPSM: case ShaderCompilerPlatform.PSM:
return "psm"; return "psm";
case ShaderCompilerPlatform.kShaderCompPlatformMetal: case ShaderCompilerPlatform.Metal:
return "metal"; return "metal";
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore: case ShaderCompilerPlatform.OpenGLCore:
return "glcore"; return "glcore";
case ShaderCompilerPlatform.kShaderCompPlatformN3DS: case ShaderCompilerPlatform.N3DS:
return "n3ds"; return "n3ds";
case ShaderCompilerPlatform.kShaderCompPlatformWiiU: case ShaderCompilerPlatform.WiiU:
return "wiiu"; return "wiiu";
case ShaderCompilerPlatform.kShaderCompPlatformVulkan: case ShaderCompilerPlatform.Vulkan:
return "vulkan"; return "vulkan";
case ShaderCompilerPlatform.kShaderCompPlatformSwitch: case ShaderCompilerPlatform.Switch:
return "switch"; return "switch";
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12: case ShaderCompilerPlatform.XboxOneD3D12:
return "xboxone_d3d12"; return "xboxone_d3d12";
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne: case ShaderCompilerPlatform.GameCoreXboxOne:
return "xboxone"; return "xboxone";
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett: case ShaderCompilerPlatform.GameCoreScarlett:
return "xbox_scarlett"; return "xbox_scarlett";
case ShaderCompilerPlatform.kShaderCompPlatformPS5: case ShaderCompilerPlatform.PS5:
return "ps5"; return "ps5";
case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC: case ShaderCompilerPlatform.PS5NGGC:
return "ps5_nggc"; return "ps5_nggc";
default: default:
return "unknown"; return "unknown";
@@ -854,29 +865,49 @@ namespace AssetStudio
"///////////////////////////////////////////\n"; "///////////////////////////////////////////\n";
} }
public class ShaderSubProgramEntry
{
public int Offset;
public int Length;
public int Segment;
public ShaderSubProgramEntry(BinaryReader reader, int[] version)
{
Offset = reader.ReadInt32();
Length = reader.ReadInt32();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
Segment = reader.ReadInt32();
}
}
}
public class ShaderProgram public class ShaderProgram
{ {
public ShaderSubProgramEntry[] entries;
public ShaderSubProgram[] m_SubPrograms; public ShaderSubProgram[] m_SubPrograms;
public ShaderProgram(BinaryReader reader, int[] version) public ShaderProgram(BinaryReader reader, int[] version)
{ {
var subProgramsCapacity = reader.ReadInt32(); var subProgramsCapacity = reader.ReadInt32();
m_SubPrograms = new ShaderSubProgram[subProgramsCapacity]; entries = new ShaderSubProgramEntry[subProgramsCapacity];
int entrySize;
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
entrySize = 12;
}
else
{
entrySize = 8;
}
for (int i = 0; i < subProgramsCapacity; i++) for (int i = 0; i < subProgramsCapacity; i++)
{ {
reader.BaseStream.Position = 4 + i * entrySize; entries[i] = new ShaderSubProgramEntry(reader, version);
var offset = reader.ReadInt32(); }
reader.BaseStream.Position = offset; m_SubPrograms = new ShaderSubProgram[subProgramsCapacity];
m_SubPrograms[i] = new ShaderSubProgram(reader); }
public void Read(BinaryReader reader, int segment)
{
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
if (entry.Segment == segment)
{
reader.BaseStream.Position = entry.Offset;
m_SubPrograms[i] = new ShaderSubProgram(reader);
}
} }
} }
@@ -966,36 +997,36 @@ namespace AssetStudio
{ {
switch (m_ProgramType) switch (m_ProgramType)
{ {
case ShaderGpuProgramType.kShaderGpuProgramGLLegacy: case ShaderGpuProgramType.GLLegacy:
case ShaderGpuProgramType.kShaderGpuProgramGLES31AEP: case ShaderGpuProgramType.GLES31AEP:
case ShaderGpuProgramType.kShaderGpuProgramGLES31: case ShaderGpuProgramType.GLES31:
case ShaderGpuProgramType.kShaderGpuProgramGLES3: case ShaderGpuProgramType.GLES3:
case ShaderGpuProgramType.kShaderGpuProgramGLES: case ShaderGpuProgramType.GLES:
case ShaderGpuProgramType.kShaderGpuProgramGLCore32: case ShaderGpuProgramType.GLCore32:
case ShaderGpuProgramType.kShaderGpuProgramGLCore41: case ShaderGpuProgramType.GLCore41:
case ShaderGpuProgramType.kShaderGpuProgramGLCore43: case ShaderGpuProgramType.GLCore43:
sb.Append(Encoding.UTF8.GetString(m_ProgramCode)); sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
break; break;
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20: case ShaderGpuProgramType.DX9VertexSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30: case ShaderGpuProgramType.DX9VertexSM30:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20: case ShaderGpuProgramType.DX9PixelSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30: case ShaderGpuProgramType.DX9PixelSM30:
{ {
/*var shaderBytecode = new ShaderBytecode(m_ProgramCode); /*var shaderBytecode = new ShaderBytecode(m_ProgramCode);
sb.Append(shaderBytecode.Disassemble());*/ sb.Append(shaderBytecode.Disassemble());*/
sb.Append("// shader disassembly not supported on DXBC"); sb.Append("// shader disassembly not supported on DXBC");
break; break;
} }
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex: case ShaderGpuProgramType.DX10Level9Vertex:
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel: case ShaderGpuProgramType.DX10Level9Pixel:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40: case ShaderGpuProgramType.DX11VertexSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50: case ShaderGpuProgramType.DX11VertexSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40: case ShaderGpuProgramType.DX11PixelSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50: case ShaderGpuProgramType.DX11PixelSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40: case ShaderGpuProgramType.DX11GeometrySM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50: case ShaderGpuProgramType.DX11GeometrySM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50: case ShaderGpuProgramType.DX11HullSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50: case ShaderGpuProgramType.DX11DomainSM50:
{ {
/*int start = 6; /*int start = 6;
if (m_Version == 201509030) // 5.3 if (m_Version == 201509030) // 5.3
@@ -1009,8 +1040,8 @@ namespace AssetStudio
sb.Append("// shader disassembly not supported on DXBC"); sb.Append("// shader disassembly not supported on DXBC");
break; break;
} }
case ShaderGpuProgramType.kShaderGpuProgramMetalVS: case ShaderGpuProgramType.MetalVS:
case ShaderGpuProgramType.kShaderGpuProgramMetalFS: case ShaderGpuProgramType.MetalFS:
using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode))) using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode)))
{ {
var fourCC = reader.ReadUInt32(); var fourCC = reader.ReadUInt32();
@@ -1024,7 +1055,7 @@ namespace AssetStudio
sb.Append(Encoding.UTF8.GetString(buff)); sb.Append(Encoding.UTF8.GetString(buff));
} }
break; break;
case ShaderGpuProgramType.kShaderGpuProgramSPIRV: case ShaderGpuProgramType.SPIRV:
try try
{ {
sb.Append(SpirVShaderConverter.Convert(m_ProgramCode)); sb.Append(SpirVShaderConverter.Convert(m_ProgramCode));
@@ -1034,11 +1065,11 @@ namespace AssetStudio
sb.Append($"// disassembly error {e.Message}\n"); sb.Append($"// disassembly error {e.Message}\n");
} }
break; break;
case ShaderGpuProgramType.kShaderGpuProgramConsoleVS: case ShaderGpuProgramType.ConsoleVS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleFS: case ShaderGpuProgramType.ConsoleFS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleHS: case ShaderGpuProgramType.ConsoleHS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleDS: case ShaderGpuProgramType.ConsoleDS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleGS: case ShaderGpuProgramType.ConsoleGS:
sb.Append(Encoding.UTF8.GetString(m_ProgramCode)); sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
break; break;
default: default:
+16 -10
View File
@@ -19,32 +19,38 @@ namespace AssetStudio
{ {
if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out var m_Texture2D)) if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out var m_Texture2D))
{ {
return CutImage(m_Texture2D, m_Sprite, spriteAtlasData.textureRect, spriteAtlasData.textureRectOffset, spriteAtlasData.settingsRaw); return CutImage(m_Sprite, m_Texture2D, spriteAtlasData.textureRect, spriteAtlasData.textureRectOffset, spriteAtlasData.downscaleMultiplier, spriteAtlasData.settingsRaw);
} }
} }
else else
{ {
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D)) if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D))
{ {
return CutImage(m_Texture2D, m_Sprite, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.settingsRaw); return CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
} }
} }
return null; return null;
} }
private static Image<Bgra32> CutImage(Texture2D m_Texture2D, Sprite m_Sprite, Rectf textureRect, Vector2 textureRectOffset, SpriteSettings settingsRaw) private static Image<Bgra32> CutImage(Sprite m_Sprite, Texture2D m_Texture2D, Rectf textureRect, Vector2 textureRectOffset, float downscaleMultiplier, SpriteSettings settingsRaw)
{ {
var originalImage = m_Texture2D.ConvertToImage(false); var originalImage = m_Texture2D.ConvertToImage(false);
if (originalImage != null) if (originalImage != null)
{ {
using (originalImage) using (originalImage)
{ {
if (downscaleMultiplier > 0f && downscaleMultiplier != 1f)
{
var width = (int)(m_Texture2D.m_Width / downscaleMultiplier);
var height = (int)(m_Texture2D.m_Height / downscaleMultiplier);
originalImage.Mutate(x => x.Resize(width, height));
}
var rectX = (int)Math.Floor(textureRect.x); var rectX = (int)Math.Floor(textureRect.x);
var rectY = (int)Math.Floor(textureRect.y); var rectY = (int)Math.Floor(textureRect.y);
var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width); var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);
var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height); var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);
rectRight = Math.Min(rectRight, m_Texture2D.m_Width); rectRight = Math.Min(rectRight, originalImage.Width);
rectBottom = Math.Min(rectBottom, m_Texture2D.m_Height); rectBottom = Math.Min(rectBottom, originalImage.Height);
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY); var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
var spriteImage = originalImage.Clone(x => x.Crop(rect)); var spriteImage = originalImage.Clone(x => x.Crop(rect));
if (settingsRaw.packed == 1) if (settingsRaw.packed == 1)
@@ -52,23 +58,23 @@ namespace AssetStudio
//RotateAndFlip //RotateAndFlip
switch (settingsRaw.packingRotation) switch (settingsRaw.packingRotation)
{ {
case SpritePackingRotation.kSPRFlipHorizontal: case SpritePackingRotation.FlipHorizontal:
spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal)); spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal));
break; break;
case SpritePackingRotation.kSPRFlipVertical: case SpritePackingRotation.FlipVertical:
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical)); spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
break; break;
case SpritePackingRotation.kSPRRotate180: case SpritePackingRotation.Rotate180:
spriteImage.Mutate(x => x.Rotate(180)); spriteImage.Mutate(x => x.Rotate(180));
break; break;
case SpritePackingRotation.kSPRRotate90: case SpritePackingRotation.Rotate90:
spriteImage.Mutate(x => x.Rotate(270)); spriteImage.Mutate(x => x.Rotate(270));
break; break;
} }
} }
//Tight //Tight
if (settingsRaw.packingMode == SpritePackingMode.kSPMTight) if (settingsRaw.packingMode == SpritePackingMode.Tight)
{ {
try try
{ {
+95 -29
View File
@@ -1,4 +1,5 @@
using System; using System;
using System.Runtime.CompilerServices;
using Texture2DDecoder; using Texture2DDecoder;
namespace AssetStudio namespace AssetStudio
@@ -11,6 +12,7 @@ namespace AssetStudio
private TextureFormat m_TextureFormat; private TextureFormat m_TextureFormat;
private int[] version; private int[] version;
private BuildTarget platform; private BuildTarget platform;
private int outPutSize;
public Texture2DConverter(Texture2D m_Texture2D) public Texture2DConverter(Texture2D m_Texture2D)
{ {
@@ -20,6 +22,7 @@ namespace AssetStudio
m_TextureFormat = m_Texture2D.m_TextureFormat; m_TextureFormat = m_Texture2D.m_TextureFormat;
version = m_Texture2D.version; version = m_Texture2D.version;
platform = m_Texture2D.platform; platform = m_Texture2D.platform;
outPutSize = m_Width * m_Height * 4;
} }
public bool DecodeTexture2D(byte[] bytes) public bool DecodeTexture2D(byte[] bytes)
@@ -60,6 +63,8 @@ namespace AssetStudio
SwapBytesForXbox(buff); SwapBytesForXbox(buff);
flag = DecodeDXT1(buff, bytes); flag = DecodeDXT1(buff, bytes);
break; break;
case TextureFormat.DXT3:
break;
case TextureFormat.DXT5: //test pass case TextureFormat.DXT5: //test pass
SwapBytesForXbox(buff); SwapBytesForXbox(buff);
flag = DecodeDXT5(buff, bytes); flag = DecodeDXT5(buff, bytes);
@@ -94,18 +99,18 @@ namespace AssetStudio
case TextureFormat.RGB9e5Float: //test pass case TextureFormat.RGB9e5Float: //test pass
flag = DecodeRGB9e5Float(buff, bytes); flag = DecodeRGB9e5Float(buff, bytes);
break; break;
case TextureFormat.BC4: //test pass
flag = DecodeBC4(buff, bytes);
break;
case TextureFormat.BC5: //test pass
flag = DecodeBC5(buff, bytes);
break;
case TextureFormat.BC6H: //test pass case TextureFormat.BC6H: //test pass
flag = DecodeBC6H(buff, bytes); flag = DecodeBC6H(buff, bytes);
break; break;
case TextureFormat.BC7: //test pass case TextureFormat.BC7: //test pass
flag = DecodeBC7(buff, bytes); flag = DecodeBC7(buff, bytes);
break; break;
case TextureFormat.BC4: //test pass
flag = DecodeBC4(buff, bytes);
break;
case TextureFormat.BC5: //test pass
flag = DecodeBC5(buff, bytes);
break;
case TextureFormat.DXT1Crunched: //test pass case TextureFormat.DXT1Crunched: //test pass
flag = DecodeDXT1Crunched(buff, bytes); flag = DecodeDXT1Crunched(buff, bytes);
break; break;
@@ -194,6 +199,15 @@ namespace AssetStudio
case TextureFormat.ETC2_RGBA8Crunched: //test pass case TextureFormat.ETC2_RGBA8Crunched: //test pass
flag = DecodeETC2A8Crunched(buff, bytes); flag = DecodeETC2A8Crunched(buff, bytes);
break; break;
case TextureFormat.RG32: //test pass
flag = DecodeRG32(buff, bytes);
break;
case TextureFormat.RGB48: //test pass
flag = DecodeRGB48(buff, bytes);
break;
case TextureFormat.RGBA64: //test pass
flag = DecodeRGBA64(buff, bytes);
break;
} }
BigArrayPool<byte>.Shared.Return(buff); BigArrayPool<byte>.Shared.Return(buff);
return flag; return flag;
@@ -214,9 +228,10 @@ namespace AssetStudio
private bool DecodeAlpha8(byte[] image_data, byte[] buff) private bool DecodeAlpha8(byte[] image_data, byte[] buff)
{ {
var size = m_Width * m_Height;
var span = new Span<byte>(buff); var span = new Span<byte>(buff);
span.Fill(0xFF); span.Fill(0xFF);
for (var i = 0; i < m_Width * m_Height; i++) for (var i = 0; i < size; i++)
{ {
buff[i * 4 + 3] = image_data[i]; buff[i * 4 + 3] = image_data[i];
} }
@@ -225,8 +240,9 @@ namespace AssetStudio
private bool DecodeARGB4444(byte[] image_data, byte[] buff) private bool DecodeARGB4444(byte[] image_data, byte[] buff)
{ {
var size = m_Width * m_Height;
var pixelNew = new byte[4]; var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++) for (var i = 0; i < size; i++)
{ {
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2); var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)(pixelOldShort & 0x000f); pixelNew[0] = (byte)(pixelOldShort & 0x000f);
@@ -242,7 +258,8 @@ namespace AssetStudio
private bool DecodeRGB24(byte[] image_data, byte[] buff) private bool DecodeRGB24(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < m_Width * m_Height; i++) var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{ {
buff[i * 4] = image_data[i * 3 + 2]; buff[i * 4] = image_data[i * 3 + 2];
buff[i * 4 + 1] = image_data[i * 3 + 1]; buff[i * 4 + 1] = image_data[i * 3 + 1];
@@ -254,7 +271,7 @@ namespace AssetStudio
private bool DecodeRGBA32(byte[] image_data, byte[] buff) private bool DecodeRGBA32(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = image_data[i + 2]; buff[i] = image_data[i + 2];
buff[i + 1] = image_data[i + 1]; buff[i + 1] = image_data[i + 1];
@@ -266,7 +283,7 @@ namespace AssetStudio
private bool DecodeARGB32(byte[] image_data, byte[] buff) private bool DecodeARGB32(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = image_data[i + 3]; buff[i] = image_data[i + 3];
buff[i + 1] = image_data[i + 2]; buff[i + 1] = image_data[i + 2];
@@ -278,7 +295,8 @@ namespace AssetStudio
private bool DecodeRGB565(byte[] image_data, byte[] buff) private bool DecodeRGB565(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < m_Width * m_Height; i++) var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{ {
var p = BitConverter.ToUInt16(image_data, i * 2); var p = BitConverter.ToUInt16(image_data, i * 2);
buff[i * 4] = (byte)((p << 3) | (p >> 2 & 7)); buff[i * 4] = (byte)((p << 3) | (p >> 2 & 7));
@@ -291,11 +309,12 @@ namespace AssetStudio
private bool DecodeR16(byte[] image_data, byte[] buff) private bool DecodeR16(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < m_Width * m_Height; i++) var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{ {
buff[i * 4] = 0; //b buff[i * 4] = 0; //b
buff[i * 4 + 1] = 0; //g buff[i * 4 + 1] = 0; //g
buff[i * 4 + 2] = image_data[i * 2 + 1]; //r buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r
buff[i * 4 + 3] = 255; //a buff[i * 4 + 3] = 255; //a
} }
return true; return true;
@@ -313,8 +332,9 @@ namespace AssetStudio
private bool DecodeRGBA4444(byte[] image_data, byte[] buff) private bool DecodeRGBA4444(byte[] image_data, byte[] buff)
{ {
var size = m_Width * m_Height;
var pixelNew = new byte[4]; var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++) for (var i = 0; i < size; i++)
{ {
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2); var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)((pixelOldShort & 0x00f0) >> 4); pixelNew[0] = (byte)((pixelOldShort & 0x00f0) >> 4);
@@ -330,7 +350,7 @@ namespace AssetStudio
private bool DecodeBGRA32(byte[] image_data, byte[] buff) private bool DecodeBGRA32(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = image_data[i]; buff[i] = image_data[i];
buff[i + 1] = image_data[i + 1]; buff[i + 1] = image_data[i + 1];
@@ -342,7 +362,7 @@ namespace AssetStudio
private bool DecodeRHalf(byte[] image_data, byte[] buff) private bool DecodeRHalf(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = 0; buff[i] = 0;
buff[i + 1] = 0; buff[i + 1] = 0;
@@ -354,7 +374,7 @@ namespace AssetStudio
private bool DecodeRGHalf(byte[] image_data, byte[] buff) private bool DecodeRGHalf(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = 0; buff[i] = 0;
buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i + 2) * 255f); buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i + 2) * 255f);
@@ -366,7 +386,7 @@ namespace AssetStudio
private bool DecodeRGBAHalf(byte[] image_data, byte[] buff) private bool DecodeRGBAHalf(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f); buff[i] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f);
buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f); buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f);
@@ -378,7 +398,7 @@ namespace AssetStudio
private bool DecodeRFloat(byte[] image_data, byte[] buff) private bool DecodeRFloat(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = 0; buff[i] = 0;
buff[i + 1] = 0; buff[i + 1] = 0;
@@ -390,7 +410,7 @@ namespace AssetStudio
private bool DecodeRGFloat(byte[] image_data, byte[] buff) private bool DecodeRGFloat(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = 0; buff[i] = 0;
buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2 + 4) * 255f); buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2 + 4) * 255f);
@@ -402,7 +422,7 @@ namespace AssetStudio
private bool DecodeRGBAFloat(byte[] image_data, byte[] buff) private bool DecodeRGBAFloat(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
buff[i] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 8) * 255f); buff[i] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 8) * 255f);
buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 4) * 255f); buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 4) * 255f);
@@ -412,6 +432,7 @@ namespace AssetStudio
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static byte ClampByte(int x) private static byte ClampByte(int x)
{ {
return (byte)(byte.MaxValue < x ? byte.MaxValue : (x > byte.MinValue ? x : byte.MinValue)); return (byte)(byte.MaxValue < x ? byte.MaxValue : (x > byte.MinValue ? x : byte.MinValue));
@@ -449,7 +470,7 @@ namespace AssetStudio
private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff) private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < buff.Length; i += 4) for (var i = 0; i < outPutSize; i += 4)
{ {
var n = BitConverter.ToInt32(image_data, i); var n = BitConverter.ToInt32(image_data, i);
var scale = n >> 27 & 0x1f; var scale = n >> 27 & 0x1f;
@@ -571,19 +592,21 @@ namespace AssetStudio
private bool DecodeRG16(byte[] image_data, byte[] buff) private bool DecodeRG16(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < m_Width * m_Height; i += 2) var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{ {
buff[i * 2] = 0; //B buff[i * 4] = 0; //B
buff[i * 2 + 1] = image_data[i + 1];//G buff[i * 4 + 1] = image_data[i * 2 + 1];//G
buff[i * 2 + 2] = image_data[i];//R buff[i * 4 + 2] = image_data[i * 2];//R
buff[i * 2 + 3] = 255;//A buff[i * 4 + 3] = 255;//A
} }
return true; return true;
} }
private bool DecodeR8(byte[] image_data, byte[] buff) private bool DecodeR8(byte[] image_data, byte[] buff)
{ {
for (var i = 0; i < m_Width * m_Height; i++) var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{ {
buff[i * 4] = 0; //B buff[i * 4] = 0; //B
buff[i * 4 + 1] = 0; //G buff[i * 4 + 1] = 0; //G
@@ -617,6 +640,49 @@ namespace AssetStudio
return false; return false;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte DownScaleFrom16BitTo8Bit(ushort component)
{
return (byte)(((component * 255) + 32895) >> 16);
}
private bool DecodeRG32(byte[] image_data, byte[] buff)
{
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0; //b
buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i + 2)); //g
buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i)); //r
buff[i + 3] = byte.MaxValue; //a
}
return true;
}
private bool DecodeRGB48(byte[] image_data, byte[] buff)
{
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
buff[i * 4] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 4)); //b
buff[i * 4 + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 2)); //g
buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6)); //r
buff[i * 4 + 3] = byte.MaxValue; //a
}
return true;
}
private bool DecodeRGBA64(byte[] image_data, byte[] buff)
{
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 4)); //b
buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 2)); //g
buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r
buff[i + 3] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 6)); //a
}
return true;
}
private bool UnpackCrunch(byte[] image_data, out byte[] result) private bool UnpackCrunch(byte[] image_data, out byte[] result)
{ {
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up
@@ -253,28 +253,28 @@ namespace AssetStudio
switch (typeRef.FullName) switch (typeRef.FullName)
{ {
case "UnityEngine.AnimationCurve": case "UnityEngine.AnimationCurve":
Helper.AddAnimationCurve(nodes, name, indent + 1); Helper.AddAnimationCurve(nodes, name, indent);
break; break;
case "UnityEngine.Gradient": case "UnityEngine.Gradient":
Helper.AddGradient(nodes, name, indent + 1); Helper.AddGradient(nodes, name, indent);
break; break;
case "UnityEngine.GUIStyle": case "UnityEngine.GUIStyle":
Helper.AddGUIStyle(nodes, name, indent + 1); Helper.AddGUIStyle(nodes, name, indent);
break; break;
case "UnityEngine.RectOffset": case "UnityEngine.RectOffset":
Helper.AddRectOffset(nodes, name, indent + 1); Helper.AddRectOffset(nodes, name, indent);
break; break;
case "UnityEngine.Color32": case "UnityEngine.Color32":
Helper.AddColor32(nodes, name, indent + 1); Helper.AddColor32(nodes, name, indent);
break; break;
case "UnityEngine.Matrix4x4": case "UnityEngine.Matrix4x4":
Helper.AddMatrix4x4(nodes, name, indent + 1); Helper.AddMatrix4x4(nodes, name, indent);
break; break;
case "UnityEngine.Rendering.SphericalHarmonicsL2": case "UnityEngine.Rendering.SphericalHarmonicsL2":
Helper.AddSphericalHarmonicsL2(nodes, name, indent + 1); Helper.AddSphericalHarmonicsL2(nodes, name, indent);
break; break;
case "UnityEngine.PropertyName": case "UnityEngine.PropertyName":
Helper.AddPropertyName(nodes, name, indent + 1); Helper.AddPropertyName(nodes, name, indent);
break; break;
} }
} }
+1 -1
View File
@@ -7,7 +7,7 @@ AssetStudio is a tool for exploring, extracting and exporting assets and assetbu
## Features ## Features
* Support version: * Support version:
* 3.4 - 2021.2 * 3.4 - 2022.1
* Support asset types: * Support asset types:
* **Texture2D** : convert to png, tga, jpeg, bmp * **Texture2D** : convert to png, tga, jpeg, bmp
* **Sprite** : crop Texture2D to png, tga, jpeg, bmp * **Sprite** : crop Texture2D to png, tga, jpeg, bmp
@@ -6,7 +6,8 @@
<Version>0.16.0.0</Version> <Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion> <AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion> <FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2020-2021; Copyright © hozuki 2020</Copyright> <Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>