diff --git a/AssetStudio/AssetsHelper.cs b/AssetStudio/AssetsHelper.cs index 3c8fdc8..060a9aa 100644 --- a/AssetStudio/AssetsHelper.cs +++ b/AssetStudio/AssetsHelper.cs @@ -110,16 +110,29 @@ namespace AssetStudio private static IEnumerable LoadFiles(string[] files) { - for (int i = 0; i < files.Length; i++) + string msg; + + var path = Path.GetDirectoryName(Path.GetFullPath(files[0])); + ImportHelper.MergeSplitAssets(path); + var toReadFile = ImportHelper.ProcessingSplitFiles(files.ToList()); + + var filesList = new List(toReadFile); + for (int i = 0; i < filesList.Count; i++) { - var file = files[i]; + var file = filesList[i]; assetsManager.LoadFiles(file); if (assetsManager.assetsFileList.Count > 0) { yield return file; - Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}"); - Progress.Report(i + 1, files.Length); + msg = $"Processed {Path.GetFileName(file)}"; } + else + { + filesList.Remove(file); + msg = $"Removed {Path.GetFileName(file)}, no assets found"; + } + Logger.Info($"[{i + 1}/{filesList.Count}] {msg}"); + Progress.Report(i + 1, filesList.Count); assetsManager.Clear(); } } diff --git a/AssetStudio/AssetsManager.cs b/AssetStudio/AssetsManager.cs index e5e281d..1e078df 100644 --- a/AssetStudio/AssetsManager.cs +++ b/AssetStudio/AssetsManager.cs @@ -28,6 +28,23 @@ namespace AssetStudio internal HashSet noexistFiles = new HashSet(StringComparer.OrdinalIgnoreCase); internal HashSet assetsFileListHash = new HashSet(StringComparer.OrdinalIgnoreCase); + public void LoadFiles(string file) + { + if (Silent) + { + Logger.Silent = true; + Progress.Silent = true; + } + + Load(new string[] { file }); + + if (Silent) + { + Logger.Silent = false; + Progress.Silent = false; + } + } + public void LoadFiles(params string[] files) { if (Silent) diff --git a/AssetStudio/GameManager.cs b/AssetStudio/GameManager.cs index dd2419d..e19087d 100644 --- a/AssetStudio/GameManager.cs +++ b/AssetStudio/GameManager.cs @@ -34,6 +34,7 @@ namespace AssetStudio Games.Add(index++, new Game(GameType.HelixWaltz2)); Games.Add(index++, new Game(GameType.NetEase)); Games.Add(index++, new Game(GameType.AnchorPanic)); + Games.Add(index++, new Game(GameType.DreamscapeAlbireo)); } public static Game GetGame(GameType gameType) => GetGame((int)gameType); public static Game GetGame(int index) @@ -138,7 +139,8 @@ namespace AssetStudio ShiningNikki, HelixWaltz2, NetEase, - AnchorPanic + AnchorPanic, + DreamscapeAlbireo } public static class GameTypes diff --git a/AssetStudio/ImportHelper.cs b/AssetStudio/ImportHelper.cs index 0a06e4c..2915d34 100644 --- a/AssetStudio/ImportHelper.cs +++ b/AssetStudio/ImportHelper.cs @@ -530,5 +530,66 @@ namespace AssetStudio } } } + + public static FileReader DecryptDreamscapeAlbireo(FileReader reader) + { + var key = new byte[] { 0x1E, 0x1E, 0x01, 0x01, 0xFC }; + + var signature = reader.ReadStringToNull(4); + if (signature != "MJJ") + { + reader.Position = 0; + return reader; + } + + reader.Endian = EndianType.BigEndian; + + var u1 = reader.ReadUInt32(); + var u2 = reader.ReadUInt32(); + var u3 = reader.ReadUInt32(); + var u4 = reader.ReadUInt32(); + var u5 = reader.ReadUInt32(); + var u6 = reader.ReadUInt32(); + + var flag = Scrample(u4) ^ 0x70020017; + var compressedBlocksInfoSize = Scrample(u1) ^ u4; + var uncompressedBlocksInfoSize = Scrample(u6) ^ u1; + + var sizeHigh = (u5 & 0xFFFFFF00 | u2 >> 24) ^ u4; + var sizeLow = (u5 >> 24 | (u2 << 8)) ^ u1; + var size = (long)(sizeHigh << 32 | sizeLow); + + var blocksInfo = reader.ReadBytes((int)compressedBlocksInfoSize); + for(int i = 0; i < blocksInfo.Length; i++) + { + blocksInfo[i] ^= key[i % key.Length]; + } + + var data = reader.ReadBytes((int)reader.Remaining); + + var buffer = (stackalloc byte[8]); + MemoryStream ms = new(); + ms.Write(Encoding.UTF8.GetBytes("UnityFS\x00")); + BinaryPrimitives.WriteUInt32BigEndian(buffer, 6); + ms.Write(buffer[..4]); + ms.Write(Encoding.UTF8.GetBytes("5.x.x\x00")); + ms.Write(Encoding.UTF8.GetBytes("2018.4.2f1\x00")); + BinaryPrimitives.WriteInt64BigEndian(buffer, size); + ms.Write(buffer); + BinaryPrimitives.WriteUInt32BigEndian(buffer, compressedBlocksInfoSize); + ms.Write(buffer[..4]); + BinaryPrimitives.WriteUInt32BigEndian(buffer, uncompressedBlocksInfoSize); + ms.Write(buffer[..4]); + BinaryPrimitives.WriteUInt32BigEndian(buffer, flag); + ms.Write(buffer[..4]); + ms.Write(blocksInfo); + ms.Write(data); + reader.BaseStream.CopyTo(ms); + ms.Position = 0; + + return new FileReader(reader.FullPath, ms); + + static uint Scrample(uint value) => (value >> 5) & 0xFFE000 | (value >> 29) | (value << 14) & 0xFF000000 | (8 * value) & 0x1FF8; + } } } diff --git a/AssetStudio/UnityCNManager.cs b/AssetStudio/UnityCNManager.cs index ccfb420..a182e3b 100644 --- a/AssetStudio/UnityCNManager.cs +++ b/AssetStudio/UnityCNManager.cs @@ -14,7 +14,7 @@ namespace AssetStudio static UnityCNManager() { - var str = File.ReadAllText(KeysFileName); + var str = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, KeysFileName)); Entries = JsonConvert.DeserializeObject>(str); } @@ -24,7 +24,7 @@ namespace AssetStudio Entries.AddRange(entries); var str = JsonConvert.SerializeObject(Entries); - File.WriteAllText(KeysFileName, str); + File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, KeysFileName), str); } public static void SetKey(int index) diff --git a/AssetStudioCLI/Program.cs b/AssetStudioCLI/Program.cs index 5cf517f..917cc47 100644 --- a/AssetStudioCLI/Program.cs +++ b/AssetStudioCLI/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -65,7 +66,6 @@ namespace AssetStudioCLI Logger.Info("Scanning for files..."); var files = o.Input.Attributes.HasFlag(FileAttributes.Directory) ? Directory.GetFiles(o.Input.FullName, "*.*", SearchOption.AllDirectories).OrderBy(x => x.Length).ToArray() : new string[] { o.Input.FullName }; - files = files.Where(x => FileReader.IsReadable(x, game)).ToArray(); Logger.Info($"Found {files.Length} files"); if (o.MapOp.HasFlag(MapOpType.CABMap)) @@ -100,7 +100,13 @@ namespace AssetStudioCLI if (o.MapOp.Equals(MapOpType.None) || o.MapOp.HasFlag(MapOpType.Load)) { var i = 0; - foreach (var file in files) + + var path = Path.GetDirectoryName(Path.GetFullPath(files[0])); + ImportHelper.MergeSplitAssets(path); + var toReadFile = ImportHelper.ProcessingSplitFiles(files.ToList()); + + var fileList = new List(toReadFile); + foreach (var file in fileList) { assetsManager.LoadFiles(file); if (assetsManager.assetsFileList.Count > 0) diff --git a/AssetStudioGUI/AssetStudioGUIForm.cs b/AssetStudioGUI/AssetStudioGUIForm.cs index 9ad095a..b95ebdd 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.cs @@ -2084,7 +2084,6 @@ namespace AssetStudioGUI { Logger.Info("Scanning for files..."); var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray(); - files = files.Where(x => FileReader.IsReadable(x, Studio.Game)).ToArray(); Logger.Info($"Found {files.Length} files"); await Task.Run(() => AssetsHelper.BuildCABMap(files, name, openFolderDialog.Folder, Studio.Game)); } @@ -2137,6 +2136,10 @@ namespace AssetStudioGUI openFolderDialog.Title = "Select Game Folder"; if (openFolderDialog.ShowDialog(this) == DialogResult.OK) { + Logger.Info("Scanning for files..."); + var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray(); + Logger.Info($"Found {files.Length} files"); + var saveFolderDialog = new OpenFolderDialog(); saveFolderDialog.InitialFolder = saveDirectoryBackup; saveFolderDialog.Title = "Select Output Folder"; @@ -2152,10 +2155,6 @@ namespace AssetStudioGUI } } saveDirectoryBackup = saveFolderDialog.Folder; - Logger.Info("Scanning for files..."); - var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray(); - files = files.Where(x => FileReader.IsReadable(x, Studio.Game)).ToArray(); - Logger.Info($"Found {files.Length} files"); await Task.Run(() => AssetsHelper.BuildBoth(files, name, openFolderDialog.Folder, Studio.Game, saveFolderDialog.Folder, exportListType)); } } @@ -2275,7 +2274,6 @@ namespace AssetStudioGUI { Logger.Info("Scanning for files..."); var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray(); - files = files.Where(x => FileReader.IsReadable(x, Studio.Game)).ToArray(); Logger.Info($"Found {files.Length} files"); var saveFolderDialog = new OpenFolderDialog();