37 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
Perfare
97b5f51f3a Fix build 2021-12-09 20:23:25 +08:00
Perfare
7295feda72 Update README.md 2021-12-09 19:16:13 +08:00
Perfare
fe95c91759 Add net6.0 target framework 2021-12-09 19:00:59 +08:00
Perfare
d220315d9b Add detailed export progress in the status bar 2021-12-09 18:08:56 +08:00
Perfare
a94caa5e34 Update project 2021-12-09 17:21:44 +08:00
Perfare
3660b4ed67 Some improvements 2021-12-09 17:13:21 +08:00
Perfare
3370f93037 Fixed bug 2021-12-06 17:37:59 +08:00
Perfare
80653711cd Performance improvement 2021-12-06 13:36:22 +08:00
Perfare
88c5804586 Fixed #886 2021-12-04 09:23:41 +08:00
Perfare
e501940f03 Use a better way to crop Sprite 2021-12-04 08:44:33 +08:00
Perfare
d4060cde6d Fixed bug 2021-12-04 02:05:35 +08:00
Perfare
582a779441 Update project file 2021-12-03 19:46:20 +08:00
Perfare
5fa4934787 Add net5.0 target framework 2021-12-03 17:21:24 +08:00
Perfare
18277fbea8 fixed bug 2021-12-03 17:05:06 +08:00
55 changed files with 1607 additions and 1757 deletions

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

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

View File

@@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<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>
</Project>

View File

@@ -1,11 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright>
<Copyright>Copyright © Perfare 2018-2022</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<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" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,7 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using static AssetStudio.ImportHelper;
@@ -17,11 +18,12 @@ namespace AssetStudio
private List<string> importFiles = new List<string>();
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);
public void LoadFiles(params string[] files)
{
var path = Path.GetDirectoryName(files[0]);
var path = Path.GetDirectoryName(Path.GetFullPath(files[0]));
MergeSplitAssets(path);
var toReadFile = ProcessingSplitFiles(files.ToList());
Load(toReadFile);
@@ -53,6 +55,7 @@ namespace AssetStudio
importFiles.Clear();
importFilesHash.Clear();
noexistFiles.Clear();
assetsFileListHash.Clear();
ReadAssets();
@@ -84,6 +87,9 @@ namespace AssetStudio
case FileType.BrotliFile:
LoadFile(DecompressBrotli(reader));
break;
case FileType.ZipFile:
LoadZipFile(reader);
break;
}
}
@@ -91,7 +97,7 @@ namespace AssetStudio
{
if (!assetsFileListHash.Contains(reader.FileName))
{
Logger.Info($"Loading {reader.FileName}");
Logger.Info($"Loading {reader.FullPath}");
try
{
var assetsFile = new SerializedFile(reader, this);
@@ -106,31 +112,38 @@ namespace AssetStudio
if (!importFilesHash.Contains(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 (findFiles.Length > 0)
if (!File.Exists(sharedFilePath))
{
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)
{
Logger.Error($"Error while reading assets file {reader.FileName}", e);
Logger.Error($"Error while reading assets file {reader.FullPath}", e);
reader.Dispose();
}
}
else
{
Logger.Info($"Skipping {reader.FullPath}");
reader.Dispose();
}
}
@@ -143,7 +156,7 @@ namespace AssetStudio
{
var assetsFile = new SerializedFile(reader, this);
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);
}
@@ -153,15 +166,17 @@ namespace AssetStudio
}
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);
}
}
else
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
}
private void LoadBundleFile(FileReader reader, string originalPath = null)
{
Logger.Info("Loading " + reader.FileName);
Logger.Info("Loading " + reader.FullPath);
try
{
var bundleFile = new BundleFile(reader);
@@ -181,7 +196,7 @@ namespace AssetStudio
}
catch (Exception e)
{
var str = $"Error while reading bundle file {reader.FileName}";
var str = $"Error while reading bundle file {reader.FullPath}";
if (originalPath != null)
{
str += $" from {Path.GetFileName(originalPath)}";
@@ -196,7 +211,7 @@ namespace AssetStudio
private void LoadWebFile(FileReader reader)
{
Logger.Info("Loading " + reader.FileName);
Logger.Info("Loading " + reader.FullPath);
try
{
var webFile = new WebFile(reader);
@@ -223,7 +238,107 @@ namespace AssetStudio
}
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
{
@@ -373,6 +488,7 @@ namespace AssetStudio
var sb = new StringBuilder();
sb.AppendLine("Unable to load object")
.AppendLine($"Assets {assetsFile.fileName}")
.AppendLine($"Path {assetsFile.originalPath}")
.AppendLine($"Type {objectReader.type}")
.AppendLine($"PathID {objectInfo.m_PathID}")
.Append(e);
@@ -432,6 +548,14 @@ namespace AssetStudio
{
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);
}
}
}
}
}
@@ -439,4 +563,4 @@ namespace AssetStudio
}
}
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Buffers;
namespace AssetStudio
{
public static class BigArrayPool<T>
{
private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
public static ArrayPool<T> Shared => s_shared;
}
}

View File

@@ -8,7 +8,8 @@ namespace AssetStudio
public enum BuildTarget
{
NoTarget = -2,
DashboardWidget = 1,
AnyPlayer = -1,
ValidPlayer = 1,
StandaloneOSX = 2,
StandaloneOSXPPC = 3,
StandaloneOSXIntel = 4,
@@ -19,8 +20,10 @@ namespace AssetStudio
iOS = 9,
PS3,
XBOX360,
Broadcom = 12,
Android = 13,
StandaloneGLESEmu = 14,
StandaloneGLES20Emu = 15,
NaCl = 16,
StandaloneLinux = 17,
FlashPlayer = 18,
@@ -48,6 +51,8 @@ namespace AssetStudio
GameCoreXboxSeries,
GameCoreXboxOne,
PS5,
EmbeddedLinux,
QNX,
UnknownPlatform = 9999
}
}

View File

@@ -1,11 +1,36 @@
using System;
using System.Collections.Generic;
using K4os.Compression.LZ4;
using System;
using System.IO;
using System.Linq;
using Lz4;
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 Header
@@ -17,14 +42,14 @@ namespace AssetStudio
public long size;
public uint compressedBlocksInfoSize;
public uint uncompressedBlocksInfoSize;
public uint flags;
public ArchiveFlags flags;
}
public class StorageBlock
{
public uint compressedSize;
public uint uncompressedSize;
public ushort flags;
public StorageBlockFlags flags;
}
public class Node
@@ -79,7 +104,6 @@ namespace AssetStudio
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
{
var isCompressed = m_Header.signature == "UnityWeb";
if (m_Header.version >= 4)
{
var hash = reader.ReadBytes(16);
@@ -96,7 +120,6 @@ namespace AssetStudio
{
compressedSize = reader.ReadUInt32(),
uncompressedSize = reader.ReadUInt32(),
flags = (ushort)(isCompressed ? 1 : 0)
};
if (i == levelCount - 1)
{
@@ -133,10 +156,11 @@ namespace AssetStudio
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
{
var isCompressed = m_Header.signature == "UnityWeb";
foreach (var blockInfo in m_BlocksInfo)
{
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
if (blockInfo.flags == 1)
if (isCompressed)
{
using (var memoryStream = new MemoryStream(uncompressedBytes))
{
@@ -196,7 +220,7 @@ namespace AssetStudio
m_Header.size = reader.ReadInt64();
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
m_Header.flags = reader.ReadUInt32();
m_Header.flags = (ArchiveFlags)reader.ReadUInt32();
if (m_Header.signature != "UnityFS")
{
reader.ReadByte();
@@ -210,45 +234,51 @@ namespace AssetStudio
{
reader.AlignStream(16);
}
if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd
if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
{
var position = reader.Position;
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
reader.Position = position;
}
else //0x40 kArchiveBlocksAndDirectoryInfoCombined
else //0x40 BlocksAndDirectoryInfoCombined
{
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
}
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
MemoryStream blocksInfoUncompresseddStream;
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
switch (compressionType)
{
default: //None
case CompressionType.None:
{
blocksInfoUncompresseddStream = blocksInfoCompressedStream;
blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
break;
}
case 1: //LZMA
case CompressionType.Lzma:
{
blocksInfoUncompresseddStream = new MemoryStream((int)(m_Header.uncompressedBlocksInfoSize));
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
blocksInfoUncompresseddStream.Position = 0;
blocksInfoCompressedStream.Close();
break;
}
case 2: //LZ4
case 3: //LZ4HC
{
var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
{
decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length);
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
}
blocksInfoUncompresseddStream.Position = 0;
break;
}
case CompressionType.Lz4:
case CompressionType.Lz4HC:
{
var uncompressedBytes = new byte[uncompressedSize];
var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
if (numWrite != uncompressedSize)
{
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
}
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
break;
}
default:
throw new IOException($"Unsupported compression type {compressionType}");
}
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
{
@@ -261,7 +291,7 @@ namespace AssetStudio
{
uncompressedSize = blocksInfoReader.ReadUInt32(),
compressedSize = blocksInfoReader.ReadUInt32(),
flags = blocksInfoReader.ReadUInt16()
flags = (StorageBlockFlags)blocksInfoReader.ReadUInt16()
};
}
@@ -278,34 +308,49 @@ namespace AssetStudio
};
}
}
if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
{
reader.AlignStream(16);
}
}
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
{
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);
break;
}
case 1: //LZMA
case CompressionType.Lzma:
{
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
break;
}
case 2: //LZ4
case 3: //LZ4HC
case CompressionType.Lz4:
case CompressionType.Lz4HC:
{
var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize));
using (var lz4Stream = new Lz4DecoderStream(compressedStream))
var compressedSize = (int)blockInfo.compressedSize;
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
reader.Read(compressedBytes, 0, compressedSize);
var uncompressedSize = (int)blockInfo.uncompressedSize;
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
if (numWrite != uncompressedSize)
{
lz4Stream.CopyTo(blocksStream, blockInfo.uncompressedSize);
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
}
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
BigArrayPool<byte>.Shared.Return(compressedBytes);
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
break;
}
default:
throw new IOException($"Unsupported compression type {compressionType}");
}
}
blocksStream.Position = 0;

View File

@@ -797,6 +797,7 @@ namespace AssetStudio
public ClassIDType typeID;
public byte customType;
public byte isPPtrCurve;
public byte isIntCurve;
public GenericBinding() { }
@@ -816,6 +817,10 @@ namespace AssetStudio
}
customType = reader.ReadByte();
isPPtrCurve = reader.ReadByte();
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{
isIntCurve = reader.ReadByte();
}
reader.AlignStream();
}
}
@@ -909,9 +914,9 @@ namespace AssetStudio
public enum AnimationType
{
kLegacy = 1,
kGeneric = 2,
kHumanoid = 3
Legacy = 1,
Generic = 2,
Humanoid = 3
};
public sealed class AnimationClip : NamedObject
@@ -945,7 +950,7 @@ namespace AssetStudio
else if (version[0] >= 4)//4.0 and up
{
m_AnimationType = (AnimationType)reader.ReadInt32();
if (m_AnimationType == AnimationType.kLegacy)
if (m_AnimationType == AnimationType.Legacy)
m_Legacy = true;
}
else

View File

@@ -9,7 +9,7 @@ namespace AssetStudio
public sealed class AudioClip : NamedObject
{
public int m_Format;
public AudioType m_Type;
public FMODSoundType m_Type;
public bool m_3D;
public bool m_UseHardware;
@@ -36,7 +36,7 @@ namespace AssetStudio
if (version[0] < 5)
{
m_Format = reader.ReadInt32();
m_Type = (AudioType)reader.ReadInt32();
m_Type = (FMODSoundType)reader.ReadInt32();
m_3D = reader.ReadBoolean();
m_UseHardware = reader.ReadBoolean();
reader.AlignStream();
@@ -92,34 +92,51 @@ namespace AssetStudio
}
}
public enum AudioType
public enum FMODSoundType
{
UNKNOWN,
ACC,
AIFF,
UNKNOWN = 0,
ACC = 1,
AIFF = 2,
ASF = 3,
AT3 = 4,
CDDA = 5,
DLS = 6,
FLAC = 7,
FSB = 8,
GCADPCM = 9,
IT = 10,
MIDI = 11,
MOD = 12,
MPEG,
OGGVORBIS,
MPEG = 13,
OGGVORBIS = 14,
PLAYLIST = 15,
RAW = 16,
S3M = 17,
SF2 = 18,
USER = 19,
WAV = 20,
XM,
XMA,
VAG,
AUDIOQUEUE
XM = 21,
XMA = 22,
VAG = 23,
AUDIOQUEUE = 24,
XWMA = 25,
BCWAV = 26,
AT9 = 27,
VORBIS = 28,
MEDIA_FOUNDATION = 29
}
public enum AudioCompressionFormat
{
PCM,
Vorbis,
ADPCM,
MP3,
VAG,
HEVAG,
XMA,
AAC,
GCADPCM,
ATRAC9
PCM = 0,
Vorbis = 1,
ADPCM = 2,
MP3 = 3,
PSMVAG = 4,
HEVAG = 5,
XMA = 6,
AAC = 7,
GCADPCM = 8,
ATRAC9 = 9
}
}

View File

@@ -74,9 +74,18 @@ namespace AssetStudio
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();
}
if (version[0] >= 5) //5.0 and up
{
var m_LightmapFlags = reader.ReadUInt32();
}

View File

