(Unity): adjusted deserialization for '2021.1.3f1' assets.

This commit is contained in:
morkt 2022-05-03 13:40:43 +04:00
parent 911efef9b9
commit 30f3eebde9
6 changed files with 79 additions and 14 deletions

View File

@ -42,12 +42,19 @@ namespace GameRes.Formats.Unity
public override ArcFile TryOpen (ArcView file) public override ArcFile TryOpen (ArcView file)
{ {
uint header_size = Binary.BigEndian (file.View.ReadUInt32 (0)); uint header_size = Binary.BigEndian (file.View.ReadUInt32 (0));
uint file_size = Binary.BigEndian (file.View.ReadUInt32 (4)); long file_size = Binary.BigEndian (file.View.ReadUInt32 (4));
if (file_size != file.MaxOffset || header_size > file_size || 0 == header_size)
return null;
int format = Binary.BigEndian (file.View.ReadInt32 (8)); int format = Binary.BigEndian (file.View.ReadInt32 (8));
uint data_offset = Binary.BigEndian (file.View.ReadUInt32 (12)); if (format <= 0 || format > 0x100)
if (format <= 0 || format > 0x100 || data_offset >= file_size || data_offset < header_size) return null;
long data_offset = Binary.BigEndian (file.View.ReadUInt32 (12));
if (format >= 22)
{
header_size = Binary.BigEndian (file.View.ReadUInt32 (0x14));
file_size = Binary.BigEndian (file.View.ReadInt64 (0x18));
data_offset = Binary.BigEndian (file.View.ReadInt64 (0x20));
}
if (file_size != file.MaxOffset || header_size > file_size || 0 == header_size
|| data_offset >= file_size || data_offset < header_size)
return null; return null;
using (var stream = file.CreateStream()) using (var stream = file.CreateStream())
using (var input = new AssetReader (stream)) using (var input = new AssetReader (stream))
@ -84,7 +91,7 @@ namespace GameRes.Formats.Unity
{ {
reader.SetupReaders (obj.Asset); reader.SetupReaders (obj.Asset);
var tex = new Texture2D(); var tex = new Texture2D();
tex.Load (reader, obj.Asset.Tree.Version); tex.Load (reader, obj.Asset.Tree);
if (0 == tex.m_DataLength) if (0 == tex.m_DataLength)
{ {
reader.Dispose(); reader.Dispose();

View File

@ -41,7 +41,7 @@ namespace GameRes.Formats.Unity
internal class Asset internal class Asset
{ {
int m_format; int m_format;
uint m_data_offset; long m_data_offset;
bool m_is_little_endian; bool m_is_little_endian;
UnityTypeData m_tree = new UnityTypeData(); UnityTypeData m_tree = new UnityTypeData();
Dictionary<long, int> m_adds; Dictionary<long, int> m_adds;
@ -63,6 +63,13 @@ namespace GameRes.Formats.Unity
m_data_offset = input.ReadUInt32(); m_data_offset = input.ReadUInt32();
if (m_format >= 9) if (m_format >= 9)
m_is_little_endian = 0 == input.ReadInt32(); m_is_little_endian = 0 == input.ReadInt32();
if (m_format >= 22)
{
input.ReadInt32(); // header_size
input.ReadInt64(); // file_size
m_data_offset = input.ReadInt64();
input.ReadInt64();
}
input.SetupReaders (this); input.SetupReaders (this);
m_tree.Load (input); m_tree.Load (input);
@ -176,7 +183,8 @@ namespace GameRes.Formats.Unity
public void Load (AssetReader reader) public void Load (AssetReader reader)
{ {
PathId = reader.ReadId(); PathId = reader.ReadId();
Offset = reader.ReadUInt32() + Asset.DataOffset; Offset = reader.ReadOffset();
Offset += Asset.DataOffset;
Size = reader.ReadUInt32(); Size = reader.ReadUInt32();
if (Asset.Format < 17) if (Asset.Format < 17)
{ {

View File

@ -65,6 +65,7 @@ namespace GameRes.Formats.Unity
public Func<int> ReadInt32; public Func<int> ReadInt32;
public Func<long> ReadInt64; public Func<long> ReadInt64;
public Func<long> ReadId; public Func<long> ReadId;
public Func<long> ReadOffset;
public void SetupReaders (Asset asset) public void SetupReaders (Asset asset)
{ {
@ -109,6 +110,10 @@ namespace GameRes.Formats.Unity
ReadId = ReadInt64; ReadId = ReadInt64;
else else
ReadId = () => ReadInt32(); ReadId = () => ReadInt32();
if (m_format >= 22)
ReadOffset = ReadInt64;
else
ReadOffset = () => ReadUInt32();
} }
/// <summary> /// <summary>
@ -122,6 +127,11 @@ namespace GameRes.Formats.Unity
ReadId = () => ReadInt32(); ReadId = () => ReadInt32();
} }
public void Skip (int count)
{
m_input.Seek (count, SeekOrigin.Current);
}
/// <summary> /// <summary>
/// Read bytes into specified buffer. /// Read bytes into specified buffer.
/// </summary> /// </summary>

View File

@ -97,13 +97,13 @@ namespace GameRes.Formats.Unity
internal class StreamingInfo internal class StreamingInfo
{ {
public uint Offset; public long Offset;
public uint Size; public uint Size;
public string Path; public string Path;
public void Load (AssetReader reader) public void Load (AssetReader reader)
{ {
Offset = reader.ReadUInt32(); Offset = reader.ReadOffset();
Size = reader.ReadUInt32(); Size = reader.ReadUInt32();
Path = reader.ReadString(); Path = reader.ReadString();
} }

View File

@ -61,7 +61,7 @@ namespace GameRes.Formats.Unity
case 28: // Texture2D case 28: // Texture2D
{ {
var tex = new Texture2D(); var tex = new Texture2D();
tex.Load (input, asset.Tree.Version); tex.Load (input, asset.Tree);
if (0 == tex.m_DataLength) if (0 == tex.m_DataLength)
{ {
var stream_data = new StreamingInfo(); var stream_data = new StreamingInfo();

View File

@ -97,12 +97,17 @@ namespace GameRes.Formats.Unity
m_DataLength = reader.ReadInt32(); m_DataLength = reader.ReadInt32();
} }
public void Load (AssetReader reader, string version) public void Load (AssetReader reader, UnityTypeData type)
{ {
if (version != "2017.3.1f1") if ("2021.1.3f1" == type.Version) // type.Hashes[28] == [0D 08 41 4C FD 5B DB 0D 22 79 20 11 BD A9 AB 26]
{
Load2021 (reader);
return;
}
if (type.Version != "2017.3.1f1")
{ {
Load (reader); Load (reader);
if (0 == m_DataLength && version.StartsWith ("2017.")) // "2017.2.0f3" || "2017.1.1p1" if (0 == m_DataLength && type.Version.StartsWith ("2017.")) // "2017.2.0f3" || "2017.1.1p1"
reader.ReadInt64(); reader.ReadInt64();
return; return;
} }
@ -130,6 +135,35 @@ namespace GameRes.Formats.Unity
m_DataLength = reader.ReadInt32(); m_DataLength = reader.ReadInt32();
} }
public void Load2021 (AssetReader reader)
{
m_Name = reader.ReadString();
reader.Align();
reader.ReadInt32(); // m_ForcedFallbackFormat
reader.ReadInt32(); // m_DownscaleFallback
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
m_CompleteImageSize = reader.ReadInt32();
reader.ReadInt32(); // m_MipsStripped;
m_TextureFormat = (TextureFormat)reader.ReadInt32();
m_MipCount = reader.ReadInt32();
m_IsReadable = reader.ReadBool();
reader.Align();
reader.ReadInt32(); // m_StreamingMipmapsPriority
m_ImageCount = reader.ReadInt32();
m_TextureDimension = reader.ReadInt32();
m_FilterMode = reader.ReadInt32();
m_Aniso = reader.ReadInt32();
m_MipBias = reader.ReadFloat();
m_WrapMode = reader.ReadInt32(); // m_WrapU
reader.ReadInt32(); // m_WrapV
reader.ReadInt32(); // m_WrapW
reader.ReadInt32(); // m_LightmapFormat
m_ColorSpace = reader.ReadInt32();
reader.ReadInt32();
m_DataLength = reader.ReadInt32();
}
public void LoadData (AssetReader reader) public void LoadData (AssetReader reader)
{ {
m_Data = reader.ReadBytes (m_DataLength); m_Data = reader.ReadBytes (m_DataLength);
@ -243,6 +277,12 @@ namespace GameRes.Formats.Unity
pixels = ConvertArgb16 (m_texture.m_Data); pixels = ConvertArgb16 (m_texture.m_Data);
break; break;
case TextureFormat.BC7:
{
var decoder = new Bc7Decoder (m_texture.m_Data, Info);
pixels = decoder.Unpack();
break;
}
default: default:
throw new NotImplementedException (string.Format ("Not supported Unity Texture2D format '{0}'.", m_texture.m_TextureFormat)); throw new NotImplementedException (string.Format ("Not supported Unity Texture2D format '{0}'.", m_texture.m_TextureFormat));
} }