diff --git a/Unity Studio/Unity Classes/AudioClip.cs b/Unity Studio/Unity Classes/AudioClip.cs index 0c927c2..419c895 100644 --- a/Unity Studio/Unity Classes/AudioClip.cs +++ b/Unity Studio/Unity Classes/AudioClip.cs @@ -110,7 +110,7 @@ namespace Unity_Studio } else { - EndianStream estream; + EndianBinaryReader estream; if (UnityStudio.assetsfileandstream.TryGetValue(Path.GetFileName(m_Source), out estream)) { estream.Position = m_Offset; diff --git a/Unity Studio/Unity Classes/Mesh.cs b/Unity Studio/Unity Classes/Mesh.cs index dc53a5e..e5a33ff 100644 --- a/Unity Studio/Unity Classes/Mesh.cs +++ b/Unity Studio/Unity Classes/Mesh.cs @@ -102,7 +102,7 @@ namespace Unity_Studio { public class Mesh { - private EndianStream a_Stream; + private EndianBinaryReader a_Stream; public string m_Name; public List m_SubMeshes = new List(); public List m_Indices = new List(); //use a list because I don't always know the facecount for triangle strips diff --git a/Unity Studio/Unity Classes/Shader.cs b/Unity Studio/Unity Classes/Shader.cs index ea40b7d..c4d105c 100644 --- a/Unity Studio/Unity Classes/Shader.cs +++ b/Unity Studio/Unity Classes/Shader.cs @@ -66,7 +66,7 @@ namespace Unity_Studio } } - private static byte[] ReadSerializedShader(List members, EndianStream a_Stream) + private static byte[] ReadSerializedShader(List members, EndianBinaryReader a_Stream) { var offsets = new List(); var compressedLengths = new List(); diff --git a/Unity Studio/Unity Classes/Texture2D.cs b/Unity Studio/Unity Classes/Texture2D.cs index 4fc892c..8e8576d 100644 --- a/Unity Studio/Unity Classes/Texture2D.cs +++ b/Unity Studio/Unity Classes/Texture2D.cs @@ -180,7 +180,7 @@ namespace Unity_Studio } else { - EndianStream estream; + EndianBinaryReader estream; if (UnityStudio.assetsfileandstream.TryGetValue(Path.GetFileName(path), out estream)) { estream.Position = offset; diff --git a/Unity Studio/Unity Studio Classes/AssetsFile.cs b/Unity Studio/Unity Studio Classes/AssetsFile.cs index 9cafdac..cd84b75 100644 --- a/Unity Studio/Unity Studio Classes/AssetsFile.cs +++ b/Unity Studio/Unity Studio Classes/AssetsFile.cs @@ -9,7 +9,7 @@ namespace Unity_Studio { public class AssetsFile { - public EndianStream a_Stream; + public EndianBinaryReader a_Stream; public string filePath; public string bundlePath; public string fileName; @@ -150,7 +150,7 @@ namespace Unity_Studio public string fileName = ""; } - public AssetsFile(string fullName, EndianStream fileStream) + public AssetsFile(string fullName, EndianBinaryReader fileStream) { a_Stream = fileStream; filePath = fullName; diff --git a/Unity Studio/Unity Studio Classes/BundleFile.cs b/Unity Studio/Unity Studio Classes/BundleFile.cs index 8b81dfb..38537a7 100644 --- a/Unity Studio/Unity Studio Classes/BundleFile.cs +++ b/Unity Studio/Unity Studio Classes/BundleFile.cs @@ -42,87 +42,91 @@ namespace Unity_Studio decoder.Dispose(); } } - using (var b_Stream = new EndianStream(new MemoryStream(filebuffer), EndianType.BigEndian)) + using (var b_Stream = new EndianBinaryReader(new MemoryStream(filebuffer))) { readBundle(b_Stream); } } else { - using (var b_Stream = new EndianStream(File.OpenRead(fileName), EndianType.BigEndian)) + using (var b_Stream = new EndianBinaryReader(File.OpenRead(fileName))) { readBundle(b_Stream); } } } - private void readBundle(EndianStream b_Stream) + private void readBundle(EndianBinaryReader b_Stream) { var signature = b_Stream.ReadStringToNull(); - - if (signature == "UnityWeb" || signature == "UnityRaw" || signature == "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA") + switch (signature) { - format = b_Stream.ReadInt32(); - versionPlayer = b_Stream.ReadStringToNull(); - versionEngine = b_Stream.ReadStringToNull(); - if (format < 6) - { - int bundleSize = b_Stream.ReadInt32(); - } - else if (format == 6) - { - ReadFormat6(b_Stream, true); - return; - } - short dummy2 = b_Stream.ReadInt16(); - int offset = b_Stream.ReadInt16(); - int dummy3 = b_Stream.ReadInt32(); - int lzmaChunks = b_Stream.ReadInt32(); - - int lzmaSize = 0; - long streamSize = 0; - - for (int i = 0; i < lzmaChunks; i++) - { - lzmaSize = b_Stream.ReadInt32(); - streamSize = b_Stream.ReadInt32(); - } - - b_Stream.Position = offset; - switch (signature) - { - case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": //.bytes - case "UnityWeb": + case "UnityWeb": + case "UnityRaw": + case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": + { + format = b_Stream.ReadInt32(); + versionPlayer = b_Stream.ReadStringToNull(); + versionEngine = b_Stream.ReadStringToNull(); + if (format < 6) { - byte[] lzmaBuffer = new byte[lzmaSize]; - b_Stream.Read(lzmaBuffer, 0, lzmaSize); - - using (var lzmaStream = new EndianStream(SevenZipHelper.StreamDecompress(new MemoryStream(lzmaBuffer)), EndianType.BigEndian)) - { - getFiles(lzmaStream, 0); - } - break; + int bundleSize = b_Stream.ReadInt32(); } - case "UnityRaw": + else if (format == 6) { - getFiles(b_Stream, offset); - break; + ReadFormat6(b_Stream, true); + return; } - } - } - else if (signature == "UnityFS") - { - format = b_Stream.ReadInt32(); - versionPlayer = b_Stream.ReadStringToNull(); - versionEngine = b_Stream.ReadStringToNull(); - if (format == 6) - { - ReadFormat6(b_Stream); - } + short dummy2 = b_Stream.ReadInt16(); + int offset = b_Stream.ReadInt16(); + int dummy3 = b_Stream.ReadInt32(); + int lzmaChunks = b_Stream.ReadInt32(); + + int lzmaSize = 0; + long streamSize = 0; + + for (int i = 0; i < lzmaChunks; i++) + { + lzmaSize = b_Stream.ReadInt32(); + streamSize = b_Stream.ReadInt32(); + } + + b_Stream.Position = offset; + switch (signature) + { + case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": //.bytes + case "UnityWeb": + { + byte[] lzmaBuffer = new byte[lzmaSize]; + b_Stream.Read(lzmaBuffer, 0, lzmaSize); + + using (var lzmaStream = new EndianBinaryReader(SevenZipHelper.StreamDecompress(new MemoryStream(lzmaBuffer)))) + { + getFiles(lzmaStream, 0); + } + break; + } + case "UnityRaw": + { + getFiles(b_Stream, offset); + break; + } + } + break; + } + case "UnityFS": + format = b_Stream.ReadInt32(); + versionPlayer = b_Stream.ReadStringToNull(); + versionEngine = b_Stream.ReadStringToNull(); + if (format == 6) + { + ReadFormat6(b_Stream); + } + break; } } - private void getFiles(EndianStream f_Stream, int offset) + private void getFiles(EndianBinaryReader f_Stream, int offset) { int fileCount = f_Stream.ReadInt32(); for (int i = 0; i < fileCount; i++) @@ -143,7 +147,7 @@ namespace Unity_Studio } } - private void ReadFormat6(EndianStream b_Stream, bool padding = false) + private void ReadFormat6(EndianBinaryReader b_Stream, bool padding = false) { var bundleSize = b_Stream.ReadInt64(); int compressedSize = b_Stream.ReadInt32(); @@ -163,17 +167,17 @@ namespace Unity_Studio { blocksInfoBytes = b_Stream.ReadBytes(compressedSize); } - EndianStream blocksInfo; + MemoryStream blocksInfoStream; switch (flag & 0x3F) { default://None { - blocksInfo = new EndianStream(new MemoryStream(blocksInfoBytes), EndianType.BigEndian); + blocksInfoStream = new MemoryStream(blocksInfoBytes); break; } case 1://LZMA { - blocksInfo = new EndianStream(SevenZipHelper.StreamDecompress(new MemoryStream(blocksInfoBytes)), EndianType.BigEndian); + blocksInfoStream = SevenZipHelper.StreamDecompress(new MemoryStream(blocksInfoBytes)); break; } case 2://LZ4 @@ -186,16 +190,15 @@ namespace Unity_Studio decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } - blocksInfo = new EndianStream(new MemoryStream(uncompressedBytes), EndianType.BigEndian); + blocksInfoStream = new MemoryStream(uncompressedBytes); break; } //case 4:LZHAM? } - using (blocksInfo) + using (var blocksInfo = new EndianBinaryReader(blocksInfoStream)) { blocksInfo.Position = 0x10; int blockcount = blocksInfo.ReadInt32(); - EndianStream assetsData; var assetsDataStream = new MemoryStream(); for (int i = 0; i < blockcount; i++) { @@ -238,8 +241,7 @@ namespace Unity_Studio //case 4:LZHAM? } } - assetsData = new EndianStream(assetsDataStream, EndianType.BigEndian); - using (assetsData) + using (var assetsData = new EndianBinaryReader(assetsDataStream)) { var entryinfo_count = blocksInfo.ReadInt32(); for (int i = 0; i < entryinfo_count; i++) diff --git a/Unity Studio/Unity Studio Classes/ClassStruct.cs b/Unity Studio/Unity Studio Classes/ClassStruct.cs index c3963e1..d616644 100644 --- a/Unity Studio/Unity Studio Classes/ClassStruct.cs +++ b/Unity Studio/Unity Studio Classes/ClassStruct.cs @@ -53,7 +53,7 @@ namespace Unity_Studio return null; } - private static void ReadClassStruct(StringBuilder sb, List members, EndianStream a_Stream) + private static void ReadClassStruct(StringBuilder sb, List members, EndianBinaryReader a_Stream) { for (int i = 0; i < members.Count; i++) { diff --git a/Unity Studio/Unity Studio Classes/EndianStream.cs b/Unity Studio/Unity Studio Classes/EndianBinaryReader.cs similarity index 93% rename from Unity Studio/Unity Studio Classes/EndianStream.cs rename to Unity Studio/Unity Studio Classes/EndianBinaryReader.cs index 3ed5894..e453e12 100644 --- a/Unity Studio/Unity Studio Classes/EndianStream.cs +++ b/Unity Studio/Unity Studio Classes/EndianBinaryReader.cs @@ -11,16 +11,20 @@ namespace Unity_Studio LittleEndian } - public class EndianStream : BinaryReader + public class EndianBinaryReader : BinaryReader { public EndianType endian; private byte[] a16 = new byte[2]; private byte[] a32 = new byte[4]; private byte[] a64 = new byte[8]; - public EndianStream(Stream stream, EndianType endian) : base(stream) { } + public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream) { this.endian = endian; } - public long Position { get { return BaseStream.Position; } set { BaseStream.Position = value; } } + public long Position + { + get => BaseStream.Position; + set => BaseStream.Position = value; + } public override short ReadInt16() { diff --git a/Unity Studio/Unity Studio Classes/UnityStudio.cs b/Unity Studio/Unity Studio Classes/UnityStudio.cs index 4dd795f..88220c5 100644 --- a/Unity Studio/Unity Studio Classes/UnityStudio.cs +++ b/Unity Studio/Unity Studio Classes/UnityStudio.cs @@ -17,7 +17,7 @@ namespace Unity_Studio public static HashSet unityFilesHash = new HashSet(); //improve performance public static List assetsfileList = new List(); //loaded files public static HashSet assetsfileListHash = new HashSet(); //improve performance - public static Dictionary assetsfileandstream = new Dictionary(); //use for read res files + public static Dictionary assetsfileandstream = new Dictionary(); //use for read res files public static List exportableAssets = new List(); //used to hold all assets while the ListView is filtered private static HashSet exportableAssetsHash = new HashSet(); //improve performance public static List visibleAssets = new List(); //used to build the ListView from all or filtered assets @@ -44,7 +44,7 @@ namespace Unity_Studio { //open file here and pass the stream to facilitate loading memory files //also by keeping the stream as a property of AssetsFile, it can be used later on to read assets - AssetsFile assetsFile = new AssetsFile(fileName, new EndianStream(File.OpenRead(fileName), EndianType.BigEndian)); + AssetsFile assetsFile = new AssetsFile(fileName, new EndianBinaryReader(File.OpenRead(fileName))); //if (Path.GetFileName(fileName) == "mainData") { mainDataFile = assetsFile; } //totalAssetCount += assetsFile.preloadTable.Count; @@ -64,7 +64,7 @@ namespace Unity_Studio } else if (File.Exists(Path.GetDirectoryName(fileName) + "\\mainData")) { - mainDataFile = new AssetsFile(Path.GetDirectoryName(fileName) + "\\mainData", new EndianStream(File.OpenRead(Path.GetDirectoryName(fileName) + "\\mainData"), EndianType.BigEndian)); + mainDataFile = new AssetsFile(Path.GetDirectoryName(fileName) + "\\mainData", new EndianBinaryReader(File.OpenRead(Path.GetDirectoryName(fileName) + "\\mainData"))); assetsFile.m_Version = mainDataFile.m_Version; assetsFile.version = mainDataFile.version; @@ -131,7 +131,7 @@ namespace Unity_Studio StatusStripUpdate("Loading " + memFile.fileName); //create dummy path to be used for asset extraction memFile.fileName = Path.GetDirectoryName(bundleFileName) + "\\" + memFile.fileName; - AssetsFile assetsFile = new AssetsFile(memFile.fileName, new EndianStream(memFile.memStream, EndianType.BigEndian)); + AssetsFile assetsFile = new AssetsFile(memFile.fileName, new EndianBinaryReader(memFile.memStream)); if (assetsFile.valid) { assetsFile.bundlePath = bundleFileName; @@ -186,7 +186,7 @@ namespace Unity_Studio { int extractedCount = 0; - StatusStripUpdate("Decompressing " + Path.GetFileName(bundleFileName) + " ,,,"); + StatusStripUpdate("Decompressing " + Path.GetFileName(bundleFileName) + " ..."); string extractPath = bundleFileName + "_unpacked\\"; Directory.CreateDirectory(extractPath); @@ -1822,5 +1822,23 @@ namespace Unity_Studio if (str.Length >= 260) return Path.GetRandomFileName(); return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_')); } + + public static bool CheckBundleFile(string fileName) + { + using (var stream = new EndianBinaryReader(File.OpenRead(fileName))) + { + var signature = stream.ReadStringToNull(); + switch (signature) + { + case "UnityWeb": + case "UnityRaw": + case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": + case "UnityFS": + return true; + default: + return false; + } + } + } } } diff --git a/Unity Studio/Unity Studio.csproj b/Unity Studio/Unity Studio.csproj index e85bccb..16a4447 100644 --- a/Unity Studio/Unity Studio.csproj +++ b/Unity Studio/Unity Studio.csproj @@ -149,7 +149,7 @@ - + Form diff --git a/Unity Studio/UnityStudioForm.cs b/Unity Studio/UnityStudioForm.cs index cbe4c3d..4c411ea 100644 --- a/Unity Studio/UnityStudioForm.cs +++ b/Unity Studio/UnityStudioForm.cs @@ -91,7 +91,13 @@ namespace Unity_Studio { MergeSplitAssets(mainPath); - //unityFiles.AddRange(openFileDialog1.FileNames); + //Only verify whether the first file is bundle file + if (CheckBundleFile(openFileDialog1.FileNames[0])) + { + MessageBox.Show($"{Path.GetFileName(openFileDialog1.FileNames[0])} is bundle file, please select bundle file type to load this file"); + return; + } + foreach (var i in openFileDialog1.FileNames) { unityFiles.Add(i); @@ -197,7 +203,7 @@ namespace Unity_Studio private void extractBundleToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog openBundleDialog = new OpenFileDialog(); - openBundleDialog.Filter = "Unity bundle files|*.unity3d; *.unity3d.lz4; *.assetbundle; *.bundle; *.bytes|All files (use at your own risk!)|*.*"; + openBundleDialog.Filter = "Unity bundle files|*.*"; openBundleDialog.FilterIndex = 1; openBundleDialog.RestoreDirectory = true; openBundleDialog.Multiselect = true;