@@ -396,14 +396,14 @@ namespace AssetStudio
}
}
public enum GfxPrimitiveType : int
public enum GfxPrimitiveType
{
kPrimitiveTriangles = 0,
kPrimitiveTriangleStrip = 1,
kPrimitiveQuads = 2,
kPrimitiveLines = 3,
kPrimitiveLineStrip = 4,
kPrimitivePoints = 5,
Triangles = 0,
TriangleStrip = 1,
Quads = 2,
Lines = 3,
LineStrip = 4,
Points = 5
};
public class SubMesh
@@ -651,6 +651,11 @@ namespace AssetStudio
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
{
var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
@@ -729,7 +734,7 @@ namespace AssetStudio
}
}
if (reader.endian == EndianType.BigEndian && componentByteSize > 1) //swap bytes
if (reader.Endian == EndianType.BigEndian && componentByteSize > 1) //swap bytes
{
for (var i = 0; i < componentBytes.Length / componentByteSize; i++)
{
@@ -1060,7 +1065,7 @@ namespace AssetStudio
}
var indexCount = m_SubMesh.indexCount;
var topology = m_SubMesh.topology;
if (topology == GfxPrimitiveType.kPrimitiveTriangles)
if (topology == GfxPrimitiveType.Triangles)
{
for (int i = 0; i < indexCount; i += 3)
{
@@ -1069,7 +1074,7 @@ namespace AssetStudio
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 :
uint triIndex = 0;
@@ -1100,7 +1105,7 @@ namespace AssetStudio
//fix indexCount
m_SubMesh.indexCount = triIndex;
}
else if (topology == GfxPrimitiveType.kPrimitiveQuads)
else if (topology == GfxPrimitiveType.Quads)
{
for (int q = 0; q < indexCount; q += 4)
{
@@ -1193,44 +1198,44 @@ namespace AssetStudio
{
public enum VertexChannelFormat
{
kChannelFormatFloat,
kChannelFormatFloat16,
kChannelFormatColor,
kChannelFormatByte,
kChannelFormatUInt32
Float,
Float16,
Color,
Byte,
UInt32
}
public enum VertexFormat2017
{
kVertexFormatFloat,
kVertexFormatFloat16,
kVertexFormatColor,
kVertexFormatUNorm8,
kVertexFormatSNorm8,
kVertexFormatUNorm16,
kVertexFormatSNorm16,
kVertexFormatUInt8,
kVertexFormatSInt8,
kVertexFormatUInt16,
kVertexFormatSInt16,
kVertexFormatUInt32,
kVertexFormatSInt32
Float,
Float16,
Color,
UNorm8,
SNorm8,
UNorm16,
SNorm16,
UInt8,
SInt8,
UInt16,
SInt16,
UInt32,
SInt32
}
public enum VertexFormat
{
kVertexFormatFloat,
kVertexFormatFloat16,
kVertexFormatUNorm8,
kVertexFormatSNorm8,
kVertexFormatUNorm16,
kVertexFormatSNorm16,
kVertexFormatUInt8,
kVertexFormatSInt8,
kVertexFormatUInt16,
kVertexFormatSInt16,
kVertexFormatUInt32,
kVertexFormatSInt32
Float,
Float16,
UNorm8,
SNorm8,
UNorm16,
SNorm16,
UInt8,
SInt8,
UInt16,
SInt16,
UInt32,
SInt32
}
public static VertexFormat ToVertexFormat(int format, int[] version)
@@ -1239,16 +1244,16 @@ namespace AssetStudio
{
switch ((VertexChannelFormat)format)
{
case VertexChannelFormat.kChannelFormatFloat:
return VertexFormat.kVertexFormatFloat;
case VertexChannelFormat.kChannelFormatFloat16:
return VertexFormat.kVertexFormatFloat16;
case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4
return VertexFormat.kVertexFormatUNorm8;
case VertexChannelFormat.kChannelFormatByte:
return VertexFormat.kVertexFormatUInt8;
case VertexChannelFormat.kChannelFormatUInt32: //in 5.x
return VertexFormat.kVertexFormatUInt32;
case VertexChannelFormat.Float:
return VertexFormat.Float;
case VertexChannelFormat.Float16:
return VertexFormat.Float16;
case VertexChannelFormat.Color: //in 4.x is size 4
return VertexFormat.UNorm8;
case VertexChannelFormat.Byte:
return VertexFormat.UInt8;
case VertexChannelFormat.UInt32: //in 5.x
return VertexFormat.UInt32;
default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
@@ -1257,31 +1262,31 @@ namespace AssetStudio
{
switch ((VertexFormat2017)format)
{
case VertexFormat2017.kVertexFormatFloat:
return VertexFormat.kVertexFormatFloat;
case VertexFormat2017.kVertexFormatFloat16:
return VertexFormat.kVertexFormatFloat16;
case VertexFormat2017.kVertexFormatColor:
case VertexFormat2017.kVertexFormatUNorm8:
return VertexFormat.kVertexFormatUNorm8;
case VertexFormat2017.kVertexFormatSNorm8:
return VertexFormat.kVertexFormatSNorm8;
case VertexFormat2017.kVertexFormatUNorm16:
return VertexFormat.kVertexFormatUNorm16;
case VertexFormat2017.kVertexFormatSNorm16:
return VertexFormat.kVertexFormatSNorm16;
case VertexFormat2017.kVertexFormatUInt8:
return VertexFormat.kVertexFormatUInt8;
case VertexFormat2017.kVertexFormatSInt8:
return VertexFormat.kVertexFormatSInt8;
case VertexFormat2017.kVertexFormatUInt16:
return VertexFormat.kVertexFormatUInt16;
case VertexFormat2017.kVertexFormatSInt16:
return VertexFormat.kVertexFormatSInt16;
case VertexFormat2017.kVertexFormatUInt32:
return VertexFormat.kVertexFormatUInt32;
case VertexFormat2017.kVertexFormatSInt32:
return VertexFormat.kVertexFormatSInt32;
case VertexFormat2017.Float:
return VertexFormat.Float;
case VertexFormat2017.Float16:
return VertexFormat.Float16;
case VertexFormat2017.Color:
case VertexFormat2017.UNorm8:
return VertexFormat.UNorm8;
case VertexFormat2017.SNorm8:
return VertexFormat.SNorm8;
case VertexFormat2017.UNorm16:
return VertexFormat.UNorm16;
case VertexFormat2017.SNorm16:
return VertexFormat.SNorm16;
case VertexFormat2017.UInt8:
return VertexFormat.UInt8;
case VertexFormat2017.SInt8:
return VertexFormat.SInt8;
case VertexFormat2017.UInt16:
return VertexFormat.UInt16;
case VertexFormat2017.SInt16:
return VertexFormat.SInt16;
case VertexFormat2017.UInt32:
return VertexFormat.UInt32;
case VertexFormat2017.SInt32:
return VertexFormat.SInt32;
default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
@@ -1297,20 +1302,20 @@ namespace AssetStudio
{
switch (format)
{
case VertexFormat.kVertexFormatFloat:
case VertexFormat.kVertexFormatUInt32:
case VertexFormat.kVertexFormatSInt32:
case VertexFormat.Float:
case VertexFormat.UInt32:
case VertexFormat.SInt32:
return 4u;
case VertexFormat.kVertexFormatFloat16:
case VertexFormat.kVertexFormatUNorm16:
case VertexFormat.kVertexFormatSNorm16:
case VertexFormat.kVertexFormatUInt16:
case VertexFormat.kVertexFormatSInt16:
case VertexFormat.Float16:
case VertexFormat.UNorm16:
case VertexFormat.SNorm16:
case VertexFormat.UInt16:
case VertexFormat.SInt16:
return 2u;
case VertexFormat.kVertexFormatUNorm8:
case VertexFormat.kVertexFormatSNorm8:
case VertexFormat.kVertexFormatUInt8:
case VertexFormat.kVertexFormatSInt8:
case VertexFormat.UNorm8:
case VertexFormat.SNorm8:
case VertexFormat.UInt8:
case VertexFormat.SInt8:
return 1u;
default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
@@ -1319,7 +1324,7 @@ namespace AssetStudio
public static bool IsIntFormat(VertexFormat format)
{
return format >= VertexFormat.kVertexFormatUInt8;
return format >= VertexFormat.UInt8;
}
public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
@@ -1331,22 +1336,22 @@ namespace AssetStudio
{
switch (format)
{
case VertexFormat.kVertexFormatFloat:
case VertexFormat.Float:
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
break;
case VertexFormat.kVertexFormatFloat16:
case VertexFormat.Float16:
result[i] = Half.ToHalf(inputBytes, i * 2);
break;
case VertexFormat.kVertexFormatUNorm8:
case VertexFormat.UNorm8:
result[i] = inputBytes[i] / 255f;
break;
case VertexFormat.kVertexFormatSNorm8:
case VertexFormat.SNorm8:
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
break;
case VertexFormat.kVertexFormatUNorm16:
case VertexFormat.UNorm16:
result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
break;
case VertexFormat.kVertexFormatSNorm16:
case VertexFormat.SNorm16:
result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
break;
}
@@ -1363,16 +1368,16 @@ namespace AssetStudio
{
switch (format)
{
case VertexFormat.kVertexFormatUInt8:
case VertexFormat.kVertexFormatSInt8:
case VertexFormat.UInt8:
case VertexFormat.SInt8:
result[i] = inputBytes[i];
break;
case VertexFormat.kVertexFormatUInt16:
case VertexFormat.kVertexFormatSInt16:
case VertexFormat.UInt16:
case VertexFormat.SInt16:
result[i] = BitConverter.ToInt16(inputBytes, i * 2);
break;
case VertexFormat.kVertexFormatUInt32:
case VertexFormat.kVertexFormatSInt32:
case VertexFormat.UInt32:
case VertexFormat.SInt32:
result[i] = BitConverter.ToInt32(inputBytes, i * 4);
break;
}

View File

@@ -13,7 +13,7 @@ namespace AssetStudio
public PPtr(ObjectReader reader)
{
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;
}

View File

@@ -56,15 +56,14 @@ namespace AssetStudio
}
public enum TextureDimension
{
kTexDimUnknown = -1,
kTexDimNone = 0,
kTexDimAny = 1,
kTexDim2D = 2,
kTexDim3D = 3,
kTexDimCUBE = 4,
kTexDim2DArray = 5,
kTexDimCubeArray = 6,
kTexDimForce32Bit = 2147483647
Unknown = -1,
None = 0,
Any = 1,
Tex2D = 2,
Tex3D = 3,
Cube = 4,
Tex2DArray = 5,
CubeArray = 6
};
public class SerializedTextureProperty
@@ -81,11 +80,12 @@ namespace AssetStudio
public enum SerializedPropertyType
{
kColor = 0,
kVector = 1,
kFloat = 2,
kRange = 3,
kTexture = 4
Color = 0,
Vector = 1,
Float = 2,
Range = 3,
Texture = 4,
Int = 5
};
public class SerializedProperty
@@ -195,11 +195,11 @@ namespace AssetStudio
public enum FogMode
{
kFogUnknown = -1,
kFogDisabled = 0,
kFogLinear = 1,
kFogExp = 2,
kFogExp2 = 3
Unknown = -1,
Disabled = 0,
Linear = 1,
Exp = 2,
Exp2 = 3
};
public class SerializedShaderState
@@ -428,6 +428,7 @@ namespace AssetStudio
if ((version[0] == 2020 && version[1] > 3) ||
(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[2] >= 4)) //2021.1.4f1 and up
{
@@ -453,38 +454,39 @@ namespace AssetStudio
public enum ShaderGpuProgramType
{
kShaderGpuProgramUnknown = 0,
kShaderGpuProgramGLLegacy = 1,
kShaderGpuProgramGLES31AEP = 2,
kShaderGpuProgramGLES31 = 3,
kShaderGpuProgramGLES3 = 4,
kShaderGpuProgramGLES = 5,
kShaderGpuProgramGLCore32 = 6,
kShaderGpuProgramGLCore41 = 7,
kShaderGpuProgramGLCore43 = 8,
kShaderGpuProgramDX9VertexSM20 = 9,
kShaderGpuProgramDX9VertexSM30 = 10,
kShaderGpuProgramDX9PixelSM20 = 11,
kShaderGpuProgramDX9PixelSM30 = 12,
kShaderGpuProgramDX10Level9Vertex = 13,
kShaderGpuProgramDX10Level9Pixel = 14,
kShaderGpuProgramDX11VertexSM40 = 15,
kShaderGpuProgramDX11VertexSM50 = 16,
kShaderGpuProgramDX11PixelSM40 = 17,
kShaderGpuProgramDX11PixelSM50 = 18,
kShaderGpuProgramDX11GeometrySM40 = 19,
kShaderGpuProgramDX11GeometrySM50 = 20,
kShaderGpuProgramDX11HullSM50 = 21,
kShaderGpuProgramDX11DomainSM50 = 22,
kShaderGpuProgramMetalVS = 23,
kShaderGpuProgramMetalFS = 24,
kShaderGpuProgramSPIRV = 25,
kShaderGpuProgramConsoleVS = 26,
kShaderGpuProgramConsoleFS = 27,
kShaderGpuProgramConsoleHS = 28,
kShaderGpuProgramConsoleDS = 29,
kShaderGpuProgramConsoleGS = 30,
kShaderGpuProgramRayTracing = 31,
Unknown = 0,
GLLegacy = 1,
GLES31AEP = 2,
GLES31 = 3,
GLES3 = 4,
GLES = 5,
GLCore32 = 6,
GLCore41 = 7,
GLCore43 = 8,
DX9VertexSM20 = 9,
DX9VertexSM30 = 10,
DX9PixelSM20 = 11,
DX9PixelSM30 = 12,
DX10Level9Vertex = 13,
DX10Level9Pixel = 14,
DX11VertexSM40 = 15,
DX11VertexSM50 = 16,
DX11PixelSM40 = 17,
DX11PixelSM50 = 18,
DX11GeometrySM40 = 19,
DX11GeometrySM50 = 20,
DX11HullSM50 = 21,
DX11DomainSM50 = 22,
MetalVS = 23,
MetalFS = 24,
SPIRV = 25,
ConsoleVS = 26,
ConsoleFS = 27,
ConsoleHS = 28,
ConsoleDS = 29,
ConsoleGS = 30,
RayTracing = 31,
PS5NGGC = 32
};
public class SerializedProgramParameters
@@ -604,8 +606,9 @@ namespace AssetStudio
if ((version[0] == 2020 && version[1] > 3) ||
(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[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);
}
@@ -689,6 +692,7 @@ namespace AssetStudio
{
public SerializedSubProgram[] m_SubPrograms;
public SerializedProgramParameters m_CommonParameters;
public ushort[] m_SerializedKeywordStateMask;
public SerializedProgram(ObjectReader reader)
{
@@ -703,19 +707,26 @@ namespace AssetStudio
if ((version[0] == 2020 && version[1] > 3) ||
(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[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);
}
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
}
public enum PassType
{
kPassTypeNormal = 0,
kPassTypeUse = 1,
kPassTypeGrab = 2
Normal = 0,
Use = 1,
Grab = 2
};
public class SerializedPass
@@ -794,7 +805,7 @@ namespace AssetStudio
m_Name = reader.ReadAlignedString();
m_TextureName = reader.ReadAlignedString();
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();
reader.AlignStream();
@@ -922,32 +933,32 @@ namespace AssetStudio
public enum ShaderCompilerPlatform
{
kShaderCompPlatformNone = -1,
kShaderCompPlatformGL = 0,
kShaderCompPlatformD3D9 = 1,
kShaderCompPlatformXbox360 = 2,
kShaderCompPlatformPS3 = 3,
kShaderCompPlatformD3D11 = 4,
kShaderCompPlatformGLES20 = 5,
kShaderCompPlatformNaCl = 6,
kShaderCompPlatformFlash = 7,
kShaderCompPlatformD3D11_9x = 8,
kShaderCompPlatformGLES3Plus = 9,
kShaderCompPlatformPSP2 = 10,
kShaderCompPlatformPS4 = 11,
kShaderCompPlatformXboxOne = 12,
kShaderCompPlatformPSM = 13,
kShaderCompPlatformMetal = 14,
kShaderCompPlatformOpenGLCore = 15,
kShaderCompPlatformN3DS = 16,
kShaderCompPlatformWiiU = 17,
kShaderCompPlatformVulkan = 18,
kShaderCompPlatformSwitch = 19,
kShaderCompPlatformXboxOneD3D12 = 20,
kShaderCompPlatformGameCoreXboxOne = 21,
kShaderCompPlatformGameCoreScarlett = 22,
kShaderCompPlatformPS5 = 23,
kShaderCompPlatformPS5NGGC = 24,
None = -1,
GL = 0,
D3D9 = 1,
Xbox360 = 2,
PS3 = 3,
D3D11 = 4,
GLES20 = 5,
NaCl = 6,
Flash = 7,
D3D11_9x = 8,
GLES3Plus = 9,
PSP2 = 10,
PS4 = 11,
XboxOne = 12,
PSM = 13,
Metal = 14,
OpenGLCore = 15,
N3DS = 16,
WiiU = 17,
Vulkan = 18,
Switch = 19,
XboxOneD3D12 = 20,
GameCoreXboxOne = 21,
GameCoreScarlett = 22,
PS5 = 23,
PS5NGGC = 24
};
public class Shader : NamedObject
@@ -959,9 +970,9 @@ namespace AssetStudio
//5.5 and up
public SerializedShader m_ParsedForm;
public ShaderCompilerPlatform[] platforms;
public uint[] offsets;
public uint[] compressedLengths;
public uint[] decompressedLengths;
public uint[][] offsets;
public uint[][] compressedLengths;
public uint[][] decompressedLengths;
public byte[] compressedBlob;
public Shader(ObjectReader reader) : base(reader)
@@ -972,15 +983,15 @@ namespace AssetStudio
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
offsets = reader.ReadUInt32ArrayArray();
compressedLengths = reader.ReadUInt32ArrayArray();
decompressedLengths = reader.ReadUInt32ArrayArray();
}
else
{
offsets = reader.ReadUInt32Array();
compressedLengths = reader.ReadUInt32Array();
decompressedLengths = reader.ReadUInt32Array();
offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
}
compressedBlob = reader.ReadUInt8Array();
reader.AlignStream();

View File

@@ -18,23 +18,23 @@ namespace AssetStudio
public enum SpritePackingRotation
{
kSPRNone = 0,
kSPRFlipHorizontal = 1,
kSPRFlipVertical = 2,
kSPRRotate180 = 3,
kSPRRotate90 = 4
None = 0,
FlipHorizontal = 1,
FlipVertical = 2,
Rotate180 = 3,
Rotate90 = 4
};
public enum SpritePackingMode
{
kSPMTight = 0,
kSPMRectangle
Tight = 0,
Rectangle
};
public enum SpriteMeshType
{
kSpriteMeshTypeFullRect,
kSpriteMeshTypeTight
FullRect,
Tight
};
public class SpriteSettings
@@ -197,7 +197,7 @@ namespace AssetStudio
public Vector2 m_Offset;
public Vector4 m_Border;
public float m_PixelsToUnits;
public Vector2 m_Pivot;
public Vector2 m_Pivot = new Vector2(0.5f, 0.5f);
public uint m_Extrude;
public bool m_IsPolygon;
public KeyValuePair<Guid, long> m_RenderDataKey;

View File

@@ -46,6 +46,7 @@ namespace AssetStudio
{
public PPtr<Sprite>[] m_PackedSprites;
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
public bool m_IsVariant;
public SpriteAtlas(ObjectReader reader) : base(reader)
{
@@ -67,8 +68,9 @@ namespace AssetStudio
var value = new SpriteAtlasData(reader);
m_RenderDataMap.Add(new KeyValuePair<Guid, long>(first, second), value);
}
//string m_Tag
//bool m_IsVariant
var m_Tag = reader.ReadAlignedString();
m_IsVariant = reader.ReadBoolean();
reader.AlignStream();
}
}
}

View File

@@ -151,10 +151,13 @@ namespace AssetStudio
RGB24,
RGBA32,
ARGB32,
RGB565 = 7,
R16 = 9,
ARGBFloat,
RGB565,
BGR24,
R16,
DXT1,
DXT5 = 12,
DXT3,
DXT5,
RGBA4444,
BGRA32,
RHalf,
@@ -165,11 +168,12 @@ namespace AssetStudio
RGBAFloat,
YUY2,
RGB9e5Float,
BC4 = 26,
BC5,
BC6H = 24,
RGBFloat,
BC6H,
BC7,
DXT1Crunched = 28,
BC4,
BC5,
DXT1Crunched,
DXT5Crunched,
PVRTC_RGB2,
PVRTC_RGBA2,

View File

@@ -1,23 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Buffers.Binary;
using System.IO;
namespace AssetStudio
{
public enum EndianType
{
LittleEndian,
BigEndian
}
public class EndianBinaryReader : BinaryReader
{
public EndianType endian;
private readonly byte[] buffer;
public EndianType Endian;
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
{
this.endian = endian;
Endian = endian;
buffer = new byte[8];
}
public long Position
@@ -28,88 +24,82 @@ namespace AssetStudio
public override short ReadInt16()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(2);
Array.Reverse(buff);
return BitConverter.ToInt16(buff, 0);
Read(buffer, 0, 2);
return BinaryPrimitives.ReadInt16BigEndian(buffer);
}
return base.ReadInt16();
}
public override int ReadInt32()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToInt32(buff, 0);
Read(buffer, 0, 4);
return BinaryPrimitives.ReadInt32BigEndian(buffer);
}
return base.ReadInt32();
}
public override long ReadInt64()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToInt64(buff, 0);
Read(buffer, 0, 8);
return BinaryPrimitives.ReadInt64BigEndian(buffer);
}
return base.ReadInt64();
}
public override ushort ReadUInt16()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(2);
Array.Reverse(buff);
return BitConverter.ToUInt16(buff, 0);
Read(buffer, 0, 2);
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
}
return base.ReadUInt16();
}
public override uint ReadUInt32()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToUInt32(buff, 0);
Read(buffer, 0, 4);
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
}
return base.ReadUInt32();
}
public override ulong ReadUInt64()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToUInt64(buff, 0);
Read(buffer, 0, 8);
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
}
return base.ReadUInt64();
}
public override float ReadSingle()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToSingle(buff, 0);
Read(buffer, 0, 4);
Array.Reverse(buffer, 0, 4);
return BitConverter.ToSingle(buffer, 0);
}
return base.ReadSingle();
}
public override double ReadDouble()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToUInt64(buff, 0);
Read(buffer, 0, 8);
Array.Reverse(buffer);
return BitConverter.ToDouble(buffer, 0);
}
return base.ReadDouble();
}

