mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 11:24:14 +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)
|
||||
{
|
||||
var uarc = (UnityBundle)arc;
|
||||
var input = new BundleStream (uarc.File, uarc.Segments);
|
||||
return new StreamRegion (input, entry.Offset, entry.Size);
|
||||
Stream input = new BundleStream (uarc.File, uarc.Segments);
|
||||
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)
|
||||
{
|
||||
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
|
||||
@ -124,6 +144,7 @@ namespace GameRes.Formats.Unity
|
||||
{
|
||||
public BundleEntry Bundle;
|
||||
public UnityObject AssetObject;
|
||||
public bool IsEncrypted;
|
||||
}
|
||||
|
||||
internal class UnityBundle : ArcFile
|
||||
@ -209,7 +230,7 @@ namespace GameRes.Formats.Unity
|
||||
{
|
||||
var asset = new Asset();
|
||||
asset.Load (reader);
|
||||
var object_dir = ParseAsset (bundle, asset, stream);
|
||||
var object_dir = ParseAsset (stream, bundle, asset);
|
||||
dir.AddRange (object_dir);
|
||||
}
|
||||
}
|
||||
@ -219,7 +240,7 @@ namespace GameRes.Formats.Unity
|
||||
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;
|
||||
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;
|
||||
if ("AudioClip" == type)
|
||||
{
|
||||
entry = ReadAudioClip (file, obj, asset);
|
||||
entry = ReadAudioClip (file, obj);
|
||||
}
|
||||
else if ("TextAsset" == type)
|
||||
{
|
||||
entry = ReadTextAsset (file, obj);
|
||||
}
|
||||
if (null == entry)
|
||||
{
|
||||
@ -253,9 +278,11 @@ namespace GameRes.Formats.Unity
|
||||
Size = obj.Size,
|
||||
};
|
||||
}
|
||||
if (null == entry.Bundle)
|
||||
entry.Bundle = bundle;
|
||||
string name;
|
||||
if (!id_map.TryGetValue (obj.PathId, out name))
|
||||
name = obj.PathId.ToString ("X16");
|
||||
name = GetObjectName (file, obj);
|
||||
else
|
||||
name = ShortenPath (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))
|
||||
using (var reader = new AssetReader (stream, ""))
|
||||
TypeTree type;
|
||||
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();
|
||||
clip.Load (reader);
|
||||
var bundle_name = Path.GetFileName (clip.m_Source);
|
||||
|
@ -198,6 +198,14 @@ namespace GameRes.Formats.Unity
|
||||
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)
|
||||
{
|
||||
PathId = reader.ReadId();
|
||||
@ -451,4 +459,66 @@ namespace GameRes.Formats.Unity
|
||||
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