mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 19:34:15 +08:00
(UnityFS): implemented encrypted entries.
This commit is contained in:
parent
3203e48d83
commit
12c2690ae3
@ -105,14 +105,34 @@ namespace GameRes.Formats.Unity
|
|||||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||||
{
|
{
|
||||||
var uarc = (UnityBundle)arc;
|
var uarc = (UnityBundle)arc;
|
||||||
var input = new BundleStream (uarc.File, uarc.Segments);
|
Stream input = new BundleStream (uarc.File, uarc.Segments);
|
||||||
return new StreamRegion (input, entry.Offset, entry.Size);
|
input = new StreamRegion (input, entry.Offset, entry.Size);
|
||||||
|
var aent = entry as AssetEntry;
|
||||||
|
if (null == aent || !aent.IsEncrypted)
|
||||||
|
return input;
|
||||||
|
using (input)
|
||||||
|
{
|
||||||
|
var data = new byte[entry.Size];
|
||||||
|
input.Read (data, 0, data.Length);
|
||||||
|
DecryptAsset (data);
|
||||||
|
return new BinMemoryStream (data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static byte[] UnpackLzma (byte[] input, int unpacked_size)
|
internal static byte[] UnpackLzma (byte[] input, int unpacked_size)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void DecryptAsset (byte[] data)
|
||||||
|
{
|
||||||
|
uint key = 0xBF8766F5u;
|
||||||
|
for (int i = 0; i < data.Length; ++i)
|
||||||
|
{
|
||||||
|
key = ((0x343FD * key + 0x269EC3) >> 16) & 0x7FFF; // MSVC rand()
|
||||||
|
data[i] ^= (byte)key;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class BundleEntry : Entry
|
internal class BundleEntry : Entry
|
||||||
@ -124,6 +144,7 @@ namespace GameRes.Formats.Unity
|
|||||||
{
|
{
|
||||||
public BundleEntry Bundle;
|
public BundleEntry Bundle;
|
||||||
public UnityObject AssetObject;
|
public UnityObject AssetObject;
|
||||||
|
public bool IsEncrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class UnityBundle : ArcFile
|
internal class UnityBundle : ArcFile
|
||||||
@ -209,7 +230,7 @@ namespace GameRes.Formats.Unity
|
|||||||
{
|
{
|
||||||
var asset = new Asset();
|
var asset = new Asset();
|
||||||
asset.Load (reader);
|
asset.Load (reader);
|
||||||
var object_dir = ParseAsset (bundle, asset, stream);
|
var object_dir = ParseAsset (stream, bundle, asset);
|
||||||
dir.AddRange (object_dir);
|
dir.AddRange (object_dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,7 +240,7 @@ namespace GameRes.Formats.Unity
|
|||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Entry> ParseAsset (BundleEntry bundle, Asset asset, Stream file)
|
IEnumerable<Entry> ParseAsset (Stream file, BundleEntry bundle, Asset asset)
|
||||||
{
|
{
|
||||||
Dictionary<long, string> id_map = null;
|
Dictionary<long, string> id_map = null;
|
||||||
var bundle_types = asset.Tree.TypeTrees.Where (t => t.Value.Type == "AssetBundle").Select (t => t.Key);
|
var bundle_types = asset.Tree.TypeTrees.Where (t => t.Value.Type == "AssetBundle").Select (t => t.Key);
|
||||||
@ -241,7 +262,11 @@ namespace GameRes.Formats.Unity
|
|||||||
AssetEntry entry = null;
|
AssetEntry entry = null;
|
||||||
if ("AudioClip" == type)
|
if ("AudioClip" == type)
|
||||||
{
|
{
|
||||||
entry = ReadAudioClip (file, obj, asset);
|
entry = ReadAudioClip (file, obj);
|
||||||
|
}
|
||||||
|
else if ("TextAsset" == type)
|
||||||
|
{
|
||||||
|
entry = ReadTextAsset (file, obj);
|
||||||
}
|
}
|
||||||
if (null == entry)
|
if (null == entry)
|
||||||
{
|
{
|
||||||
@ -253,9 +278,11 @@ namespace GameRes.Formats.Unity
|
|||||||
Size = obj.Size,
|
Size = obj.Size,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (null == entry.Bundle)
|
||||||
|
entry.Bundle = bundle;
|
||||||
string name;
|
string name;
|
||||||
if (!id_map.TryGetValue (obj.PathId, out name))
|
if (!id_map.TryGetValue (obj.PathId, out name))
|
||||||
name = obj.PathId.ToString ("X16");
|
name = GetObjectName (file, obj);
|
||||||
else
|
else
|
||||||
name = ShortenPath (name);
|
name = ShortenPath (name);
|
||||||
entry.Name = name;
|
entry.Name = name;
|
||||||
@ -263,12 +290,56 @@ namespace GameRes.Formats.Unity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetEntry ReadAudioClip (Stream input, UnityObject obj, Asset asset)
|
string GetObjectName (Stream input, UnityObject obj)
|
||||||
{
|
{
|
||||||
using (var stream = new StreamRegion (input, obj.Offset, obj.Size, true))
|
TypeTree type;
|
||||||
using (var reader = new AssetReader (stream, ""))
|
if (obj.Asset.Tree.TypeTrees.TryGetValue (obj.TypeId, out type) && type.Children.Count > 0)
|
||||||
|
{
|
||||||
|
var first_field = type.Children[0];
|
||||||
|
if ("m_Name" == first_field.Name && "string" == first_field.Type)
|
||||||
|
{
|
||||||
|
using (var reader = obj.Open (input))
|
||||||
|
{
|
||||||
|
var name = reader.ReadString();
|
||||||
|
if (!string.IsNullOrEmpty (name))
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj.PathId.ToString ("X16");
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetEntry ReadTextAsset (Stream input, UnityObject obj)
|
||||||
|
{
|
||||||
|
var type_def = obj.Asset.Tree.TypeTrees[obj.TypeId];
|
||||||
|
var script = type_def.Children.FirstOrDefault (f => f.Name == "m_Script");
|
||||||
|
if (null == script)
|
||||||
|
return null;
|
||||||
|
using (var reader = obj.Open (input))
|
||||||
|
{
|
||||||
|
var name = reader.ReadString();
|
||||||
|
reader.Align();
|
||||||
|
uint size = reader.ReadUInt32();
|
||||||
|
var entry = new AssetEntry {
|
||||||
|
AssetObject = obj,
|
||||||
|
Offset = obj.Offset + reader.Position,
|
||||||
|
Size = size,
|
||||||
|
IsEncrypted = 0 != (script.Flags & 0x04000000),
|
||||||
|
};
|
||||||
|
if (entry.IsEncrypted)
|
||||||
|
{
|
||||||
|
uint signature = reader.ReadUInt32();
|
||||||
|
if (0x0D15F641 == signature)
|
||||||
|
entry.Type = "image";
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetEntry ReadAudioClip (Stream input, UnityObject obj)
|
||||||
|
{
|
||||||
|
using (var reader = obj.Open (input))
|
||||||
{
|
{
|
||||||
reader.SetupReaders (asset.Format, asset.IsLittleEndian);
|
|
||||||
var clip = new AudioClip();
|
var clip = new AudioClip();
|
||||||
clip.Load (reader);
|
clip.Load (reader);
|
||||||
var bundle_name = Path.GetFileName (clip.m_Source);
|
var bundle_name = Path.GetFileName (clip.m_Source);
|
||||||
|
@ -198,6 +198,14 @@ namespace GameRes.Formats.Unity
|
|||||||
Asset = owner;
|
Asset = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AssetReader Open (Stream input)
|
||||||
|
{
|
||||||
|
var stream = new StreamRegion (input, Offset, Size, true);
|
||||||
|
var reader = new AssetReader (stream, "");
|
||||||
|
reader.SetupReaders (Asset.Format, Asset.IsLittleEndian);
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
public void Load (AssetReader reader)
|
public void Load (AssetReader reader)
|
||||||
{
|
{
|
||||||
PathId = reader.ReadId();
|
PathId = reader.ReadId();
|
||||||
@ -451,4 +459,66 @@ namespace GameRes.Formats.Unity
|
|||||||
m_CompressionFormat = reader.ReadInt32();
|
m_CompressionFormat = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TextureFormat : int
|
||||||
|
{
|
||||||
|
Alpha8 = 1,
|
||||||
|
ARGB4444 = 2,
|
||||||
|
RGB24 = 3,
|
||||||
|
RGBA32 = 4,
|
||||||
|
ARGB32 = 5,
|
||||||
|
R16 = 6, // A 16 bit color texture format that only has a red channel.
|
||||||
|
RGB565 = 7,
|
||||||
|
DXT1 = 10,
|
||||||
|
DXT5 = 12,
|
||||||
|
RGBA4444 = 13,
|
||||||
|
BGRA32 = 14,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Texture2D
|
||||||
|
{
|
||||||
|
public string m_Name;
|
||||||
|
public int m_Width;
|
||||||
|
public int m_Height;
|
||||||
|
public int m_CompleteImageSize;
|
||||||
|
public TextureFormat m_TextureFormat;
|
||||||
|
public int m_MipCount;
|
||||||
|
public bool m_IsReadable;
|
||||||
|
public bool m_ReadAllowed;
|
||||||
|
public int m_ImageCount;
|
||||||
|
public int m_TextureDimension;
|
||||||
|
public int m_FilterMode;
|
||||||
|
public int m_Aniso;
|
||||||
|
public int m_MipBias;
|
||||||
|
public int m_WrapMode;
|
||||||
|
public int m_LightFormat;
|
||||||
|
public int m_ColorSpace;
|
||||||
|
// byte[] m_Data
|
||||||
|
// StreamingInfo m_StreamData
|
||||||
|
// uint offset
|
||||||
|
// uint size
|
||||||
|
// string path
|
||||||
|
|
||||||
|
public void Load (AssetReader reader)
|
||||||
|
{
|
||||||
|
m_Name = reader.ReadString();
|
||||||
|
reader.Align();
|
||||||
|
m_Width = reader.ReadInt32();
|
||||||
|
m_Height = reader.ReadInt32();
|
||||||
|
m_CompleteImageSize = reader.ReadInt32();
|
||||||
|
m_TextureFormat = (TextureFormat)reader.ReadInt32();
|
||||||
|
m_MipCount = reader.ReadInt32();
|
||||||
|
m_IsReadable = reader.ReadBool();
|
||||||
|
m_ReadAllowed = reader.ReadBool();
|
||||||
|
reader.Align();
|
||||||
|
m_ImageCount = reader.ReadInt32();
|
||||||
|
m_TextureDimension = reader.ReadInt32();
|
||||||
|
m_FilterMode = reader.ReadInt32();
|
||||||
|
m_Aniso = reader.ReadInt32();
|
||||||
|
m_MipBias = reader.ReadInt32();
|
||||||
|
m_WrapMode = reader.ReadInt32();
|
||||||
|
m_LightFormat = reader.ReadInt32();
|
||||||
|
m_ColorSpace = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user