14
AssetStudio/EndianType.cs Normal file
View File

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

View File

@@ -11,6 +11,8 @@ namespace AssetStudio
private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
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)) { }
@@ -36,7 +38,7 @@ namespace AssetStudio
return FileType.WebFile;
default:
{
var magic = ReadBytes(2);
byte[] magic = ReadBytes(2);
Position = 0;
if (gzipMagic.SequenceEqual(magic))
{
@@ -53,10 +55,11 @@ namespace AssetStudio
{
return FileType.AssetsFile;
}
else
{
return FileType.ResourceFile;
}
magic = ReadBytes(4);
Position = 0;
if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
return FileType.ZipFile;
return FileType.ResourceFile;
}
}
}

View File

@@ -13,6 +13,7 @@ namespace AssetStudio
WebFile,
ResourceFile,
GZipFile,
BrotliFile
BrotliFile,
ZipFile
}
}

View File

@@ -73,6 +73,28 @@ namespace AssetStudio
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)
{
if (Name == name)

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

View File

@@ -1,540 +0,0 @@
#define CHECK_ARGS
#define CHECK_EOF
//#define LOCAL_SHADOW
using System;
using System.IO;
namespace Lz4
{
public class Lz4DecoderStream : Stream
{
public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
{
Reset(input, inputLength);
}
private void Reset(Stream input, long inputLength = long.MaxValue)
{
this.inputLength = inputLength;
this.input = input;
phase = DecodePhase.ReadToken;
decodeBufferPos = 0;
litLen = 0;
matLen = 0;
matDst = 0;
inBufPos = DecBufLen;
inBufEnd = DecBufLen;
}
protected override void Dispose(bool disposing)
{
try
{
if (disposing && input != null)
{
input.Close();
}
input = null;
decodeBuffer = null;
}
finally
{
base.Dispose(disposing);
}
}
private long inputLength;
private Stream input;
//because we might not be able to match back across invocations,
//we have to keep the last window's worth of bytes around for reuse
//we use a circular buffer for this - every time we write into this
//buffer, we also write the same into our output buffer
private const int DecBufLen = 0x10000;
private const int DecBufMask = 0xFFFF;
private const int InBufLen = 128;
private byte[] decodeBuffer = new byte[DecBufLen + InBufLen];
private int decodeBufferPos, inBufPos, inBufEnd;
//we keep track of which phase we're in so that we can jump right back
//into the correct part of decoding
private DecodePhase phase;
private enum DecodePhase
{
ReadToken,
ReadExLiteralLength,
CopyLiteral,
ReadOffset,
ReadExMatchLength,
CopyMatch,
}
//state within interruptable phases and across phase boundaries is
//kept here - again, so that we can punt out and restart freely
private int litLen, matLen, matDst;
public override int Read(byte[] buffer, int offset, int count)
{
#if CHECK_ARGS
if (buffer == null)
throw new ArgumentNullException("buffer");
if (offset < 0 || count < 0 || buffer.Length - count < offset)
throw new ArgumentOutOfRangeException();
if (input == null)
throw new InvalidOperationException();
#endif
int nRead, nToRead = count;
var decBuf = decodeBuffer;
//the stringy gotos are obnoxious, but their purpose is to
//make it *blindingly* obvious how the state machine transitions
//back and forth as it reads - remember, we can yield out of
//this routine in several places, and we must be able to re-enter
//and pick up where we left off!
#if LOCAL_SHADOW
var phase = this.phase;
var inBufPos = this.inBufPos;
var inBufEnd = this.inBufEnd;
#endif
switch (phase)
{
case DecodePhase.ReadToken:
goto readToken;
case DecodePhase.ReadExLiteralLength:
goto readExLiteralLength;
case DecodePhase.CopyLiteral:
goto copyLiteral;
case DecodePhase.ReadOffset:
goto readOffset;
case DecodePhase.ReadExMatchLength:
goto readExMatchLength;
case DecodePhase.CopyMatch:
goto copyMatch;
}
readToken:
int tok;
if (inBufPos < inBufEnd)
{
tok = decBuf[inBufPos++];
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
tok = ReadByteCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (tok == -1)
goto finish;
#endif
}
litLen = tok >> 4;
matLen = (tok & 0xF) + 4;
switch (litLen)
{
case 0:
phase = DecodePhase.ReadOffset;
goto readOffset;
case 0xF:
phase = DecodePhase.ReadExLiteralLength;
goto readExLiteralLength;
default:
phase = DecodePhase.CopyLiteral;
goto copyLiteral;
}
readExLiteralLength:
int exLitLen;
if (inBufPos < inBufEnd)
{
exLitLen = decBuf[inBufPos++];
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
exLitLen = ReadByteCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (exLitLen == -1)
goto finish;
#endif
}
litLen += exLitLen;
if (exLitLen == 255)
goto readExLiteralLength;
phase = DecodePhase.CopyLiteral;
goto copyLiteral;
copyLiteral:
int nReadLit = litLen < nToRead ? litLen : nToRead;
if (nReadLit != 0)
{
if (inBufPos + nReadLit <= inBufEnd)
{
int ofs = offset;
for (int c = nReadLit; c-- != 0;)
buffer[ofs++] = decBuf[inBufPos++];
nRead = nReadLit;
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
nRead = ReadCore(buffer, offset, nReadLit);
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (nRead == 0)
goto finish;
#endif
}
offset += nRead;
nToRead -= nRead;
litLen -= nRead;
if (litLen != 0)
goto copyLiteral;
}
if (nToRead == 0)
goto finish;
phase = DecodePhase.ReadOffset;
goto readOffset;
readOffset:
if (inBufPos + 1 < inBufEnd)
{
matDst = (decBuf[inBufPos + 1] << 8) | decBuf[inBufPos];
inBufPos += 2;
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
matDst = ReadOffsetCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (matDst == -1)
goto finish;
#endif
}
if (matLen == 15 + 4)
{
phase = DecodePhase.ReadExMatchLength;
goto readExMatchLength;
}
else
{
phase = DecodePhase.CopyMatch;
goto copyMatch;
}
readExMatchLength:
int exMatLen;
if (inBufPos < inBufEnd)
{
exMatLen = decBuf[inBufPos++];
}
else
{
#if LOCAL_SHADOW
this.inBufPos = inBufPos;
#endif
exMatLen = ReadByteCore();
#if LOCAL_SHADOW
inBufPos = this.inBufPos;
inBufEnd = this.inBufEnd;
#endif
#if CHECK_EOF
if (exMatLen == -1)
goto finish;
#endif
}
matLen += exMatLen;
if (exMatLen == 255)
goto readExMatchLength;
phase = DecodePhase.CopyMatch;
goto copyMatch;
copyMatch:
int nCpyMat = matLen < nToRead ? matLen : nToRead;
if (nCpyMat != 0)
{
nRead = count - nToRead;
int bufDst = matDst - nRead;
if (bufDst > 0)
{
//offset is fairly far back, we need to pull from the buffer
int bufSrc = decodeBufferPos - bufDst;
if (bufSrc < 0)
bufSrc += DecBufLen;
int bufCnt = bufDst < nCpyMat ? bufDst : nCpyMat;
for (int c = bufCnt; c-- != 0;)
buffer[offset++] = decBuf[bufSrc++ & DecBufMask];
}
else
{
bufDst = 0;
}
int sOfs = offset - matDst;
for (int i = bufDst; i < nCpyMat; i++)
buffer[offset++] = buffer[sOfs++];
nToRead -= nCpyMat;
matLen -= nCpyMat;
}
if (nToRead == 0)
goto finish;
phase = DecodePhase.ReadToken;
goto readToken;
finish:
nRead = count - nToRead;
int nToBuf = nRead < DecBufLen ? nRead : DecBufLen;
int repPos = offset - nToBuf;
if (nToBuf == DecBufLen)
{
Buffer.BlockCopy(buffer, repPos, decBuf, 0, DecBufLen);
decodeBufferPos = 0;
}
else
{
int decPos = decodeBufferPos;
while (nToBuf-- != 0)
decBuf[decPos++ & DecBufMask] = buffer[repPos++];
decodeBufferPos = decPos & DecBufMask;
}
#if LOCAL_SHADOW
this.phase = phase;
this.inBufPos = inBufPos;
#endif
return nRead;
}
private int ReadByteCore()
{
var buf = decodeBuffer;
if (inBufPos == inBufEnd)
{
int nRead = input.Read(buf, DecBufLen,
InBufLen < inputLength ? InBufLen : (int)inputLength);
#if CHECK_EOF
if (nRead == 0)
return -1;
#endif
inputLength -= nRead;
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead;
}
return buf[inBufPos++];
}
private int ReadOffsetCore()
{
var buf = decodeBuffer;
if (inBufPos == inBufEnd)
{
int nRead = input.Read(buf, DecBufLen,
InBufLen < inputLength ? InBufLen : (int)inputLength);
#if CHECK_EOF
if (nRead == 0)
return -1;
#endif
inputLength -= nRead;
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead;
}
if (inBufEnd - inBufPos == 1)
{
buf[DecBufLen] = buf[inBufPos];
int nRead = input.Read(buf, DecBufLen + 1,
InBufLen - 1 < inputLength ? InBufLen - 1 : (int)inputLength);
#if CHECK_EOF
if (nRead == 0)
{
inBufPos = DecBufLen;
inBufEnd = DecBufLen + 1;
return -1;
}
#endif
inputLength -= nRead;
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead + 1;
}
int ret = (buf[inBufPos + 1] << 8) | buf[inBufPos];
inBufPos += 2;
return ret;
}
private int ReadCore(byte[] buffer, int offset, int count)
{
int nToRead = count;
var buf = decodeBuffer;
int inBufLen = inBufEnd - inBufPos;
int fromBuf = nToRead < inBufLen ? nToRead : inBufLen;
if (fromBuf != 0)
{
var bufPos = inBufPos;
for (int c = fromBuf; c-- != 0;)
buffer[offset++] = buf[bufPos++];
inBufPos = bufPos;
nToRead -= fromBuf;
}
if (nToRead != 0)
{
int nRead;
if (nToRead >= InBufLen)
{
nRead = input.Read(buffer, offset,
nToRead < inputLength ? nToRead : (int)inputLength);
nToRead -= nRead;
}
else
{
nRead = input.Read(buf, DecBufLen,
InBufLen < inputLength ? InBufLen : (int)inputLength);
inBufPos = DecBufLen;
inBufEnd = DecBufLen + nRead;
fromBuf = nToRead < nRead ? nToRead : nRead;
var bufPos = inBufPos;
for (int c = fromBuf; c-- != 0;)
buffer[offset++] = buf[bufPos++];
inBufPos = bufPos;
nToRead -= fromBuf;
}
inputLength -= nRead;
}
return count - nToRead;
}
#region Stream internals
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override void Flush()
{
}
public override long Length => throw new NotSupportedException();
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
#endregion
}
}

View File

@@ -20,7 +20,7 @@ namespace AssetStudio
public int[] version => assetsFile.version;
public BuildType buildType => assetsFile.buildType;
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.endian)
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian)
{
this.assetsFile = assetsFile;
m_PathID = objectInfo.m_PathID;

View File

@@ -1,8 +1,10 @@
namespace AssetStudio
using System;
namespace AssetStudio
{
public static class Progress
{
public static IProgress Default = new DummyProgress();
public static IProgress<int> Default = new Progress<int>();
private static int preValue;
public static void Reset()

View File

@@ -11,6 +11,8 @@ namespace AssetStudio
private long size;
private BinaryReader reader;
public int Size { get => (int)size; }
public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
{
needSearch = true;
@@ -69,6 +71,13 @@ namespace AssetStudio
return binaryReader.ReadBytes((int)size);
}
public void GetData(byte[] buff)
{
var binaryReader = GetReader();
binaryReader.BaseStream.Position = offset;
binaryReader.Read(buff, 0, (int)size);
}
public void WriteData(string path)
{
var binaryReader = GetReader();

View File

@@ -45,7 +45,7 @@ namespace AssetStudio
header.m_Version = (SerializedFileFormatVersion)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_Reserved = reader.ReadBytes(3);
@@ -57,7 +57,7 @@ namespace AssetStudio
m_FileEndianess = reader.ReadByte();
}
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
{
header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadInt64();
@@ -68,14 +68,14 @@ namespace AssetStudio
// ReadMetadata
if (m_FileEndianess == 0)
{
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();
SetVersion(unityVersion);
}
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_8)
if (header.m_Version >= SerializedFileFormatVersion.Unknown_8)
{
m_TargetPlatform = (BuildTarget)reader.ReadInt32();
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
@@ -83,7 +83,7 @@ namespace AssetStudio
m_TargetPlatform = BuildTarget.UnknownPlatform;
}
}
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
{
m_EnableTypeTree = reader.ReadBoolean();
}
@@ -96,7 +96,7 @@ namespace AssetStudio
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();
}
@@ -113,7 +113,7 @@ namespace AssetStudio
{
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();
}
@@ -123,7 +123,7 @@ namespace AssetStudio
objectInfo.m_PathID = reader.ReadInt64();
}
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
objectInfo.byteStart = reader.ReadInt64();
else
objectInfo.byteStart = reader.ReadUInt32();
@@ -131,7 +131,7 @@ namespace AssetStudio
objectInfo.byteStart += header.m_DataOffset;
objectInfo.byteSize = reader.ReadUInt32();
objectInfo.typeID = reader.ReadInt32();
if (header.m_Version < SerializedFileFormatVersion.kRefactoredClassId)
if (header.m_Version < SerializedFileFormatVersion.RefactoredClassId)
{
objectInfo.classID = reader.ReadUInt16();
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
@@ -142,24 +142,24 @@ namespace AssetStudio
objectInfo.serializedType = type;
objectInfo.classID = type.classID;
}
if (header.m_Version < SerializedFileFormatVersion.kHasScriptTypeIndex)
if (header.m_Version < SerializedFileFormatVersion.HasScriptTypeIndex)
{
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();
if (objectInfo.serializedType != null)
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();
}
m_Objects.Add(objectInfo);
}
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex)
if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex)
{
int scriptCount = reader.ReadInt32();
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
@@ -167,7 +167,7 @@ namespace AssetStudio
{
var m_ScriptType = new LocalSerializedObjectIdentifier();
m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
if (header.m_Version < SerializedFileFormatVersion.kUnknown_14)
if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
{
m_ScriptType.localIdentifierInFile = reader.ReadInt32();
}
@@ -185,11 +185,11 @@ namespace AssetStudio
for (int i = 0; i < externalsCount; i++)
{
var m_External = new FileIdentifier();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_6)
if (header.m_Version >= SerializedFileFormatVersion.Unknown_6)
{
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.type = reader.ReadInt32();
@@ -199,7 +199,7 @@ namespace AssetStudio
m_Externals.Add(m_External);
}
if (header.m_Version >= SerializedFileFormatVersion.kSupportsRefObject)
if (header.m_Version >= SerializedFileFormatVersion.SupportsRefObject)
{
int refTypesCount = reader.ReadInt32();
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();
}
@@ -235,23 +235,23 @@ namespace AssetStudio
type.classID = reader.ReadInt32();
if (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId)
if (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId)
{
type.m_IsStrippedType = reader.ReadBoolean();
}
if (header.m_Version >= SerializedFileFormatVersion.kRefactorTypeData)
if (header.m_Version >= SerializedFileFormatVersion.RefactorTypeData)
{
type.m_ScriptTypeIndex = reader.ReadInt16();
}
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
{
if (isRefType && type.m_ScriptTypeIndex >= 0)
{
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);
}
@@ -262,7 +262,7 @@ namespace AssetStudio
{
type.m_Type = new TypeTree();
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);
}
@@ -270,7 +270,7 @@ namespace AssetStudio
{
ReadTypeTree(type.m_Type);
}
if (header.m_Version >= SerializedFileFormatVersion.kStoresTypeDependencies)
if (header.m_Version >= SerializedFileFormatVersion.StoresTypeDependencies)
{
if (isRefType)
{
@@ -296,17 +296,17 @@ namespace AssetStudio
typeTreeNode.m_Type = reader.ReadStringToNull();
typeTreeNode.m_Name = reader.ReadStringToNull();
typeTreeNode.m_ByteSize = reader.ReadInt32();
if (header.m_Version == SerializedFileFormatVersion.kUnknown_2)
if (header.m_Version == SerializedFileFormatVersion.Unknown_2)
{
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_TypeFlags = 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();
}
@@ -334,7 +334,7 @@ namespace AssetStudio
typeTreeNode.m_ByteSize = reader.ReadInt32();
typeTreeNode.m_Index = reader.ReadInt32();
typeTreeNode.m_MetaFlag = reader.ReadInt32();
if (header.m_Version >= SerializedFileFormatVersion.kTypeTreeNodeWithTypeFlags)
if (header.m_Version >= SerializedFileFormatVersion.TypeTreeNodeWithTypeFlags)
{
typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
}

View File

@@ -8,80 +8,80 @@ namespace AssetStudio
{
public enum SerializedFileFormatVersion
{
kUnsupported = 1,
kUnknown_2 = 2,
kUnknown_3 = 3,
Unsupported = 1,
Unknown_2 = 2,
Unknown_3 = 3,
/// <summary>
/// 1.2.0 to 2.0.0
/// </summary>
kUnknown_5 = 5,
Unknown_5 = 5,
/// <summary>
/// 2.1.0 to 2.6.1
/// </summary>
kUnknown_6 = 6,
Unknown_6 = 6,
/// <summary>
/// 3.0.0b
/// </summary>
kUnknown_7 = 7,
Unknown_7 = 7,
/// <summary>
/// 3.0.0 to 3.4.2
/// </summary>
kUnknown_8 = 8,
Unknown_8 = 8,
/// <summary>
/// 3.5.0 to 4.7.2
/// </summary>
kUnknown_9 = 9,
Unknown_9 = 9,
/// <summary>
/// 5.0.0aunk1
/// </summary>
kUnknown_10 = 10,
Unknown_10 = 10,
/// <summary>
/// 5.0.0aunk2
/// </summary>
kHasScriptTypeIndex = 11,
HasScriptTypeIndex = 11,
/// <summary>
/// 5.0.0aunk3
/// </summary>
kUnknown_12 = 12,
Unknown_12 = 12,
/// <summary>
/// 5.0.0aunk4
/// </summary>
kHasTypeTreeHashes = 13,
HasTypeTreeHashes = 13,
/// <summary>
/// 5.0.0unk
/// </summary>
kUnknown_14 = 14,
Unknown_14 = 14,
/// <summary>
/// 5.0.1 to 5.4.0
/// </summary>
kSupportsStrippedObject = 15,
SupportsStrippedObject = 15,
/// <summary>
/// 5.5.0a
/// </summary>
kRefactoredClassId = 16,
RefactoredClassId = 16,
/// <summary>
/// 5.5.0unk to 2018.4
/// </summary>
kRefactorTypeData = 17,
RefactorTypeData = 17,
/// <summary>
/// 2019.1a
/// </summary>
kRefactorShareableTypeTreeData = 18,
RefactorShareableTypeTreeData = 18,
/// <summary>
/// 2019.1unk
/// </summary>
kTypeTreeNodeWithTypeFlags = 19,
TypeTreeNodeWithTypeFlags = 19,
/// <summary>
/// 2019.2
/// </summary>
kSupportsRefObject = 20,
SupportsRefObject = 20,
/// <summary>
/// 2019.3 to 2019.4
/// </summary>
kStoresTypeDependencies = 21,
StoresTypeDependencies = 21,
/// <summary>
/// 2020.1 to x
/// </summary>
kLargeFilesSupport = 22
LargeFilesSupport = 22
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text;
@@ -39,9 +40,11 @@ namespace AssetStudio
value = reader.ReadSByte();
break;
case "UInt8":
case "char":
value = reader.ReadByte();
break;
case "char":
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
break;
case "short":
case "SInt16":
value = reader.ReadInt16();
@@ -81,7 +84,8 @@ namespace AssetStudio
append = false;
var str = reader.ReadAlignedString();
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;
case "map":
{
@@ -190,9 +194,11 @@ namespace AssetStudio
value = reader.ReadSByte();
break;
case "UInt8":
case "char":
value = reader.ReadByte();
break;
case "char":
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
break;
case "short":
case "SInt16":
value = reader.ReadInt16();
@@ -230,7 +236,8 @@ namespace AssetStudio
break;
case "string":
value = reader.ReadAlignedString();
i += 3;
var toSkip = GetNodes(m_Nodes, i);
i += toSkip.Count - 1;
break;
case "map":
{

View File

@@ -17,7 +17,7 @@ namespace AssetStudio
public WebFile(EndianBinaryReader reader)
{
reader.endian = EndianType.LittleEndian;
reader.Endian = EndianType.LittleEndian;
var signature = reader.ReadStringToNull();
var headLength = reader.ReadInt32();
var dataList = new List<WebData>();

View File

@@ -29,26 +29,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
@@ -100,14 +100,14 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
@@ -119,7 +119,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
@@ -128,7 +128,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -137,14 +137,14 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
@@ -156,7 +156,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
@@ -165,7 +165,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View File

@@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<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>
<ItemGroup>

View File

@@ -2,13 +2,14 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net472</TargetFramework>
<TargetFrameworks>net472;net5.0-windows;net6.0-windows</TargetFrameworks>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright>
<Copyright>Copyright © Perfare 2018-2022</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>
@@ -51,16 +52,33 @@
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
<PackageReference Include="OpenTK" Version="4.6.7" />
<Reference Include="OpenTK.WinForms">
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="OpenTK" Version="3.1.0" />
<PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
</ItemGroup>
<Target Name="CustomAfterBuild" AfterTargets="AfterBuild">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<Target Name="CopyExtraFiles" AfterTargets="AfterBuild">
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
</Target>
<Target Name="PublishExtraFiles" AfterTargets="Publish">
<Copy SourceFiles="$(TargetDir)x86\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x64\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x86\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x64\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
</Target>
</Project>

View File

@@ -819,20 +819,21 @@
//
// FMODtimerLabel
//
this.FMODtimerLabel.AutoSize = true;
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODtimerLabel.Location = new System.Drawing.Point(404, 235);
this.FMODtimerLabel.Location = new System.Drawing.Point(460, 235);
this.FMODtimerLabel.Name = "FMODtimerLabel";
this.FMODtimerLabel.Size = new System.Drawing.Size(155, 12);
this.FMODtimerLabel.Size = new System.Drawing.Size(95, 12);
this.FMODtimerLabel.TabIndex = 7;
this.FMODtimerLabel.Text = "0:00.0 / 0:00.0";
this.FMODtimerLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// FMODstatusLabel
//
this.FMODstatusLabel.AutoSize = true;
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODstatusLabel.Location = new System.Drawing.Point(213, 235);
this.FMODstatusLabel.Name = "FMODstatusLabel";
this.FMODstatusLabel.Size = new System.Drawing.Size(50, 12);
this.FMODstatusLabel.Size = new System.Drawing.Size(47, 12);
this.FMODstatusLabel.TabIndex = 6;
this.FMODstatusLabel.Text = "Stopped";
//
@@ -1065,8 +1066,6 @@
// AssetStudioGUIForm
//
this.AllowDrop = true;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1264, 681);
this.Controls.Add(this.splitContainer1);
this.Controls.Add(this.menuStrip1);

View File

@@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Globalization;
using System.IO;
@@ -19,17 +18,21 @@ using System.Timers;
using System.Windows.Forms;
using static AssetStudioGUI.Studio;
using Font = AssetStudio.Font;
using ImageFormat = AssetStudio.ImageFormat;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
#if NET472
using Vector3 = OpenTK.Vector3;
using Vector4 = OpenTK.Vector4;
#else
using Vector3 = OpenTK.Mathematics.Vector3;
using Vector4 = OpenTK.Mathematics.Vector4;
using Matrix4 = OpenTK.Mathematics.Matrix4;
#endif
namespace AssetStudioGUI
{
partial class AssetStudioGUIForm : Form
{
private AssetItem lastSelectedItem;
private Bitmap imageTexture;
private DirectBitmap imageTexture;
private string tempClipboard;
private FMOD.System system;
@@ -104,7 +107,7 @@ namespace AssetStudioGUI
logger = new GUILogger(StatusStripUpdate);
Logger.Default = logger;
Progress.Default = new GUIProgress(SetProgressBarValue);
Progress.Default = new Progress<int>(SetProgressBarValue);
Studio.StatusStripUpdate = StatusStripUpdate;
}
@@ -138,7 +141,7 @@ namespace AssetStudioGUI
private async void loadFile_Click(object sender, EventArgs e)
{
openFileDialog1.InitialDirectory = openDirectoryBackup;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{
ResetForm();
openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
@@ -164,7 +167,7 @@ namespace AssetStudioGUI
private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.Title = "Select the save folder";
@@ -219,10 +222,6 @@ namespace AssetStudioGUI
sceneTreeView.BeginUpdate();
sceneTreeView.Nodes.AddRange(treeNodeCollection.ToArray());
foreach (var node in treeNodeCollection)
{
node.HideCheckBox();
}
sceneTreeView.EndUpdate();
treeNodeCollection.Clear();
@@ -390,7 +389,7 @@ namespace AssetStudioGUI
{
if (enablePreview.Checked && imageTexture != null)
{
previewPanel.BackgroundImage = imageTexture;
previewPanel.BackgroundImage = imageTexture.Bitmap;
}
else
{
@@ -458,7 +457,7 @@ namespace AssetStudioGUI
private void showExpOpt_Click(object sender, EventArgs e)
{
var exportOpt = new ExportOptions();
exportOpt.ShowDialog();
exportOpt.ShowDialog(this);
}
private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
@@ -753,10 +752,11 @@ namespace AssetStudioGUI
private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D)
{
var stream = m_Texture2D.ConvertToStream(ImageFormat.Png, true);
if (stream != null)
var image = m_Texture2D.ConvertToImage(true);
if (image != null)
{
var bitmap = new Bitmap(stream);
var bitmap = new DirectBitmap(image.ConvertToBytes(), m_Texture2D.m_Width, m_Texture2D.m_Height);
image.Dispose();
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
{
@@ -784,13 +784,11 @@ namespace AssetStudioGUI
assetItem.InfoText += "None";
if (validChannel != 4)
{
var bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
var bytes = new byte[bitmap.Width * bitmap.Height * 4];
Marshal.Copy(bmpData.Scan0, bytes, 0, bytes.Length);
for (int i = 0; i < bmpData.Height; i++)
var bytes = bitmap.Bits;
for (int i = 0; i < bitmap.Height; i++)
{
int offset = Math.Abs(bmpData.Stride) * i;
for (int j = 0; j < bmpData.Width; j++)
int offset = Math.Abs(bitmap.Stride) * i;
for (int j = 0; j < bitmap.Width; j++)
{
bytes[offset] = textureChannels[0] ? bytes[offset] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue;
bytes[offset + 1] = textureChannels[1] ? bytes[offset + 1] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue;
@@ -799,8 +797,6 @@ namespace AssetStudioGUI
offset += 4;
}
}
Marshal.Copy(bytes, 0, bmpData.Scan0, bytes.Length);
bitmap.UnlockBits(bmpData);
}
PreviewTexture(bitmap);
@@ -820,40 +816,40 @@ namespace AssetStudioGUI
{
switch (m_AudioClip.m_Type)
{
case AudioType.ACC:
case FMODSoundType.ACC:
assetItem.InfoText += "Acc";
break;
case AudioType.AIFF:
case FMODSoundType.AIFF:
assetItem.InfoText += "AIFF";
break;
case AudioType.IT:
case FMODSoundType.IT:
assetItem.InfoText += "Impulse tracker";
break;
case AudioType.MOD:
case FMODSoundType.MOD:
assetItem.InfoText += "Protracker / Fasttracker MOD";
break;
case AudioType.MPEG:
case FMODSoundType.MPEG:
assetItem.InfoText += "MP2/MP3 MPEG";
break;
case AudioType.OGGVORBIS:
case FMODSoundType.OGGVORBIS:
assetItem.InfoText += "Ogg vorbis";
break;
case AudioType.S3M:
case FMODSoundType.S3M:
assetItem.InfoText += "ScreamTracker 3";
break;
case AudioType.WAV:
case FMODSoundType.WAV:
assetItem.InfoText += "Microsoft WAV";
break;
case AudioType.XM:
case FMODSoundType.XM:
assetItem.InfoText += "FastTracker 2 XM";
break;
case AudioType.XMA:
case FMODSoundType.XMA:
assetItem.InfoText += "Xbox360 XMA";
break;
case AudioType.VAG:
case FMODSoundType.VAG:
assetItem.InfoText += "PlayStation Portable ADPCM";
break;
case AudioType.AUDIOQUEUE:
case FMODSoundType.AUDIOQUEUE:
assetItem.InfoText += "iPhone";
break;
default:
@@ -877,7 +873,7 @@ namespace AssetStudioGUI
case AudioCompressionFormat.MP3:
assetItem.InfoText += "MP3";
break;
case AudioCompressionFormat.VAG:
case AudioCompressionFormat.PSMVAG:
assetItem.InfoText += "PlayStation Portable ADPCM";
break;
case AudioCompressionFormat.HEVAG:
@@ -1164,10 +1160,11 @@ namespace AssetStudioGUI
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
{
var stream = m_Sprite.GetImage(ImageFormat.Png);
if (stream != null)
var image = m_Sprite.GetImage();
if (image != null)
{
var bitmap = new Bitmap(stream);
var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);
image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
PreviewTexture(bitmap);
}
@@ -1177,11 +1174,11 @@ namespace AssetStudioGUI
}
}
private void PreviewTexture(Bitmap bitmap)
private void PreviewTexture(DirectBitmap bitmap)
{
imageTexture?.Dispose();
imageTexture = bitmap;
previewPanel.BackgroundImage = imageTexture;
previewPanel.BackgroundImage = imageTexture.Bitmap;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else
@@ -1232,6 +1229,7 @@ namespace AssetStudioGUI
classesListView.Groups.Clear();
previewPanel.BackgroundImage = Properties.Resources.preview;
imageTexture?.Dispose();
imageTexture = null;
previewPanel.BackgroundImageLayout = ImageLayout.Center;
assetInfoLabel.Visible = false;
assetInfoLabel.Text = null;
@@ -1382,25 +1380,32 @@ namespace AssetStudioGUI
{
var gameObjects = new List<GameObject>();
GetSelectedParentNode(sceneTreeView.Nodes, gameObjects);
var saveFileDialog = new SaveFileDialog();
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)
if (gameObjects.Count > 0)
{
saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName);
var exportPath = saveFileDialog.FileName;
List<AssetItem> animationList = null;
if (animation)
var saveFileDialog = new SaveFileDialog();
saveFileDialog.FileName = gameObjects[0].m_Name + " (merge).fbx";
saveFileDialog.AddExtension = false;
saveFileDialog.Filter = "Fbx file (*.fbx)|*.fbx";
saveFileDialog.InitialDirectory = saveDirectoryBackup;
if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
{
animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList();
if (animationList.Count == 0)
saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName);
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.");
}
}
}

View File

@@ -7,11 +7,6 @@ namespace AssetStudioGUI
{
public GameObject gameObject;
public GameObjectTreeNode(string name)
{
Text = name;
}
public GameObjectTreeNode(GameObject gameObject)
{
this.gameObject = gameObject;

View File

@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;
@@ -15,12 +14,13 @@ namespace AssetStudioGUI
internal DialogResult ShowDialog(IWin32Window owner = null)
{
//#if NETFRAMEWORK
if (Environment.OSVersion.Version.Major >= 6)
{
return ShowVistaDialog(owner);
}
return ShowLegacyDialog(owner);
//#endif
return ShowFolderBrowserDialog(owner);
}
private DialogResult ShowVistaDialog(IWin32Window owner)
@@ -74,7 +74,7 @@ namespace AssetStudioGUI
return DialogResult.Cancel;
}
private DialogResult ShowLegacyDialog(IWin32Window owner)
private DialogResult ShowFolderBrowserDialog(IWin32Window owner)
{
using (var frm = new FolderBrowserDialog())
{
@@ -82,13 +82,20 @@ namespace AssetStudioGUI
{
frm.SelectedPath = InitialFolder;
}
if ((owner == null ? frm.ShowDialog() : frm.ShowDialog(owner)) == DialogResult.OK)
#if !NETFRAMEWORK
if (Title != null)
{
Folder = Path.GetDirectoryName(frm.SelectedPath);
return DialogResult.OK;
frm.Description = Title;
frm.UseDescriptionForTitle = true;
}
return DialogResult.Cancel;
#endif
var result = owner == null ? frm.ShowDialog() : frm.ShowDialog(owner);
if (result == DialogResult.OK)
{
Folder = frm.SelectedPath;
return result;
}
return result;
}
}
}

View File

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

View File

@@ -0,0 +1,43 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace AssetStudioGUI
{
public sealed class DirectBitmap : IDisposable
{
public DirectBitmap(byte[] buff, int width, int height)
{
Width = width;
Height = height;
Bits = buff;
m_handle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
m_bitmap = new Bitmap(Width, Height, Stride, PixelFormat.Format32bppArgb, m_handle.AddrOfPinnedObject());
}
private void Dispose(bool disposing)
{
if (disposing)
{
m_bitmap.Dispose();
m_handle.Free();
}
m_bitmap = null;
}
public void Dispose()
{
Dispose(true);
}
public int Height { get; }
public int Width { get; }
public int Stride => Width * 4;
public byte[] Bits { get; }
public Bitmap Bitmap => m_bitmap;
private Bitmap m_bitmap;
private readonly GCHandle m_handle;
}
}

View File

@@ -17,12 +17,15 @@ namespace AssetStudioGUI
var type = Properties.Settings.Default.convertType;
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false;
var stream = m_Texture2D.ConvertToStream(type, true);
if (stream == null)
var image = m_Texture2D.ConvertToImage(true);
if (image == null)
return false;
using (stream)
using (image)
{
File.WriteAllBytes(exportFullPath, stream.ToArray());
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
return true;
}
}
@@ -149,6 +152,7 @@ namespace AssetStudioGUI
#region UV
if (m_Mesh.m_UV0?.Length > 0)
{
c = 4;
if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
{
c = 2;
@@ -229,12 +233,15 @@ namespace AssetStudioGUI
var type = Properties.Settings.Default.convertType;
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false;
var stream = ((Sprite)item.Asset).GetImage(type);
if (stream != null)
var image = ((Sprite)item.Asset).GetImage();
if (image != null)
{
using (stream)
using (image)
{
File.WriteAllBytes(exportFullPath, stream.ToArray());
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
return true;
}
}

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

Binary file not shown.

View File

@@ -265,7 +265,7 @@ namespace AssetStudioGUI
Progress.Reset();
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)
{
@@ -307,11 +307,12 @@ namespace AssetStudioGUI
{
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);
treeNodeDictionary.Add(parentGameObject, parentNode);
parentGameObjectNode = new GameObjectTreeNode(parentGameObject);
treeNodeDictionary.Add(parentGameObject, parentGameObjectNode);
}
parentNode = parentGameObjectNode;
}
}
}
@@ -413,7 +414,7 @@ namespace AssetStudioGUI
break;
}
exportPath += Path.DirectorySeparatorChar;
StatusStripUpdate($"Exporting {asset.TypeString}: {asset.Text}");
StatusStripUpdate($"[{exportedCount}/{toExportCount}] Exporting {asset.TypeString}: {asset.Text}");
try
{
switch (exportType)
@@ -457,7 +458,7 @@ namespace AssetStudioGUI
if (Properties.Settings.Default.openAfterExport && exportedCount > 0)
{
Process.Start(savePath);
OpenFolderInExplorer(savePath);
}
});
}
@@ -502,7 +503,7 @@ namespace AssetStudioGUI
if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0)
{
Process.Start(savePath);
OpenFolderInExplorer(savePath);
}
});
}
@@ -514,7 +515,7 @@ namespace AssetStudioGUI
var count = nodes.Cast<TreeNode>().Sum(x => x.Nodes.Count);
int k = 0;
Progress.Reset();
foreach (GameObjectTreeNode node in nodes)
foreach (TreeNode node in nodes)
{
//遍历一级子节点
foreach (GameObjectTreeNode j in node.Nodes)
@@ -562,7 +563,7 @@ namespace AssetStudioGUI
}
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(savePath);
OpenFolderInExplorer(savePath);
}
StatusStripUpdate("Finished");
});
@@ -588,7 +589,7 @@ namespace AssetStudioGUI
ExportAnimator(animator, exportPath, animationList);
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(exportPath);
OpenFolderInExplorer(exportPath);
}
Progress.Report(1, 1);
StatusStripUpdate($"Finished exporting {animator.Text}");
@@ -630,12 +631,12 @@ namespace AssetStudioGUI
}
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(exportPath);
OpenFolderInExplorer(exportPath);
}
}
else
{
StatusStripUpdate("No Object can be exported.");
StatusStripUpdate("No Object selected for export.");
}
});
}
@@ -660,18 +661,18 @@ namespace AssetStudioGUI
}
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(Path.GetDirectoryName(exportPath));
OpenFolderInExplorer(Path.GetDirectoryName(exportPath));
}
});
}
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
{
@@ -708,5 +709,12 @@ namespace AssetStudioGUI
}
return str;
}
public static void OpenFolderInExplorer(string path)
{
var info = new ProcessStartInfo(path);
info.UseShellExecute = true;
Process.Start(info);
}
}
}

View File

@@ -1,11 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright>
<Copyright>Copyright © Perfare 2018-2022</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>

View File

@@ -94,29 +94,29 @@ namespace AssetStudio
{
switch (m_AudioClip.m_Type)
{
case AudioType.ACC:
case FMODSoundType.ACC:
return ".m4a";
case AudioType.AIFF:
case FMODSoundType.AIFF:
return ".aif";
case AudioType.IT:
case FMODSoundType.IT:
return ".it";
case AudioType.MOD:
case FMODSoundType.MOD:
return ".mod";
case AudioType.MPEG:
case FMODSoundType.MPEG:
return ".mp3";
case AudioType.OGGVORBIS:
case FMODSoundType.OGGVORBIS:
return ".ogg";
case AudioType.S3M:
case FMODSoundType.S3M:
return ".s3m";
case AudioType.WAV:
case FMODSoundType.WAV:
return ".wav";
case AudioType.XM:
case FMODSoundType.XM:
return ".xm";
case AudioType.XMA:
case FMODSoundType.XMA:
return ".wav";
case AudioType.VAG:
case FMODSoundType.VAG:
return ".vag";
case AudioType.AUDIOQUEUE:
case FMODSoundType.AUDIOQUEUE:
return ".fsb";
}
@@ -133,7 +133,7 @@ namespace AssetStudio
return ".fsb";
case AudioCompressionFormat.MP3:
return ".fsb";
case AudioCompressionFormat.VAG:
case AudioCompressionFormat.PSMVAG:
return ".fsb";
case AudioCompressionFormat.HEVAG:
return ".fsb";
@@ -159,13 +159,13 @@ namespace AssetStudio
{
switch (m_AudioClip.m_Type)
{
case AudioType.AIFF:
case AudioType.IT:
case AudioType.MOD:
case AudioType.S3M:
case AudioType.XM:
case AudioType.XMA:
case AudioType.AUDIOQUEUE:
case FMODSoundType.AIFF:
case FMODSoundType.IT:
case FMODSoundType.MOD:
case FMODSoundType.S3M:
case FMODSoundType.XM:
case FMODSoundType.XMA:
case FMODSoundType.AUDIOQUEUE:
return true;
default:
return false;

View File

@@ -1,39 +1,55 @@
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.PixelFormats;
using System.IO;
using System.Runtime.InteropServices;
namespace AssetStudio
{
public static class ImageExtensions
{
public static MemoryStream ConvertToStream(this Image image, ImageFormat imageFormat)
public static void WriteToStream(this Image image, Stream stream, ImageFormat imageFormat)
{
var outputStream = new MemoryStream();
switch (imageFormat)
{
case ImageFormat.Jpeg:
image.SaveAsJpeg(outputStream);
image.SaveAsJpeg(stream);
break;
case ImageFormat.Png:
image.SaveAsPng(outputStream);
image.SaveAsPng(stream);
break;
case ImageFormat.Bmp:
image.Save(outputStream, new BmpEncoder
image.Save(stream, new BmpEncoder
{
BitsPerPixel = BmpBitsPerPixel.Pixel32,
SupportTransparency = true
});
break;
case ImageFormat.Tga:
image.Save(outputStream, new TgaEncoder
image.Save(stream, new TgaEncoder
{
BitsPerPixel = TgaBitsPerPixel.Pixel32,
Compression = TgaCompression.None
});
break;
}
return outputStream;
}
public static MemoryStream ConvertToStream(this Image image, ImageFormat imageFormat)
{
var stream = new MemoryStream();
image.WriteToStream(stream, imageFormat);
return stream;
}
public static byte[] ConvertToBytes<TPixel>(this Image<TPixel> image) where TPixel : unmanaged, IPixel<TPixel>
{
if (image.TryGetSinglePixelSpan(out var pixelSpan))
{
return MemoryMarshal.AsBytes(pixelSpan).ToArray();
}
return null;
}
}
}

View File

@@ -1063,26 +1063,21 @@ namespace AssetStudio
else
{
transformName = strs.Last();
var parentFrameName = strs[strs.Length - 2];
parentFrame = RootFrame.FindChild(parentFrameName);
//var parentFramePath = path.Substring(0, path.LastIndexOf('/'));
//parentFrame = RootFrame.FindFrameByPath(parentFramePath);
var parentFramePath = path.Substring(0, path.LastIndexOf('/'));
parentFrame = RootFrame.FindRelativeFrameWithPath(parentFramePath);
}
var skeletonPose = avatar.m_Avatar.m_DefaultPose;
var xform = skeletonPose.m_X[i];
var frame = RootFrame.FindChild(transformName);
if (frame != null)
{
SetFrame(frame, xform.t, xform.q, xform.s);
parentFrame.AddChild(frame);
}
else
{
frame = CreateFrame(transformName, xform.t, xform.q, xform.s);
parentFrame.AddChild(frame);
}
parentFrame.AddChild(frame);
}
}

View File

@@ -1,10 +1,10 @@
using System;
using K4os.Compression.LZ4;
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Lz4;
namespace AssetStudio
{
@@ -15,13 +15,11 @@ namespace AssetStudio
if (shader.m_SubProgramBlob != null) //5.3 - 5.4
{
var decompressedBytes = new byte[shader.decompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob)))
{
decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize);
}
LZ4Codec.Decode(shader.m_SubProgramBlob, decompressedBytes);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
var program = new ShaderProgram(blobReader, shader.version);
program.Read(blobReader, 0);
return header + program.Export(Encoding.UTF8.GetString(shader.m_Script));
}
}
@@ -36,19 +34,25 @@ namespace AssetStudio
private static string ConvertSerializedShader(Shader shader)
{
var shaderPrograms = new ShaderProgram[shader.platforms.Length];
for (var i = 0; i < shader.platforms.Length; i++)
var length = shader.platforms.Length;
var shaderPrograms = new ShaderProgram[length];
for (var i = 0; i < length; i++)
{
var compressedBytes = new byte[shader.compressedLengths[i]];
Buffer.BlockCopy(shader.compressedBlob, (int)shader.offsets[i], compressedBytes, 0, (int)shader.compressedLengths[i]);
var decompressedBytes = new byte[shader.decompressedLengths[i]];
using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes)))
for (var j = 0; j < shader.offsets[i].Length; j++)
{
decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]);
}
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);
}
}
}
@@ -105,17 +109,17 @@ namespace AssetStudio
var sb = new StringBuilder();
switch (m_Passe.m_Type)
{
case PassType.kPassTypeNormal:
case PassType.Normal:
sb.Append(" Pass ");
break;
case PassType.kPassTypeUse:
case PassType.Use:
sb.Append(" UsePass ");
break;
case PassType.kPassTypeGrab:
case PassType.Grab:
sb.Append(" GrabPass ");
break;
}
if (m_Passe.m_Type == PassType.kPassTypeUse)
if (m_Passe.m_Type == PassType.Use)
{
sb.Append($"\"{m_Passe.m_UseName}\"\n");
}
@@ -123,7 +127,7 @@ namespace AssetStudio
{
sb.Append("{\n");
if (m_Passe.m_Type == PassType.kPassTypeGrab)
if (m_Passe.m_Type == PassType.Grab)
{
if (!string.IsNullOrEmpty(m_Passe.m_TextureName))
{
@@ -354,7 +358,7 @@ namespace AssetStudio
sb.Append(" }\n");
}
if (m_State.fogMode != FogMode.kFogUnknown ||
if (m_State.fogMode != FogMode.Unknown ||
m_State.fogColor.x.val != 0f ||
m_State.fogColor.y.val != 0f ||
m_State.fogColor.z.val != 0f ||
@@ -364,21 +368,21 @@ namespace AssetStudio
m_State.fogEnd.val != 0f)
{
sb.Append(" Fog {\n");
if (m_State.fogMode != FogMode.kFogUnknown)
if (m_State.fogMode != FogMode.Unknown)
{
sb.Append(" Mode ");
switch (m_State.fogMode)
{
case FogMode.kFogDisabled:
case FogMode.Disabled:
sb.Append("Off");
break;
case FogMode.kFogLinear:
case FogMode.Linear:
sb.Append("Linear");
break;
case FogMode.kFogExp:
case FogMode.Exp:
sb.Append("Exp");
break;
case FogMode.kFogExp2:
case FogMode.Exp2:
sb.Append("Exp2");
break;
}
@@ -670,37 +674,37 @@ namespace AssetStudio
sb.Append($"{m_Prop.m_Name} (\"{m_Prop.m_Description}\", ");
switch (m_Prop.m_Type)
{
case SerializedPropertyType.kColor:
case SerializedPropertyType.Color:
sb.Append("Color");
break;
case SerializedPropertyType.kVector:
case SerializedPropertyType.Vector:
sb.Append("Vector");
break;
case SerializedPropertyType.kFloat:
case SerializedPropertyType.Float:
sb.Append("Float");
break;
case SerializedPropertyType.kRange:
case SerializedPropertyType.Range:
sb.Append($"Range({m_Prop.m_DefValue[1]}, {m_Prop.m_DefValue[2]})");
break;
case SerializedPropertyType.kTexture:
case SerializedPropertyType.Texture:
switch (m_Prop.m_DefTexture.m_TexDim)
{
case TextureDimension.kTexDimAny:
case TextureDimension.Any:
sb.Append("any");
break;
case TextureDimension.kTexDim2D:
case TextureDimension.Tex2D:
sb.Append("2D");
break;
case TextureDimension.kTexDim3D:
case TextureDimension.Tex3D:
sb.Append("3D");
break;
case TextureDimension.kTexDimCUBE:
case TextureDimension.Cube:
sb.Append("Cube");
break;
case TextureDimension.kTexDim2DArray:
case TextureDimension.Tex2DArray:
sb.Append("2DArray");
break;
case TextureDimension.kTexDimCubeArray:
case TextureDimension.CubeArray:
sb.Append("CubeArray");
break;
}
@@ -709,15 +713,15 @@ namespace AssetStudio
sb.Append(") = ");
switch (m_Prop.m_Type)
{
case SerializedPropertyType.kColor:
case SerializedPropertyType.kVector:
case SerializedPropertyType.Color:
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]})");
break;
case SerializedPropertyType.kFloat:
case SerializedPropertyType.kRange:
case SerializedPropertyType.Float:
case SerializedPropertyType.Range:
sb.Append(m_Prop.m_DefValue[0]);
break;
case SerializedPropertyType.kTexture:
case SerializedPropertyType.Texture:
sb.Append($"\"{m_Prop.m_DefTexture.m_DefaultName}\" {{ }}");
break;
default:
@@ -731,64 +735,65 @@ namespace AssetStudio
{
switch (platform)
{
case ShaderCompilerPlatform.kShaderCompPlatformGL:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLLegacy;
case ShaderCompilerPlatform.kShaderCompPlatformD3D9:
return programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30;
case ShaderCompilerPlatform.kShaderCompPlatformXbox360:
case ShaderCompilerPlatform.kShaderCompPlatformPS3:
case ShaderCompilerPlatform.kShaderCompPlatformPSP2:
case ShaderCompilerPlatform.kShaderCompPlatformPS4:
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne:
case ShaderCompilerPlatform.kShaderCompPlatformN3DS:
case ShaderCompilerPlatform.kShaderCompPlatformWiiU:
case ShaderCompilerPlatform.kShaderCompPlatformSwitch:
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12:
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne:
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett:
case ShaderCompilerPlatform.kShaderCompPlatformPS5:
case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformD3D11:
return programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50;
case ShaderCompilerPlatform.kShaderCompPlatformGLES20:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES;
case ShaderCompilerPlatform.kShaderCompPlatformNaCl: //Obsolete
case ShaderCompilerPlatform.GL:
return programType == ShaderGpuProgramType.GLLegacy;
case ShaderCompilerPlatform.D3D9:
return programType == ShaderGpuProgramType.DX9VertexSM20
|| programType == ShaderGpuProgramType.DX9VertexSM30
|| programType == ShaderGpuProgramType.DX9PixelSM20
|| programType == ShaderGpuProgramType.DX9PixelSM30;
case ShaderCompilerPlatform.Xbox360:
case ShaderCompilerPlatform.PS3:
case ShaderCompilerPlatform.PSP2:
case ShaderCompilerPlatform.PS4:
case ShaderCompilerPlatform.XboxOne:
case ShaderCompilerPlatform.N3DS:
case ShaderCompilerPlatform.WiiU:
case ShaderCompilerPlatform.Switch:
case ShaderCompilerPlatform.XboxOneD3D12:
case ShaderCompilerPlatform.GameCoreXboxOne:
case ShaderCompilerPlatform.GameCoreScarlett:
case ShaderCompilerPlatform.PS5:
return programType == ShaderGpuProgramType.ConsoleVS
|| programType == ShaderGpuProgramType.ConsoleFS
|| programType == ShaderGpuProgramType.ConsoleHS
|| programType == ShaderGpuProgramType.ConsoleDS
|| programType == ShaderGpuProgramType.ConsoleGS;
case ShaderCompilerPlatform.PS5NGGC:
return programType == ShaderGpuProgramType.PS5NGGC;
case ShaderCompilerPlatform.D3D11:
return programType == ShaderGpuProgramType.DX11VertexSM40
|| programType == ShaderGpuProgramType.DX11VertexSM50
|| programType == ShaderGpuProgramType.DX11PixelSM40
|| programType == ShaderGpuProgramType.DX11PixelSM50
|| programType == ShaderGpuProgramType.DX11GeometrySM40
|| programType == ShaderGpuProgramType.DX11GeometrySM50
|| programType == ShaderGpuProgramType.DX11HullSM50
|| programType == ShaderGpuProgramType.DX11DomainSM50;
case ShaderCompilerPlatform.GLES20:
return programType == ShaderGpuProgramType.GLES;
case ShaderCompilerPlatform.NaCl: //Obsolete
throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformFlash: //Obsolete
case ShaderCompilerPlatform.Flash: //Obsolete
throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x:
return programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel;
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES31AEP
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES31
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES3;
case ShaderCompilerPlatform.kShaderCompPlatformPSM: //Unknown
case ShaderCompilerPlatform.D3D11_9x:
return programType == ShaderGpuProgramType.DX10Level9Vertex
|| programType == ShaderGpuProgramType.DX10Level9Pixel;
case ShaderCompilerPlatform.GLES3Plus:
return programType == ShaderGpuProgramType.GLES31AEP
|| programType == ShaderGpuProgramType.GLES31
|| programType == ShaderGpuProgramType.GLES3;
case ShaderCompilerPlatform.PSM: //Unknown
throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformMetal:
return programType == ShaderGpuProgramType.kShaderGpuProgramMetalVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramMetalFS;
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLCore32
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore41
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore43;
case ShaderCompilerPlatform.kShaderCompPlatformVulkan:
return programType == ShaderGpuProgramType.kShaderGpuProgramSPIRV;
case ShaderCompilerPlatform.Metal:
return programType == ShaderGpuProgramType.MetalVS
|| programType == ShaderGpuProgramType.MetalFS;
case ShaderCompilerPlatform.OpenGLCore:
return programType == ShaderGpuProgramType.GLCore32
|| programType == ShaderGpuProgramType.GLCore41
|| programType == ShaderGpuProgramType.GLCore43;
case ShaderCompilerPlatform.Vulkan:
return programType == ShaderGpuProgramType.SPIRV;
default:
throw new NotSupportedException();
}
@@ -798,55 +803,55 @@ namespace AssetStudio
{
switch (platform)
{
case ShaderCompilerPlatform.kShaderCompPlatformGL:
case ShaderCompilerPlatform.GL:
return "openGL";
case ShaderCompilerPlatform.kShaderCompPlatformD3D9:
case ShaderCompilerPlatform.D3D9:
return "d3d9";
case ShaderCompilerPlatform.kShaderCompPlatformXbox360:
case ShaderCompilerPlatform.Xbox360:
return "xbox360";
case ShaderCompilerPlatform.kShaderCompPlatformPS3:
case ShaderCompilerPlatform.PS3:
return "ps3";
case ShaderCompilerPlatform.kShaderCompPlatformD3D11:
case ShaderCompilerPlatform.D3D11:
return "d3d11";
case ShaderCompilerPlatform.kShaderCompPlatformGLES20:
case ShaderCompilerPlatform.GLES20:
return "gles";
case ShaderCompilerPlatform.kShaderCompPlatformNaCl:
case ShaderCompilerPlatform.NaCl:
return "glesdesktop";
case ShaderCompilerPlatform.kShaderCompPlatformFlash:
case ShaderCompilerPlatform.Flash:
return "flash";
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x:
case ShaderCompilerPlatform.D3D11_9x:
return "d3d11_9x";
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus:
case ShaderCompilerPlatform.GLES3Plus:
return "gles3";
case ShaderCompilerPlatform.kShaderCompPlatformPSP2:
case ShaderCompilerPlatform.PSP2:
return "psp2";
case ShaderCompilerPlatform.kShaderCompPlatformPS4:
case ShaderCompilerPlatform.PS4:
return "ps4";
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne:
case ShaderCompilerPlatform.XboxOne:
return "xboxone";
case ShaderCompilerPlatform.kShaderCompPlatformPSM:
case ShaderCompilerPlatform.PSM:
return "psm";
case ShaderCompilerPlatform.kShaderCompPlatformMetal:
case ShaderCompilerPlatform.Metal:
return "metal";
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore:
case ShaderCompilerPlatform.OpenGLCore:
return "glcore";
case ShaderCompilerPlatform.kShaderCompPlatformN3DS:
case ShaderCompilerPlatform.N3DS:
return "n3ds";
case ShaderCompilerPlatform.kShaderCompPlatformWiiU:
case ShaderCompilerPlatform.WiiU:
return "wiiu";
case ShaderCompilerPlatform.kShaderCompPlatformVulkan:
case ShaderCompilerPlatform.Vulkan:
return "vulkan";
case ShaderCompilerPlatform.kShaderCompPlatformSwitch:
case ShaderCompilerPlatform.Switch:
return "switch";
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12:
case ShaderCompilerPlatform.XboxOneD3D12:
return "xboxone_d3d12";
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne:
case ShaderCompilerPlatform.GameCoreXboxOne:
return "xboxone";
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett:
case ShaderCompilerPlatform.GameCoreScarlett:
return "xbox_scarlett";
case ShaderCompilerPlatform.kShaderCompPlatformPS5:
case ShaderCompilerPlatform.PS5:
return "ps5";
case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC:
case ShaderCompilerPlatform.PS5NGGC:
return "ps5_nggc";
default:
return "unknown";
@@ -860,29 +865,49 @@ namespace AssetStudio
"///////////////////////////////////////////\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 ShaderSubProgramEntry[] entries;
public ShaderSubProgram[] m_SubPrograms;
public ShaderProgram(BinaryReader reader, int[] version)
{
var subProgramsCapacity = reader.ReadInt32();
m_SubPrograms = new ShaderSubProgram[subProgramsCapacity];
int entrySize;
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
entrySize = 12;
}
else
{
entrySize = 8;
}
entries = new ShaderSubProgramEntry[subProgramsCapacity];
for (int i = 0; i < subProgramsCapacity; i++)
{
reader.BaseStream.Position = 4 + i * entrySize;
var offset = reader.ReadInt32();
reader.BaseStream.Position = offset;
m_SubPrograms[i] = new ShaderSubProgram(reader);
entries[i] = new ShaderSubProgramEntry(reader, version);
}
m_SubPrograms = new ShaderSubProgram[subProgramsCapacity];
}
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);
}
}
}
@@ -972,36 +997,36 @@ namespace AssetStudio
{
switch (m_ProgramType)
{
case ShaderGpuProgramType.kShaderGpuProgramGLLegacy:
case ShaderGpuProgramType.kShaderGpuProgramGLES31AEP:
case ShaderGpuProgramType.kShaderGpuProgramGLES31:
case ShaderGpuProgramType.kShaderGpuProgramGLES3:
case ShaderGpuProgramType.kShaderGpuProgramGLES:
case ShaderGpuProgramType.kShaderGpuProgramGLCore32:
case ShaderGpuProgramType.kShaderGpuProgramGLCore41:
case ShaderGpuProgramType.kShaderGpuProgramGLCore43:
case ShaderGpuProgramType.GLLegacy:
case ShaderGpuProgramType.GLES31AEP:
case ShaderGpuProgramType.GLES31:
case ShaderGpuProgramType.GLES3:
case ShaderGpuProgramType.GLES:
case ShaderGpuProgramType.GLCore32:
case ShaderGpuProgramType.GLCore41:
case ShaderGpuProgramType.GLCore43:
sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
break;
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30:
case ShaderGpuProgramType.DX9VertexSM20:
case ShaderGpuProgramType.DX9VertexSM30:
case ShaderGpuProgramType.DX9PixelSM20:
case ShaderGpuProgramType.DX9PixelSM30:
{
/*var shaderBytecode = new ShaderBytecode(m_ProgramCode);
sb.Append(shaderBytecode.Disassemble());*/
sb.Append("// shader disassembly not supported on DXBC");
break;
}
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex:
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50:
case ShaderGpuProgramType.DX10Level9Vertex:
case ShaderGpuProgramType.DX10Level9Pixel:
case ShaderGpuProgramType.DX11VertexSM40:
case ShaderGpuProgramType.DX11VertexSM50:
case ShaderGpuProgramType.DX11PixelSM40:
case ShaderGpuProgramType.DX11PixelSM50:
case ShaderGpuProgramType.DX11GeometrySM40:
case ShaderGpuProgramType.DX11GeometrySM50:
case ShaderGpuProgramType.DX11HullSM50:
case ShaderGpuProgramType.DX11DomainSM50:
{
/*int start = 6;
if (m_Version == 201509030) // 5.3
@@ -1015,8 +1040,8 @@ namespace AssetStudio
sb.Append("// shader disassembly not supported on DXBC");
break;
}
case ShaderGpuProgramType.kShaderGpuProgramMetalVS:
case ShaderGpuProgramType.kShaderGpuProgramMetalFS:
case ShaderGpuProgramType.MetalVS:
case ShaderGpuProgramType.MetalFS:
using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode)))
{
var fourCC = reader.ReadUInt32();
@@ -1030,7 +1055,7 @@ namespace AssetStudio
sb.Append(Encoding.UTF8.GetString(buff));
}
break;
case ShaderGpuProgramType.kShaderGpuProgramSPIRV:
case ShaderGpuProgramType.SPIRV:
try
{
sb.Append(SpirVShaderConverter.Convert(m_ProgramCode));
@@ -1040,11 +1065,11 @@ namespace AssetStudio
sb.Append($"// disassembly error {e.Message}\n");
}
break;
case ShaderGpuProgramType.kShaderGpuProgramConsoleVS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleFS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleHS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleDS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleGS:
case ShaderGpuProgramType.ConsoleVS:
case ShaderGpuProgramType.ConsoleFS:
case ShaderGpuProgramType.ConsoleHS:
case ShaderGpuProgramType.ConsoleDS:
case ShaderGpuProgramType.ConsoleGS:
sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
break;
default:

View File

@@ -13,51 +13,44 @@ namespace AssetStudio
{
public static class SpriteHelper
{
public static MemoryStream GetImage(this Sprite m_Sprite, ImageFormat imageFormat)
{
var image = GetImage(m_Sprite);
if (image != null)
{
using (image)
{
return image.ConvertToStream(imageFormat);
}
}
return null;
}
public static Image GetImage(this Sprite m_Sprite)
public static Image<Bgra32> GetImage(this Sprite m_Sprite)
{
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
{
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
{
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;
}
private static Image 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);
if (originalImage != null)
{
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 rectY = (int)Math.Floor(textureRect.y);
var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);
var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);
rectRight = Math.Min(rectRight, m_Texture2D.m_Width);
rectBottom = Math.Min(rectBottom, m_Texture2D.m_Height);
rectRight = Math.Min(rectRight, originalImage.Width);
rectBottom = Math.Min(rectBottom, originalImage.Height);
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
var spriteImage = originalImage.Clone(x => x.Crop(rect));
if (settingsRaw.packed == 1)
@@ -65,23 +58,23 @@ namespace AssetStudio
//RotateAndFlip
switch (settingsRaw.packingRotation)
{
case SpritePackingRotation.kSPRFlipHorizontal:
case SpritePackingRotation.FlipHorizontal:
spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal));
break;
case SpritePackingRotation.kSPRFlipVertical:
case SpritePackingRotation.FlipVertical:
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
break;
case SpritePackingRotation.kSPRRotate180:
case SpritePackingRotation.Rotate180:
spriteImage.Mutate(x => x.Rotate(180));
break;
case SpritePackingRotation.kSPRRotate90:
case SpritePackingRotation.Rotate90:
spriteImage.Mutate(x => x.Rotate(270));
break;
}
}
//Tight
if (settingsRaw.packingMode == SpritePackingMode.kSPMTight)
if (settingsRaw.packingMode == SpritePackingMode.Tight)
{
try
{
@@ -89,29 +82,25 @@ namespace AssetStudio
var polygons = triangles.Select(x => new Polygon(new LinearLineSegment(x.Select(y => new PointF(y.X, y.Y)).ToArray()))).ToArray();
IPathCollection path = new PathCollection(polygons);
var matrix = Matrix3x2.CreateScale(m_Sprite.m_PixelsToUnits);
var version = m_Sprite.version;
if (version[0] < 5
|| (version[0] == 5 && version[1] < 4)
|| (version[0] == 5 && version[1] == 4 && version[2] <= 1)) //5.4.1p3 down
{
matrix *= Matrix3x2.CreateTranslation(m_Sprite.m_Rect.width * 0.5f - textureRectOffset.X, m_Sprite.m_Rect.height * 0.5f - textureRectOffset.Y);
}
else
{
matrix *= Matrix3x2.CreateTranslation(m_Sprite.m_Rect.width * m_Sprite.m_Pivot.X - textureRectOffset.X, m_Sprite.m_Rect.height * m_Sprite.m_Pivot.Y - textureRectOffset.Y);
}
matrix *= Matrix3x2.CreateTranslation(m_Sprite.m_Rect.width * m_Sprite.m_Pivot.X - textureRectOffset.X, m_Sprite.m_Rect.height * m_Sprite.m_Pivot.Y - textureRectOffset.Y);
path = path.Transform(matrix);
var graphicsOptions = new GraphicsOptions
{
Antialias = false,
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
};
var options = new DrawingOptions
{
GraphicsOptions = new GraphicsOptions()
{
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
}
GraphicsOptions = graphicsOptions
};
var rectP = new RectangularPolygon(0, 0, rect.Width, rect.Height);
spriteImage.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, rectP.Clip(path)));
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
return spriteImage;
using (var mask = new Image<Bgra32>(rect.Width, rect.Height, SixLabors.ImageSharp.Color.Black))
{
mask.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, path));
var bursh = new ImageBrush(mask);
spriteImage.Mutate(x => x.Fill(graphicsOptions, bursh));
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
return spriteImage;
}
}
catch
{

View File

@@ -1,217 +1,223 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using Texture2DDecoder;
namespace AssetStudio
{
public class Texture2DConverter
{
private ResourceReader reader;
private int m_Width;
private int m_Height;
private TextureFormat m_TextureFormat;
private int image_data_size;
private byte[] image_data;
private int[] version;
private BuildTarget platform;
private int outPutSize;
public Texture2DConverter(Texture2D m_Texture2D)
{
image_data = m_Texture2D.image_data.GetData();
image_data_size = image_data.Length;
reader = m_Texture2D.image_data;
m_Width = m_Texture2D.m_Width;
m_Height = m_Texture2D.m_Height;
m_TextureFormat = m_Texture2D.m_TextureFormat;
version = m_Texture2D.version;
platform = m_Texture2D.platform;
outPutSize = m_Width * m_Height * 4;
}
public byte[] DecodeTexture2D()
public bool DecodeTexture2D(byte[] bytes)
{
byte[] bytes = null;
if (reader.Size == 0 || m_Width == 0 || m_Height == 0)
{
return false;
}
var flag = false;
var buff = BigArrayPool<byte>.Shared.Rent(reader.Size);
reader.GetData(buff);
switch (m_TextureFormat)
{
case TextureFormat.Alpha8: //test pass
bytes = DecodeAlpha8();
flag = DecodeAlpha8(buff, bytes);
break;
case TextureFormat.ARGB4444: //test pass
SwapBytesForXbox();
bytes = DecodeARGB4444();
SwapBytesForXbox(buff);
flag = DecodeARGB4444(buff, bytes);
break;
case TextureFormat.RGB24: //test pass
bytes = DecodeRGB24();
flag = DecodeRGB24(buff, bytes);
break;
case TextureFormat.RGBA32: //test pass
bytes = DecodeRGBA32();
flag = DecodeRGBA32(buff, bytes);
break;
case TextureFormat.ARGB32: //test pass
bytes = DecodeARGB32();
flag = DecodeARGB32(buff, bytes);
break;
case TextureFormat.RGB565: //test pass
SwapBytesForXbox();
bytes = DecodeRGB565();
SwapBytesForXbox(buff);
flag = DecodeRGB565(buff, bytes);
break;
case TextureFormat.R16: //test pass
bytes = DecodeR16();
flag = DecodeR16(buff, bytes);
break;
case TextureFormat.DXT1: //test pass
SwapBytesForXbox();
bytes = DecodeDXT1();
SwapBytesForXbox(buff);
flag = DecodeDXT1(buff, bytes);
break;
case TextureFormat.DXT3:
break;
case TextureFormat.DXT5: //test pass
SwapBytesForXbox();
bytes = DecodeDXT5();
SwapBytesForXbox(buff);
flag = DecodeDXT5(buff, bytes);
break;
case TextureFormat.RGBA4444: //test pass
bytes = DecodeRGBA4444();
flag = DecodeRGBA4444(buff, bytes);
break;
case TextureFormat.BGRA32: //test pass
bytes = DecodeBGRA32();
flag = DecodeBGRA32(buff, bytes);
break;
case TextureFormat.RHalf:
bytes = DecodeRHalf();
flag = DecodeRHalf(buff, bytes);
break;
case TextureFormat.RGHalf:
bytes = DecodeRGHalf();
flag = DecodeRGHalf(buff, bytes);
break;
case TextureFormat.RGBAHalf: //test pass
bytes = DecodeRGBAHalf();
flag = DecodeRGBAHalf(buff, bytes);
break;
case TextureFormat.RFloat:
bytes = DecodeRFloat();
flag = DecodeRFloat(buff, bytes);
break;
case TextureFormat.RGFloat:
bytes = DecodeRGFloat();
flag = DecodeRGFloat(buff, bytes);
break;
case TextureFormat.RGBAFloat:
bytes = DecodeRGBAFloat();
flag = DecodeRGBAFloat(buff, bytes);
break;
case TextureFormat.YUY2: //test pass
bytes = DecodeYUY2();
flag = DecodeYUY2(buff, bytes);
break;
case TextureFormat.RGB9e5Float: //test pass
bytes = DecodeRGB9e5Float();
break;
case TextureFormat.BC4: //test pass
bytes = DecodeBC4();
break;
case TextureFormat.BC5: //test pass
bytes = DecodeBC5();
flag = DecodeRGB9e5Float(buff, bytes);
break;
case TextureFormat.BC6H: //test pass
bytes = DecodeBC6H();
flag = DecodeBC6H(buff, bytes);
break;
case TextureFormat.BC7: //test pass
bytes = DecodeBC7();
flag = DecodeBC7(buff, bytes);
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
if (UnpackCrunch())
{
bytes = DecodeDXT1();
}
flag = DecodeDXT1Crunched(buff, bytes);
break;
case TextureFormat.DXT5Crunched: //test pass
if (UnpackCrunch())
{
bytes = DecodeDXT5();
}
flag = DecodeDXT5Crunched(buff, bytes);
break;
case TextureFormat.PVRTC_RGB2: //test pass
case TextureFormat.PVRTC_RGBA2: //test pass
bytes = DecodePVRTC(true);
flag = DecodePVRTC(buff, bytes, true);
break;
case TextureFormat.PVRTC_RGB4: //test pass
case TextureFormat.PVRTC_RGBA4: //test pass
bytes = DecodePVRTC(false);
flag = DecodePVRTC(buff, bytes, false);
break;
case TextureFormat.ETC_RGB4: //test pass
case TextureFormat.ETC_RGB4_3DS:
bytes = DecodeETC1();
flag = DecodeETC1(buff, bytes);
break;
case TextureFormat.ATC_RGB4: //test pass
bytes = DecodeATCRGB4();
flag = DecodeATCRGB4(buff, bytes);
break;
case TextureFormat.ATC_RGBA8: //test pass
bytes = DecodeATCRGBA8();
flag = DecodeATCRGBA8(buff, bytes);
break;
case TextureFormat.EAC_R: //test pass
bytes = DecodeEACR();
flag = DecodeEACR(buff, bytes);
break;
case TextureFormat.EAC_R_SIGNED:
bytes = DecodeEACRSigned();
flag = DecodeEACRSigned(buff, bytes);
break;
case TextureFormat.EAC_RG: //test pass
bytes = DecodeEACRG();
flag = DecodeEACRG(buff, bytes);
break;
case TextureFormat.EAC_RG_SIGNED:
bytes = DecodeEACRGSigned();
flag = DecodeEACRGSigned(buff, bytes);
break;
case TextureFormat.ETC2_RGB: //test pass
bytes = DecodeETC2();
flag = DecodeETC2(buff, bytes);
break;
case TextureFormat.ETC2_RGBA1: //test pass
bytes = DecodeETC2A1();
flag = DecodeETC2A1(buff, bytes);
break;
case TextureFormat.ETC2_RGBA8: //test pass
case TextureFormat.ETC_RGBA8_3DS:
bytes = DecodeETC2A8();
flag = DecodeETC2A8(buff, bytes);
break;
case TextureFormat.ASTC_RGB_4x4: //test pass
case TextureFormat.ASTC_RGBA_4x4: //test pass
case TextureFormat.ASTC_HDR_4x4: //test pass
bytes = DecodeASTC(4);
flag = DecodeASTC(buff, bytes, 4);
break;
case TextureFormat.ASTC_RGB_5x5: //test pass
case TextureFormat.ASTC_RGBA_5x5: //test pass
case TextureFormat.ASTC_HDR_5x5: //test pass
bytes = DecodeASTC(5);
flag = DecodeASTC(buff, bytes, 5);
break;
case TextureFormat.ASTC_RGB_6x6: //test pass
case TextureFormat.ASTC_RGBA_6x6: //test pass
case TextureFormat.ASTC_HDR_6x6: //test pass
bytes = DecodeASTC(6);
flag = DecodeASTC(buff, bytes, 6);
break;
case TextureFormat.ASTC_RGB_8x8: //test pass
case TextureFormat.ASTC_RGBA_8x8: //test pass
case TextureFormat.ASTC_HDR_8x8: //test pass
bytes = DecodeASTC(8);
flag = DecodeASTC(buff, bytes, 8);
break;
case TextureFormat.ASTC_RGB_10x10: //test pass
case TextureFormat.ASTC_RGBA_10x10: //test pass
case TextureFormat.ASTC_HDR_10x10: //test pass
bytes = DecodeASTC(10);
flag = DecodeASTC(buff, bytes, 10);
break;
case TextureFormat.ASTC_RGB_12x12: //test pass
case TextureFormat.ASTC_RGBA_12x12: //test pass
case TextureFormat.ASTC_HDR_12x12: //test pass
bytes = DecodeASTC(12);
flag = DecodeASTC(buff, bytes, 12);
break;
case TextureFormat.RG16: //test pass
bytes = DecodeRG16();
flag = DecodeRG16(buff, bytes);
break;
case TextureFormat.R8: //test pass
bytes = DecodeR8();
flag = DecodeR8(buff, bytes);
break;
case TextureFormat.ETC_RGB4Crunched: //test pass
if (UnpackCrunch())
{
bytes = DecodeETC1();
}
flag = DecodeETC1Crunched(buff, bytes);
break;
case TextureFormat.ETC2_RGBA8Crunched: //test pass
if (UnpackCrunch())
{
bytes = DecodeETC2A8();
}
flag = DecodeETC2A8Crunched(buff, bytes);
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;
}
return bytes;
BigArrayPool<byte>.Shared.Return(buff);
return flag;
}
private void SwapBytesForXbox()
private void SwapBytesForXbox(byte[] image_data)
{
if (platform == BuildTarget.XBOX360)
{
for (var i = 0; i < image_data_size / 2; i++)
for (var i = 0; i < reader.Size / 2; i++)
{
var b = image_data[i * 2];
image_data[i * 2] = image_data[i * 2 + 1];
@@ -220,22 +226,24 @@ namespace AssetStudio
}
}
private byte[] DecodeAlpha8()
private bool DecodeAlpha8(byte[] image_data, byte[] buff)
{
var buff = Enumerable.Repeat<byte>(0xFF, m_Width * m_Height * 4).ToArray();
for (var i = 0; i < m_Width * m_Height; i++)
var size = m_Width * m_Height;
var span = new Span<byte>(buff);
span.Fill(0xFF);
for (var i = 0; i < size; i++)
{
buff[i * 4 + 3] = image_data[i];
}
return buff;
return true;
}
private byte[] DecodeARGB4444()
private bool DecodeARGB4444(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
var size = m_Width * m_Height;
var pixelNew = new byte[4];
for (var i = 0; i < size; i++)
{
var pixelNew = new byte[4];
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)(pixelOldShort & 0x000f);
pixelNew[1] = (byte)((pixelOldShort & 0x00f0) >> 4);
@@ -245,52 +253,50 @@ namespace AssetStudio
pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);
pixelNew.CopyTo(buff, i * 4);
}
return buff;
return true;
}
private byte[] DecodeRGB24()
private bool DecodeRGB24(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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 + 1] = image_data[i * 3 + 1];
buff[i * 4 + 2] = image_data[i * 3 + 0];
buff[i * 4 + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGBA32()
private bool DecodeRGBA32(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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 + 1] = image_data[i + 1];
buff[i + 2] = image_data[i + 0];
buff[i + 3] = image_data[i + 3];
}
return buff;
return true;
}
private byte[] DecodeARGB32()
private bool DecodeARGB32(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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 + 1] = image_data[i + 2];
buff[i + 2] = image_data[i + 1];
buff[i + 3] = image_data[i + 0];
}
return buff;
return true;
}
private byte[] DecodeRGB565()
private bool DecodeRGB565(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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);
buff[i * 4] = (byte)((p << 3) | (p >> 2 & 7));
@@ -298,46 +304,38 @@ namespace AssetStudio
buff[i * 4 + 2] = (byte)((p >> 8 & 0xf8) | (p >> 13));
buff[i * 4 + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeR16()
private bool DecodeR16(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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 + 2] = image_data[i * 2 + 1]; //r
buff[i * 4] = 0; //b
buff[i * 4 + 1] = 0; //g
buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r
buff[i * 4 + 3] = 255; //a
}
return buff;
return true;
}
private byte[] DecodeDXT1()
private bool DecodeDXT1(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeDXT1(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeDXT1(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeDXT5()
private bool DecodeDXT5(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeDXT5(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeDXT5(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeRGBA4444()
private bool DecodeRGBA4444(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
var size = m_Width * m_Height;
var pixelNew = new byte[4];
for (var i = 0; i < size; i++)
{
var pixelNew = new byte[4];
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)((pixelOldShort & 0x00f0) >> 4);
pixelNew[1] = (byte)((pixelOldShort & 0x0f00) >> 8);
@@ -347,108 +345,101 @@ namespace AssetStudio
pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);
pixelNew.CopyTo(buff, i * 4);
}
return buff;
return true;
}
private byte[] DecodeBGRA32()
private bool DecodeBGRA32(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = image_data[i];
buff[i + 1] = image_data[i + 1];
buff[i + 2] = image_data[i + 2];
buff[i + 3] = image_data[i + 3];
}
return buff;
return true;
}
private byte[] DecodeRHalf()
private bool DecodeRHalf(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = 0;
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i / 2) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGHalf()
private bool DecodeRGHalf(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i + 2) * 255f);
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGBAHalf()
private bool DecodeRGBAHalf(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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 + 1] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f);
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i * 2) * 255f);
buff[i + 3] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 6) * 255f);
}
return buff;
return true;
}
private byte[] DecodeRFloat()
private bool DecodeRFloat(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = 0;
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGFloat()
private bool DecodeRGFloat(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2 + 4) * 255f);
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGBAFloat()
private bool DecodeRGBAFloat(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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 + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 4) * 255f);
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4) * 255f);
buff[i + 3] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 12) * 255f);
}
return buff;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static byte ClampByte(int x)
{
return (byte)(byte.MaxValue < x ? byte.MaxValue : (x > byte.MinValue ? x : byte.MinValue));
}
private byte[] DecodeYUY2()
private bool DecodeYUY2(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
int p = 0;
int o = 0;
int halfWidth = m_Width / 2;
@@ -474,13 +465,12 @@ namespace AssetStudio
buff[o++] = 255;
}
}
return buff;
return true;
}
private byte[] DecodeRGB9e5Float()
private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
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 scale = n >> 27 & 0x1f;
@@ -493,195 +483,208 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(r * scalef * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeBC4()
private bool DecodeBC4(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC4(image_data, m_Width, m_Height, buff))
return TextureDecoder.DecodeBC4(image_data, m_Width, m_Height, buff);
}
private bool DecodeBC5(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeBC5(image_data, m_Width, m_Height, buff);
}
private bool DecodeBC6H(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeBC6(image_data, m_Width, m_Height, buff);
}
private bool DecodeBC7(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeBC7(image_data, m_Width, m_Height, buff);
}
private bool DecodeDXT1Crunched(byte[] image_data, byte[] buff)
{
if (UnpackCrunch(image_data, out var result))
{
return null;
if (DecodeDXT1(result, buff))
{
return true;
}
}
return buff;
return false;
}
private byte[] DecodeBC5()
private bool DecodeDXT5Crunched(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC5(image_data, m_Width, m_Height, buff))
if (UnpackCrunch(image_data, out var result))
{
return null;
if (DecodeDXT5(result, buff))
{
return true;
}
}
return buff;
return false;
}
private byte[] DecodeBC6H()
private bool DecodePVRTC(byte[] image_data, byte[] buff, bool is2bpp)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC6(image_data, m_Width, m_Height, buff))
return TextureDecoder.DecodePVRTC(image_data, m_Width, m_Height, buff, is2bpp);
}
private bool DecodeETC1(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeETC1(image_data, m_Width, m_Height, buff);
}
private bool DecodeATCRGB4(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeATCRGB4(image_data, m_Width, m_Height, buff);
}
private bool DecodeATCRGBA8(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeATCRGBA8(image_data, m_Width, m_Height, buff);
}
private bool DecodeEACR(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeEACR(image_data, m_Width, m_Height, buff);
}
private bool DecodeEACRSigned(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeEACRSigned(image_data, m_Width, m_Height, buff);
}
private bool DecodeEACRG(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeEACRG(image_data, m_Width, m_Height, buff);
}
private bool DecodeEACRGSigned(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeEACRGSigned(image_data, m_Width, m_Height, buff);
}
private bool DecodeETC2(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeETC2(image_data, m_Width, m_Height, buff);
}
private bool DecodeETC2A1(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeETC2A1(image_data, m_Width, m_Height, buff);
}
private bool DecodeETC2A8(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeETC2A8(image_data, m_Width, m_Height, buff);
}
private bool DecodeASTC(byte[] image_data, byte[] buff, int blocksize)
{
return TextureDecoder.DecodeASTC(image_data, m_Width, m_Height, blocksize, blocksize, buff);
}
private bool DecodeRG16(byte[] image_data, byte[] buff)
{
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
return null;
buff[i * 4] = 0; //B
buff[i * 4 + 1] = image_data[i * 2 + 1];//G
buff[i * 4 + 2] = image_data[i * 2];//R
buff[i * 4 + 3] = 255;//A
}
return buff;
return true;
}
private byte[] DecodeBC7()
private bool DecodeR8(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC7(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodePVRTC(bool is2bpp)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodePVRTC(image_data, m_Width, m_Height, buff, is2bpp))
{
return null;
}
return buff;
}
private byte[] DecodeETC1()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC1(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeATCRGB4()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeATCRGB4(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeATCRGBA8()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeATCRGBA8(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeEACR()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACR(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeEACRSigned()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACRSigned(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeEACRG()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACRG(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeEACRGSigned()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACRGSigned(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeETC2()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC2(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeETC2A1()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC2A1(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeETC2A8()
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC2A8(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeASTC(int blocksize)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeASTC(image_data, m_Width, m_Height, blocksize, blocksize, buff))
{
return null;
}
return buff;
}
private byte[] DecodeRG16()
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i += 2)
{
buff[i * 2 + 1] = image_data[i + 1];//G
buff[i * 2 + 2] = image_data[i];//R
buff[i * 2 + 3] = 255;//A
}
return buff;
}
private byte[] DecodeR8()
{
var buff = new byte[m_Width * m_Height * 4];
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 + 1] = 0; //G
buff[i * 4 + 2] = image_data[i];//R
buff[i * 4 + 3] = 255;//A
}
return buff;
return true;
}
private bool UnpackCrunch()
private bool DecodeETC1Crunched(byte[] image_data, byte[] buff)
{
if (UnpackCrunch(image_data, out var result))
{
if (DecodeETC1(result, buff))
{
return true;
}
}
return false;
}
private bool DecodeETC2A8Crunched(byte[] image_data, byte[] buff)
{
if (UnpackCrunch(image_data, out var result))
{
if (DecodeETC2A8(result, buff))
{
return true;
}
}
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)
{
byte[] result;
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up
|| m_TextureFormat == TextureFormat.ETC_RGB4Crunched
|| m_TextureFormat == TextureFormat.ETC2_RGBA8Crunched)
@@ -694,8 +697,6 @@ namespace AssetStudio
}
if (result != null)
{
image_data = result;
image_data_size = result.Length;
return true;
}
return false;

View File

@@ -7,20 +7,27 @@ namespace AssetStudio
{
public static class Texture2DExtensions
{
public static Image ConvertToImage(this Texture2D m_Texture2D, bool flip)
public static Image<Bgra32> ConvertToImage(this Texture2D m_Texture2D, bool flip)
{
var converter = new Texture2DConverter(m_Texture2D);
var bytes = converter.DecodeTexture2D();
if (bytes != null && bytes.Length > 0)
var buff = BigArrayPool<byte>.Shared.Rent(m_Texture2D.m_Width * m_Texture2D.m_Height * 4);
try
{
var image = Image.LoadPixelData<Bgra32>(bytes, m_Texture2D.m_Width, m_Texture2D.m_Height);
if (flip)
if (converter.DecodeTexture2D(buff))
{
image.Mutate(x => x.Flip(FlipMode.Vertical));
var image = Image.LoadPixelData<Bgra32>(buff, m_Texture2D.m_Width, m_Texture2D.m_Height);
if (flip)
{
image.Mutate(x => x.Flip(FlipMode.Vertical));
}
return image;
}
return image;
return null;
}
finally
{
BigArrayPool<byte>.Shared.Return(buff);
}
return null;
}
public static MemoryStream ConvertToStream(this Texture2D m_Texture2D, ImageFormat imageFormat, bool flip)

View File

@@ -253,28 +253,28 @@ namespace AssetStudio
switch (typeRef.FullName)
{
case "UnityEngine.AnimationCurve":
Helper.AddAnimationCurve(nodes, name, indent + 1);
Helper.AddAnimationCurve(nodes, name, indent);
break;
case "UnityEngine.Gradient":
Helper.AddGradient(nodes, name, indent + 1);
Helper.AddGradient(nodes, name, indent);
break;
case "UnityEngine.GUIStyle":
Helper.AddGUIStyle(nodes, name, indent + 1);
Helper.AddGUIStyle(nodes, name, indent);
break;
case "UnityEngine.RectOffset":
Helper.AddRectOffset(nodes, name, indent + 1);
Helper.AddRectOffset(nodes, name, indent);
break;
case "UnityEngine.Color32":
Helper.AddColor32(nodes, name, indent + 1);
Helper.AddColor32(nodes, name, indent);
break;
case "UnityEngine.Matrix4x4":
Helper.AddMatrix4x4(nodes, name, indent + 1);
Helper.AddMatrix4x4(nodes, name, indent);
break;
case "UnityEngine.Rendering.SphericalHarmonicsL2":
Helper.AddSphericalHarmonicsL2(nodes, name, indent + 1);
Helper.AddSphericalHarmonicsL2(nodes, name, indent);
break;
case "UnityEngine.PropertyName":
Helper.AddPropertyName(nodes, name, indent + 1);
Helper.AddPropertyName(nodes, name, indent);
break;
}
}

View File

@@ -7,7 +7,7 @@ AssetStudio is a tool for exploring, extracting and exporting assets and assetbu
## Features
* Support version:
* 3.4 - 2021.2
* 3.4 - 2022.1
* Support asset types:
* **Texture2D** : convert to png, tga, jpeg, bmp
* **Sprite** : crop Texture2D to png, tga, jpeg, bmp
@@ -23,7 +23,13 @@ AssetStudio is a tool for exploring, extracting and exporting assets and assetbu
## Requirements
- [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)
- AssetStudio.net472
- [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)
- AssetStudio.net5
- [.NET Desktop Runtime 5.0](https://dotnet.microsoft.com/download/dotnet/5.0)
- AssetStudio.net6
- [.NET Desktop Runtime 6.0](https://dotnet.microsoft.com/download/dotnet/6.0)
## Usage
@@ -63,8 +69,8 @@ First, use my another program [Il2CppDumper](https://github.com/Perfare/Il2CppDu
## Build
* Visual Studio 2019 or newer
* **AssetStudioFBXNative** uses FBX SDK 2020.0.1 VS2017, before building, you need to install the FBX SDK and modify the project file, change include directory and library directory to point to the FBX SDK directory
* Visual Studio 2022 or newer
* **AssetStudioFBXNative** uses [FBX SDK 2020.2.1](https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2020-2-1), before building, you need to install the FBX SDK and modify the project file, change include directory and library directory to point to the FBX SDK directory
## Open source libraries used

View File

@@ -67,26 +67,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>

View File

@@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<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>
<ItemGroup>