Changes:
- temp fix for shader class. - added new entry. - more updates to CLI - fixes #3 - add #4
This commit is contained in:
@@ -78,7 +78,7 @@ namespace AssetStudio
|
|||||||
if (await NeedDownload(version, versionIndex.MappedPath))
|
if (await NeedDownload(version, versionIndex.MappedPath))
|
||||||
{
|
{
|
||||||
Logger.Info("Downloading...");
|
Logger.Info("Downloading...");
|
||||||
var json = await DownloadString(url, TimeSpan.FromMinutes(1));
|
var json = await DownloadString(url, TimeSpan.FromMinutes(2));
|
||||||
if (string.IsNullOrEmpty(json))
|
if (string.IsNullOrEmpty(json))
|
||||||
{
|
{
|
||||||
Logger.Warning("Could not load AI !!");
|
Logger.Warning("Could not load AI !!");
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Newtonsoft.Json.Converters;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
@@ -82,10 +83,11 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static void BuildMap(string[] files, string mapName, string baseFolder, Game game)
|
public static void BuildMap(string[] files, string mapName, string baseFolder, Game game)
|
||||||
{
|
{
|
||||||
Logger.Info($"Processing...");
|
Logger.Info($"Building Map...");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Map.Clear();
|
Map.Clear();
|
||||||
|
Progress.Reset();
|
||||||
var collision = 0;
|
var collision = 0;
|
||||||
BaseFolder = baseFolder;
|
BaseFolder = baseFolder;
|
||||||
assetsManager.Game = game;
|
assetsManager.Game = game;
|
||||||
@@ -118,7 +120,8 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
Map.Add(assetsFile.fileName, entry);
|
Map.Add(assetsFile.fileName, entry);
|
||||||
}
|
}
|
||||||
Logger.Info($"Processed {Path.GetFileName(file)}");
|
Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}");
|
||||||
|
Progress.Report(i + 1, files.Length);
|
||||||
}
|
}
|
||||||
assetsManager.Clear();
|
assetsManager.Clear();
|
||||||
}
|
}
|
||||||
@@ -156,7 +159,9 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static void BuildBoth(string[] files, string mapName, string baseFolder, Game game, string savePath, ExportListType exportListType, ManualResetEvent resetEvent = null, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
public static void BuildBoth(string[] files, string mapName, string baseFolder, Game game, string savePath, ExportListType exportListType, ManualResetEvent resetEvent = null, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
||||||
{
|
{
|
||||||
|
Logger.Info($"Building Both...");
|
||||||
Map.Clear();
|
Map.Clear();
|
||||||
|
Progress.Reset();
|
||||||
var collision = 0;
|
var collision = 0;
|
||||||
BaseFolder = baseFolder;
|
BaseFolder = baseFolder;
|
||||||
assetsManager.Game = game;
|
assetsManager.Game = game;
|
||||||
@@ -203,74 +208,89 @@ namespace AssetStudio
|
|||||||
Source = file,
|
Source = file,
|
||||||
PathID = objectReader.m_PathID,
|
PathID = objectReader.m_PathID,
|
||||||
Type = objectReader.type,
|
Type = objectReader.type,
|
||||||
Container = ""
|
Container = string.Empty,
|
||||||
|
Name = string.Empty
|
||||||
};
|
};
|
||||||
|
|
||||||
var exportable = true;
|
var exportable = true;
|
||||||
switch (objectReader.type)
|
try
|
||||||
{
|
{
|
||||||
case ClassIDType.AssetBundle:
|
switch (objectReader.type)
|
||||||
var assetBundle = new AssetBundle(objectReader);
|
{
|
||||||
foreach (var m_Container in assetBundle.m_Container)
|
case ClassIDType.AssetBundle:
|
||||||
{
|
var assetBundle = new AssetBundle(objectReader);
|
||||||
var preloadIndex = m_Container.Value.preloadIndex;
|
foreach (var m_Container in assetBundle.m_Container)
|
||||||
var preloadSize = m_Container.Value.preloadSize;
|
|
||||||
var preloadEnd = preloadIndex + preloadSize;
|
|
||||||
for (int k = preloadIndex; k < preloadEnd; k++)
|
|
||||||
{
|
{
|
||||||
containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key));
|
var preloadIndex = m_Container.Value.preloadIndex;
|
||||||
|
var preloadSize = m_Container.Value.preloadSize;
|
||||||
|
var preloadEnd = preloadIndex + preloadSize;
|
||||||
|
for (int k = preloadIndex; k < preloadEnd; k++)
|
||||||
|
{
|
||||||
|
containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
obj = null;
|
||||||
obj = null;
|
asset.Name = assetBundle.m_Name;
|
||||||
asset.Name = assetBundle.m_Name;
|
exportable = false;
|
||||||
exportable = false;
|
break;
|
||||||
break;
|
case ClassIDType.GameObject:
|
||||||
case ClassIDType.GameObject:
|
var gameObject = new GameObject(objectReader);
|
||||||
var gameObject = new GameObject(objectReader);
|
obj = gameObject;
|
||||||
obj = gameObject;
|
asset.Name = gameObject.m_Name;
|
||||||
asset.Name = gameObject.m_Name;
|
exportable = false;
|
||||||
exportable = false;
|
break;
|
||||||
break;
|
case ClassIDType.Shader:
|
||||||
case ClassIDType.Shader:
|
asset.Name = objectReader.ReadAlignedString();
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
if (string.IsNullOrEmpty(asset.Name))
|
||||||
if (string.IsNullOrEmpty(asset.Name))
|
{
|
||||||
{
|
var m_parsedForm = new SerializedShader(objectReader);
|
||||||
var m_parsedForm = new SerializedShader(objectReader);
|
asset.Name = m_parsedForm.m_Name;
|
||||||
asset.Name = m_parsedForm.m_Name;
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case ClassIDType.Animator:
|
||||||
case ClassIDType.Animator:
|
var component = new PPtr<Object>(objectReader);
|
||||||
var component = new PPtr<Object>(objectReader);
|
animators.Add((component, asset));
|
||||||
animators.Add((component, asset));
|
break;
|
||||||
break;
|
case ClassIDType.MiHoYoBinData:
|
||||||
case ClassIDType.MiHoYoBinData:
|
var MiHoYoBinData = new MiHoYoBinData(objectReader);
|
||||||
var MiHoYoBinData = new MiHoYoBinData(objectReader);
|
obj = MiHoYoBinData;
|
||||||
obj = MiHoYoBinData;
|
exportable = true;
|
||||||
exportable = true;
|
break;
|
||||||
break;
|
case ClassIDType.IndexObject:
|
||||||
case ClassIDType.IndexObject:
|
var indexObject = new IndexObject(objectReader);
|
||||||
var indexObject = new IndexObject(objectReader);
|
obj = null;
|
||||||
obj = null;
|
foreach (var index in indexObject.AssetMap)
|
||||||
foreach (var index in indexObject.AssetMap)
|
{
|
||||||
{
|
mihoyoBinDataNames.Add((index.Value.Object, index.Key));
|
||||||
mihoyoBinDataNames.Add((index.Value.Object, index.Key));
|
}
|
||||||
}
|
asset.Name = "IndexObject";
|
||||||
asset.Name = "IndexObject";
|
break;
|
||||||
break;
|
case ClassIDType.Font:
|
||||||
case ClassIDType.Font:
|
case ClassIDType.Material:
|
||||||
case ClassIDType.Material:
|
case ClassIDType.Texture:
|
||||||
case ClassIDType.Texture:
|
case ClassIDType.Mesh:
|
||||||
case ClassIDType.Mesh:
|
case ClassIDType.Sprite:
|
||||||
case ClassIDType.Sprite:
|
case ClassIDType.TextAsset:
|
||||||
case ClassIDType.TextAsset:
|
case ClassIDType.Texture2D:
|
||||||
case ClassIDType.Texture2D:
|
case ClassIDType.VideoClip:
|
||||||
case ClassIDType.VideoClip:
|
case ClassIDType.AudioClip:
|
||||||
case ClassIDType.AudioClip:
|
asset.Name = objectReader.ReadAlignedString();
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
exportable = false;
|
||||||
exportable = false;
|
break;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("Unable to load object")
|
||||||
|
.AppendLine($"Assets {assetsFile.fileName}")
|
||||||
|
.AppendLine($"Path {assetsFile.originalPath}")
|
||||||
|
.AppendLine($"Type {objectReader.type}")
|
||||||
|
.AppendLine($"PathID {objectReader.m_PathID}")
|
||||||
|
.Append(e);
|
||||||
|
Logger.Error(sb.ToString());
|
||||||
}
|
}
|
||||||
if (obj != null)
|
if (obj != null)
|
||||||
{
|
{
|
||||||
@@ -319,7 +339,8 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Logger.Info($"Processed {Path.GetFileName(file)}");
|
Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}");
|
||||||
|
Progress.Report(i + 1, files.Length);
|
||||||
}
|
}
|
||||||
assetsManager.Clear();
|
assetsManager.Clear();
|
||||||
}
|
}
|
||||||
@@ -421,6 +442,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static AssetEntry[] BuildAssetMap(string[] files, Game game, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
public static AssetEntry[] BuildAssetMap(string[] files, Game game, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
||||||
{
|
{
|
||||||
|
Progress.Reset();
|
||||||
assetsManager.Game = game;
|
assetsManager.Game = game;
|
||||||
var assets = new List<AssetEntry>();
|
var assets = new List<AssetEntry>();
|
||||||
for (int i = 0; i < files.Length; i++)
|
for (int i = 0; i < files.Length; i++)
|
||||||
@@ -448,70 +470,84 @@ namespace AssetStudio
|
|||||||
};
|
};
|
||||||
|
|
||||||
var exportable = true;
|
var exportable = true;
|
||||||
switch (objectReader.type)
|
try
|
||||||
{
|
{
|
||||||
case ClassIDType.AssetBundle:
|
switch (objectReader.type)
|
||||||
var assetBundle = new AssetBundle(objectReader);
|
{
|
||||||
foreach (var m_Container in assetBundle.m_Container)
|
case ClassIDType.AssetBundle:
|
||||||
{
|
var assetBundle = new AssetBundle(objectReader);
|
||||||
var preloadIndex = m_Container.Value.preloadIndex;
|
foreach (var m_Container in assetBundle.m_Container)
|
||||||
var preloadSize = m_Container.Value.preloadSize;
|
|
||||||
var preloadEnd = preloadIndex + preloadSize;
|
|
||||||
for (int k = preloadIndex; k < preloadEnd; k++)
|
|
||||||
{
|
{
|
||||||
containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key));
|
var preloadIndex = m_Container.Value.preloadIndex;
|
||||||
|
var preloadSize = m_Container.Value.preloadSize;
|
||||||
|
var preloadEnd = preloadIndex + preloadSize;
|
||||||
|
for (int k = preloadIndex; k < preloadEnd; k++)
|
||||||
|
{
|
||||||
|
containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
obj = null;
|
||||||
obj = null;
|
asset.Name = assetBundle.m_Name;
|
||||||
asset.Name = assetBundle.m_Name;
|
exportable = false;
|
||||||
exportable = false;
|
break;
|
||||||
break;
|
case ClassIDType.GameObject:
|
||||||
case ClassIDType.GameObject:
|
var gameObject = new GameObject(objectReader);
|
||||||
var gameObject = new GameObject(objectReader);
|
obj = gameObject;
|
||||||
obj = gameObject;
|
asset.Name = gameObject.m_Name;
|
||||||
asset.Name = gameObject.m_Name;
|
exportable = false;
|
||||||
exportable = false;
|
break;
|
||||||
break;
|
case ClassIDType.Shader:
|
||||||
case ClassIDType.Shader:
|
asset.Name = objectReader.ReadAlignedString();
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
if (string.IsNullOrEmpty(asset.Name))
|
||||||
if (string.IsNullOrEmpty(asset.Name))
|
{
|
||||||
{
|
var m_parsedForm = new SerializedShader(objectReader);
|
||||||
var m_parsedForm = new SerializedShader(objectReader);
|
asset.Name = m_parsedForm.m_Name;
|
||||||
asset.Name = m_parsedForm.m_Name;
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case ClassIDType.Animator:
|
||||||
case ClassIDType.Animator:
|
var component = new PPtr<Object>(objectReader);
|
||||||
var component = new PPtr<Object>(objectReader);
|
animators.Add((component, asset));
|
||||||
animators.Add((component, asset));
|
break;
|
||||||
break;
|
case ClassIDType.MiHoYoBinData:
|
||||||
case ClassIDType.MiHoYoBinData:
|
var MiHoYoBinData = new MiHoYoBinData(objectReader);
|
||||||
var MiHoYoBinData = new MiHoYoBinData(objectReader);
|
obj = MiHoYoBinData;
|
||||||
obj = MiHoYoBinData;
|
exportable = true;
|
||||||
exportable = true;
|
break;
|
||||||
break;
|
case ClassIDType.IndexObject:
|
||||||
case ClassIDType.IndexObject:
|
var indexObject = new IndexObject(objectReader);
|
||||||
var indexObject = new IndexObject(objectReader);
|
obj = null;
|
||||||
obj = null;
|
foreach (var index in indexObject.AssetMap)
|
||||||
foreach (var index in indexObject.AssetMap)
|
{
|
||||||
{
|
mihoyoBinDataNames.Add((index.Value.Object, index.Key));
|
||||||
mihoyoBinDataNames.Add((index.Value.Object, index.Key));
|
}
|
||||||
}
|
asset.Name = "IndexObject";
|
||||||
asset.Name = "IndexObject";
|
break;
|
||||||
break;
|
case ClassIDType.Font:
|
||||||
case ClassIDType.Font:
|
case ClassIDType.Material:
|
||||||
case ClassIDType.Material:
|
case ClassIDType.Texture:
|
||||||
case ClassIDType.Texture:
|
case ClassIDType.Mesh:
|
||||||
case ClassIDType.Mesh:
|
case ClassIDType.Sprite:
|
||||||
case ClassIDType.Sprite:
|
case ClassIDType.TextAsset:
|
||||||
case ClassIDType.TextAsset:
|
case ClassIDType.Texture2D:
|
||||||
case ClassIDType.Texture2D:
|
case ClassIDType.VideoClip:
|
||||||
case ClassIDType.VideoClip:
|
case ClassIDType.AudioClip:
|
||||||
case ClassIDType.AudioClip:
|
asset.Name = objectReader.ReadAlignedString();
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
exportable = false;
|
||||||
exportable = false;
|
break;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("Unable to load object")
|
||||||
|
.AppendLine($"Assets {assetsFile.fileName}")
|
||||||
|
.AppendLine($"Path {assetsFile.originalPath}")
|
||||||
|
.AppendLine($"Type {objectReader.type}")
|
||||||
|
.AppendLine($"PathID {objectReader.m_PathID}")
|
||||||
|
.Append(e);
|
||||||
|
Logger.Error(sb.ToString());
|
||||||
}
|
}
|
||||||
if (obj != null)
|
if (obj != null)
|
||||||
{
|
{
|
||||||
@@ -560,7 +596,8 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Logger.Info($"Processed {Path.GetFileName(file)}");
|
Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}");
|
||||||
|
Progress.Report(i + 1, files.Length);
|
||||||
}
|
}
|
||||||
assetsManager.Clear();
|
assetsManager.Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,11 +107,6 @@ namespace AssetStudio
|
|||||||
Logger.Info("Loading files has been aborted !!");
|
Logger.Info("Loading files has been aborted !!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!SkipProcess && !tokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
ReadAssets();
|
|
||||||
ProcessAssets();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
importFiles.Clear();
|
importFiles.Clear();
|
||||||
@@ -120,12 +115,12 @@ namespace AssetStudio
|
|||||||
assetsFileListHash.Clear();
|
assetsFileListHash.Clear();
|
||||||
AssetsHelper.ClearOffsets();
|
AssetsHelper.ClearOffsets();
|
||||||
|
|
||||||
//if (!SkipProcess && !tokenSource.IsCancellationRequested)
|
if (!SkipProcess && !tokenSource.IsCancellationRequested)
|
||||||
//{
|
{
|
||||||
// ReadAssets();
|
ReadAssets();
|
||||||
// ProcessAssets();
|
ProcessAssets();
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void LoadFile(string fullName)
|
private void LoadFile(string fullName)
|
||||||
{
|
{
|
||||||
@@ -177,36 +172,36 @@ namespace AssetStudio
|
|||||||
assetsFileList.Add(assetsFile);
|
assetsFileList.Add(assetsFile);
|
||||||
assetsFileListHash.Add(assetsFile.fileName);
|
assetsFileListHash.Add(assetsFile.fileName);
|
||||||
|
|
||||||
foreach (var sharedFile in assetsFile.m_Externals)
|
foreach (var sharedFile in assetsFile.m_Externals)
|
||||||
{
|
{
|
||||||
var sharedFileName = sharedFile.fileName;
|
var sharedFileName = sharedFile.fileName;
|
||||||
|
|
||||||
if (!importFilesHash.Contains(sharedFileName))
|
if (!importFilesHash.Contains(sharedFileName))
|
||||||
|
{
|
||||||
|
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
|
||||||
|
if (!noexistFiles.Contains(sharedFilePath))
|
||||||
{
|
{
|
||||||
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
|
if (!File.Exists(sharedFilePath))
|
||||||
if (!noexistFiles.Contains(sharedFilePath))
|
|
||||||
{
|
{
|
||||||
if (!File.Exists(sharedFilePath))
|
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
|
||||||
|
if (findFiles.Length > 0)
|
||||||
{
|
{
|
||||||
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
|
sharedFilePath = findFiles[0];
|
||||||
if (findFiles.Length > 0)
|
|
||||||
{
|
|
||||||
sharedFilePath = findFiles[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (File.Exists(sharedFilePath))
|
|
||||||
{
|
|
||||||
importFiles.Add(sharedFilePath);
|
|
||||||
importFilesHash.Add(sharedFileName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
noexistFiles.Add(sharedFilePath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (File.Exists(sharedFilePath))
|
||||||
|
{
|
||||||
|
importFiles.Add(sharedFilePath);
|
||||||
|
importFilesHash.Add(sharedFileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
noexistFiles.Add(sharedFilePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Error($"Error while reading assets file {reader.FullPath}", e);
|
Logger.Error($"Error while reading assets file {reader.FullPath}", e);
|
||||||
@@ -237,37 +232,37 @@ namespace AssetStudio
|
|||||||
assetsFileList.Add(assetsFile);
|
assetsFileList.Add(assetsFile);
|
||||||
assetsFileListHash.Add(assetsFile.fileName);
|
assetsFileListHash.Add(assetsFile.fileName);
|
||||||
|
|
||||||
//if (ResolveDependencies)
|
if (ResolveDependencies)
|
||||||
//{
|
{
|
||||||
// foreach (var sharedFile in assetsFile.m_Externals)
|
foreach (var sharedFile in assetsFile.m_Externals)
|
||||||
// {
|
{
|
||||||
// var sharedFileName = sharedFile.fileName;
|
var sharedFileName = sharedFile.fileName;
|
||||||
//
|
|
||||||
// if (!importFilesHash.Contains(sharedFileName))
|
if (!importFilesHash.Contains(sharedFileName))
|
||||||
// {
|
{
|
||||||
// var sharedFilePath = Path.Combine(Path.GetDirectoryName(originalPath), sharedFileName);
|
var sharedFilePath = Path.Combine(Path.GetDirectoryName(originalPath), sharedFileName);
|
||||||
// if (!noexistFiles.Contains(sharedFilePath))
|
if (!noexistFiles.Contains(sharedFilePath))
|
||||||
// {
|
{
|
||||||
// if (AssetsHelper.TryAdd(sharedFileName, out var path))
|
if (AssetsHelper.TryAdd(sharedFileName, out var path))
|
||||||
// {
|
{
|
||||||
// sharedFilePath = path;
|
sharedFilePath = path;
|
||||||
// }
|
}
|
||||||
// if (File.Exists(sharedFilePath))
|
if (File.Exists(sharedFilePath))
|
||||||
// {
|
{
|
||||||
// if (!importFiles.Contains(sharedFilePath))
|
if (!importFiles.Contains(sharedFilePath))
|
||||||
// {
|
{
|
||||||
// importFiles.Add(sharedFilePath);
|
importFiles.Add(sharedFilePath);
|
||||||
// }
|
}
|
||||||
// importFilesHash.Add(sharedFileName);
|
importFilesHash.Add(sharedFileName);
|
||||||
// }
|
}
|
||||||
// else
|
else
|
||||||
// {
|
{
|
||||||
// noexistFiles.Add(sharedFilePath);
|
noexistFiles.Add(sharedFilePath);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -279,9 +274,12 @@ namespace AssetStudio
|
|||||||
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
|
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadBundleFile(FileReader reader, string originalPath = null, long originalOffset = 0)
|
private void LoadBundleFile(FileReader reader, string originalPath = null, long originalOffset = 0, bool log = true)
|
||||||
{
|
{
|
||||||
Logger.Info("Loading " + reader.FullPath);
|
if (log)
|
||||||
|
{
|
||||||
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var bundleFile = new BundleFile(reader, Game);
|
var bundleFile = new BundleFile(reader, Game);
|
||||||
@@ -459,15 +457,18 @@ namespace AssetStudio
|
|||||||
Logger.Info("Loading " + reader.FullPath);
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var stream = new BlockStream(reader.BaseStream, 0);
|
using var stream = new SubStream(reader.BaseStream, 0);
|
||||||
if (AssetsHelper.TryGet(reader.FullPath, out var offsets))
|
if (AssetsHelper.TryGet(reader.FullPath, out var offsets))
|
||||||
{
|
{
|
||||||
foreach (var offset in offsets)
|
foreach (var offset in offsets)
|
||||||
{
|
{
|
||||||
|
var name = offset.ToString("X8");
|
||||||
|
Logger.Info($"Loading Block {name}");
|
||||||
|
|
||||||
stream.Offset = offset;
|
stream.Offset = offset;
|
||||||
var dummyPath = Path.Combine(reader.FileName, offset.ToString("X8"));
|
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), name);
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
LoadBundleFile(subReader, reader.FullPath, offset);
|
LoadBundleFile(subReader, reader.FullPath, offset, false);
|
||||||
}
|
}
|
||||||
AssetsHelper.Remove(reader.FullPath);
|
AssetsHelper.Remove(reader.FullPath);
|
||||||
}
|
}
|
||||||
@@ -475,12 +476,15 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.RelativePosition;
|
var name = stream.AbsolutePosition.ToString("X8");
|
||||||
var dummyPath = Path.Combine(reader.FileName, stream.RelativePosition.ToString("X8"));
|
Logger.Info($"Loading Block {name}");
|
||||||
|
|
||||||
|
stream.Offset = stream.AbsolutePosition;
|
||||||
|
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), name);
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
LoadBundleFile(subReader, reader.FullPath, stream.RelativePosition);
|
LoadBundleFile(subReader, reader.FullPath, stream.AbsolutePosition, false);
|
||||||
} while (stream.Remaining > 0);
|
} while (stream.Remaining > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -501,16 +505,19 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
foreach (var offset in offsets)
|
foreach (var offset in offsets)
|
||||||
{
|
{
|
||||||
|
var name = offset.ToString("X8");
|
||||||
|
Logger.Info($"Loading Block {name}");
|
||||||
|
|
||||||
stream.Offset = offset;
|
stream.Offset = offset;
|
||||||
var dummyPath = Path.Combine(reader.FileName, offset.ToString("X8"));
|
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), name);
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
switch (subReader.FileType)
|
switch (subReader.FileType)
|
||||||
{
|
{
|
||||||
case FileType.BundleFile:
|
case FileType.BundleFile:
|
||||||
LoadBundleFile(subReader, reader.FullPath, offset);
|
LoadBundleFile(subReader, reader.FullPath, offset, false);
|
||||||
break;
|
break;
|
||||||
case FileType.Mhy0File:
|
case FileType.Mhy0File:
|
||||||
LoadMhy0File(subReader, reader.FullPath, offset);
|
LoadMhy0File(subReader, reader.FullPath, offset, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,18 +527,22 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.RelativePosition;
|
var name = stream.Position.ToString("X8");
|
||||||
var dummyPath = Path.Combine(reader.FileName, stream.RelativePosition.ToString("X8"));
|
Logger.Info($"Loading Block {name}");
|
||||||
|
|
||||||
|
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), name);
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
switch (subReader.FileType)
|
switch (subReader.FileType)
|
||||||
{
|
{
|
||||||
case FileType.BundleFile:
|
case FileType.BundleFile:
|
||||||
LoadBundleFile(subReader, reader.FullPath, stream.RelativePosition);
|
LoadBundleFile(subReader, reader.FullPath, stream.Position, false);
|
||||||
break;
|
break;
|
||||||
case FileType.Mhy0File:
|
case FileType.Mhy0File:
|
||||||
LoadMhy0File(subReader, reader.FullPath, stream.RelativePosition);
|
LoadMhy0File(subReader, reader.FullPath, stream.Position, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream.Offset += stream.Position;
|
||||||
} while (stream.Remaining > 0);
|
} while (stream.Remaining > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -548,9 +559,12 @@ namespace AssetStudio
|
|||||||
reader.Dispose();
|
reader.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void LoadMhy0File(FileReader reader, string originalPath = null, long originalOffset = 0)
|
private void LoadMhy0File(FileReader reader, string originalPath = null, long originalOffset = 0, bool log = true)
|
||||||
{
|
{
|
||||||
Logger.Info("Loading " + reader.FullPath);
|
if (log)
|
||||||
|
{
|
||||||
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var mhy0File = new Mhy0File(reader, reader.FullPath, (Mhy0)Game);
|
var mhy0File = new Mhy0File(reader, reader.FullPath, (Mhy0)Game);
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
public class BlockStream : Stream
|
|
||||||
{
|
|
||||||
private readonly Stream _baseStream;
|
|
||||||
private readonly long _origin;
|
|
||||||
private long _startPosition;
|
|
||||||
|
|
||||||
public override bool CanRead => _baseStream.CanRead;
|
|
||||||
public override bool CanSeek => _baseStream.CanSeek;
|
|
||||||
public override bool CanWrite => false;
|
|
||||||
|
|
||||||
public override long Length => _baseStream.Length - _startPosition;
|
|
||||||
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get => _baseStream.Position - _startPosition;
|
|
||||||
set => Seek(value, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Offset
|
|
||||||
{
|
|
||||||
get => _startPosition;
|
|
||||||
set => _startPosition = value + _origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long RelativePosition => _baseStream.Position - _origin;
|
|
||||||
public long Remaining => Length - Position;
|
|
||||||
|
|
||||||
public BlockStream(Stream stream, long offset)
|
|
||||||
{
|
|
||||||
_baseStream = stream;
|
|
||||||
_origin = offset;
|
|
||||||
_startPosition = offset;
|
|
||||||
Seek(0, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
var target = origin switch
|
|
||||||
{
|
|
||||||
SeekOrigin.Begin => offset + _startPosition,
|
|
||||||
SeekOrigin.Current => offset + _baseStream.Position,
|
|
||||||
SeekOrigin.End => offset + Length,
|
|
||||||
_ => throw new NotSupportedException()
|
|
||||||
};
|
|
||||||
|
|
||||||
_baseStream.Seek(target, SeekOrigin.Begin);
|
|
||||||
return Position;
|
|
||||||
}
|
|
||||||
public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count);
|
|
||||||
public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();
|
|
||||||
public override void SetLength(long value) => throw new NotImplementedException();
|
|
||||||
public override void Flush() => throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -112,7 +112,7 @@ namespace AssetStudio
|
|||||||
switch (header.signature)
|
switch (header.signature)
|
||||||
{
|
{
|
||||||
case "UnityFS":
|
case "UnityFS":
|
||||||
if (Game.Type.IsBH3())
|
if (Game.Type.IsBH3Group())
|
||||||
{
|
{
|
||||||
var version = reader.ReadUInt32();
|
var version = reader.ReadUInt32();
|
||||||
if (version > 11)
|
if (version > 11)
|
||||||
@@ -277,7 +277,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
private void ReadHeader(FileReader reader)
|
private void ReadHeader(FileReader reader)
|
||||||
{
|
{
|
||||||
if (Game.Type.IsBH3() && XORShift128.Init)
|
if ((Game.Type.IsBH3Group()) && XORShift128.Init)
|
||||||
{
|
{
|
||||||
m_Header.flags = (ArchiveFlags)reader.ReadUInt32();
|
m_Header.flags = (ArchiveFlags)reader.ReadUInt32();
|
||||||
m_Header.size = reader.ReadInt64();
|
m_Header.size = reader.ReadInt64();
|
||||||
|
|||||||
@@ -672,7 +672,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
m_ConstantClip = new ConstantClip(reader);
|
m_ConstantClip = new ConstantClip(reader);
|
||||||
}
|
}
|
||||||
if (reader.Game.Type.IsGIGroup() || reader.Game.Type.IsBH3() || reader.Game.Type.IsZZZCB1())
|
if (reader.Game.Type.IsGIGroup() || reader.Game.Type.IsBH3Group() || reader.Game.Type.IsZZZCB1())
|
||||||
{
|
{
|
||||||
m_ACLClip.Read(reader);
|
m_ACLClip.Read(reader);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,26 +41,6 @@ namespace AssetStudio
|
|||||||
var name = m_External.fileName;
|
var name = m_External.fileName;
|
||||||
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
||||||
{
|
{
|
||||||
if (assetsManager.ResolveDependencies && !assetsManager.importFilesHash.Contains(name))
|
|
||||||
{
|
|
||||||
var sharedFilePath = Path.Combine(Path.GetDirectoryName(assetsFile.originalPath), name);
|
|
||||||
if (!assetsManager.noexistFiles.Contains(sharedFilePath))
|
|
||||||
{
|
|
||||||
if (TryAdd(name, out var path))
|
|
||||||
{
|
|
||||||
sharedFilePath = path;
|
|
||||||
}
|
|
||||||
if (File.Exists(sharedFilePath))
|
|
||||||
{
|
|
||||||
assetsManager.importFilesHash.Add(name);
|
|
||||||
assetsManager.LoadFiles(sharedFilePath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assetsManager.noexistFiles.Add(sharedFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||||
assetsFileIndexCache.Add(name, index);
|
assetsFileIndexCache.Add(name, index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
var m_DynamicOccludee = reader.ReadByte();
|
var m_DynamicOccludee = reader.ReadByte();
|
||||||
}
|
}
|
||||||
if (reader.Game.Type.IsBH3())
|
if (reader.Game.Type.IsBH3Group())
|
||||||
{
|
{
|
||||||
var m_AllowHalfResolution = reader.ReadByte();
|
var m_AllowHalfResolution = reader.ReadByte();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -585,7 +585,7 @@ namespace AssetStudio
|
|||||||
m_BlobIndex = reader.ReadUInt32();
|
m_BlobIndex = reader.ReadUInt32();
|
||||||
m_Channels = new ParserBindChannels(reader);
|
m_Channels = new ParserBindChannels(reader);
|
||||||
|
|
||||||
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
|
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2) || reader.Match("E99740711222CD922E9A6F92FF1EB07A") || reader.Match("450A058C218DAF000647948F2F59DA6D")) //2019 ~2021.1
|
||||||
{
|
{
|
||||||
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
@@ -605,17 +605,6 @@ namespace AssetStudio
|
|||||||
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
|
|
||||||
if (reader.Game.Type.IsGI() && (m_GpuProgramType == ShaderGpuProgramType.Unknown || !Enum.IsDefined(typeof(ShaderGpuProgramType), m_GpuProgramType)))
|
|
||||||
{
|
|
||||||
reader.Position -= 4;
|
|
||||||
var m_LocalKeywordIndices = reader.ReadUInt16Array();
|
|
||||||
reader.AlignStream();
|
|
||||||
|
|
||||||
m_ShaderHardwareTier = reader.ReadSByte();
|
|
||||||
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
|
||||||
reader.AlignStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((version[0] == 2020 && version[1] > 3) ||
|
if ((version[0] == 2020 && version[1] > 3) ||
|
||||||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||||
(version[0] > 2021) ||
|
(version[0] > 2021) ||
|
||||||
@@ -697,6 +686,16 @@ namespace AssetStudio
|
|||||||
var m_ShaderRequirements = reader.ReadInt32();
|
var m_ShaderRequirements = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reader.Match("E99740711222CD922E9A6F92FF1EB07A"))
|
||||||
|
{
|
||||||
|
int numInstancedStructuredBuffers = reader.ReadInt32();
|
||||||
|
var m_InstancedStructuredBuffers = new ConstantBuffer[numInstancedStructuredBuffers];
|
||||||
|
for (int i = 0; i < numInstancedStructuredBuffers; i++)
|
||||||
|
{
|
||||||
|
m_InstancedStructuredBuffers[i] = new ConstantBuffer(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public static class BlkUtils
|
public static class BlkUtils
|
||||||
{
|
{
|
||||||
private const int DataPos = 0x2A;
|
private const int DataOffset = 0x2A;
|
||||||
private const int KeySize = 0x1000;
|
private const int KeySize = 0x1000;
|
||||||
private const int SeedBlockSize = 0x800;
|
private const int SeedBlockSize = 0x800;
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ namespace AssetStudio
|
|||||||
BinaryPrimitives.WriteUInt64LittleEndian(xorpad.AsSpan(i, 8), mt64.Int64());
|
BinaryPrimitives.WriteUInt64LittleEndian(xorpad.AsSpan(i, 8), mt64.Int64());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new XORStream(reader.BaseStream, DataPos, xorpad);
|
return new XORStream(reader.BaseStream, DataOffset, xorpad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,6 +126,14 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsReadable(string path, Game game)
|
||||||
|
{
|
||||||
|
var reader = new FileReader(path);
|
||||||
|
reader = reader.PreProcessing(game);
|
||||||
|
reader.Dispose();
|
||||||
|
return reader.FileType != FileType.ResourceFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FileReaderExtensions
|
public static class FileReaderExtensions
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace AssetStudio
|
|||||||
Games.Add(index++, new Blk(GameType.GI_CB3, GI_CBXExpansionKey, initVector: GI_CBXInitVector, initSeed: GI_CBXInitSeed));
|
Games.Add(index++, new Blk(GameType.GI_CB3, GI_CBXExpansionKey, initVector: GI_CBXInitVector, initSeed: GI_CBXInitSeed));
|
||||||
Games.Add(index++, new Mhy0(GameType.GI_CB3Pre, GI_CBXMhy0ShiftRow, GI_CBXMhy0Key, GI_CBXMhy0Mul, GI_CBXExpansionKey, GI_CBXSBox, GI_CBXInitVector, GI_CBXInitSeed));
|
Games.Add(index++, new Mhy0(GameType.GI_CB3Pre, GI_CBXMhy0ShiftRow, GI_CBXMhy0Key, GI_CBXMhy0Mul, GI_CBXExpansionKey, GI_CBXSBox, GI_CBXInitVector, GI_CBXInitSeed));
|
||||||
Games.Add(index++, new Mr0k(GameType.BH3, BH3ExpansionKey, BH3SBox, BH3InitVector, BH3BlockKey));
|
Games.Add(index++, new Mr0k(GameType.BH3, BH3ExpansionKey, BH3SBox, BH3InitVector, BH3BlockKey));
|
||||||
|
Games.Add(index++, new Mr0k(GameType.BH3_Pre, PackExpansionKey, blockKey: PackBlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.SR_CB2, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
Games.Add(index++, new Mr0k(GameType.SR_CB2, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.SR_CB3, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
Games.Add(index++, new Mr0k(GameType.SR_CB3, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.ZZZ_CB1, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
Games.Add(index++, new Mr0k(GameType.ZZZ_CB1, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
||||||
@@ -120,6 +121,7 @@ namespace AssetStudio
|
|||||||
GI_CB3,
|
GI_CB3,
|
||||||
GI_CB3Pre,
|
GI_CB3Pre,
|
||||||
BH3,
|
BH3,
|
||||||
|
BH3_Pre,
|
||||||
ZZZ_CB1,
|
ZZZ_CB1,
|
||||||
SR_CB2,
|
SR_CB2,
|
||||||
SR_CB3,
|
SR_CB3,
|
||||||
@@ -143,6 +145,7 @@ namespace AssetStudio
|
|||||||
public static bool IsGICB3(this GameType type) => type == GameType.GI_CB3;
|
public static bool IsGICB3(this GameType type) => type == GameType.GI_CB3;
|
||||||
public static bool IsGICB3Pre(this GameType type) => type == GameType.GI_CB3Pre;
|
public static bool IsGICB3Pre(this GameType type) => type == GameType.GI_CB3Pre;
|
||||||
public static bool IsBH3(this GameType type) => type == GameType.BH3;
|
public static bool IsBH3(this GameType type) => type == GameType.BH3;
|
||||||
|
public static bool IsBH3Pre(this GameType type) => type == GameType.BH3_Pre;
|
||||||
public static bool IsZZZCB1(this GameType type) => type == GameType.ZZZ_CB1;
|
public static bool IsZZZCB1(this GameType type) => type == GameType.ZZZ_CB1;
|
||||||
public static bool IsSRCB2(this GameType type) => type == GameType.SR_CB2;
|
public static bool IsSRCB2(this GameType type) => type == GameType.SR_CB2;
|
||||||
public static bool IsSRCB3(this GameType type) => type == GameType.SR_CB3;
|
public static bool IsSRCB3(this GameType type) => type == GameType.SR_CB3;
|
||||||
@@ -161,6 +164,12 @@ namespace AssetStudio
|
|||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static bool IsBH3Group(this GameType type) => type switch
|
||||||
|
{
|
||||||
|
GameType.BH3 or GameType.BH3_Pre => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
public static bool IsSRGroup(this GameType type) => type switch
|
public static bool IsSRGroup(this GameType type) => type switch
|
||||||
{
|
{
|
||||||
GameType.SR_CB2 or GameType.SR_CB3 => true,
|
GameType.SR_CB2 or GameType.SR_CB3 => true,
|
||||||
@@ -169,7 +178,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static bool IsBlockFile(this GameType type) => type switch
|
public static bool IsBlockFile(this GameType type) => type switch
|
||||||
{
|
{
|
||||||
GameType.BH3 or GameType.SR_CB3 or GameType.GI_Pack or GameType.TOT => true,
|
GameType.BH3 or GameType.BH3_Pre or GameType.SR_CB3 or GameType.GI_Pack or GameType.TOT => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ namespace AssetStudio
|
|||||||
var idx = data.Search("UnityFS");
|
var idx = data.Search("UnityFS");
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
{
|
{
|
||||||
stream = new BlockStream(stream, idx);
|
stream = new SubStream(stream, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FileReader(reader.FullPath, stream);
|
return new FileReader(reader.FullPath, stream);
|
||||||
@@ -295,11 +295,11 @@ namespace AssetStudio
|
|||||||
var idx2 = data[(idx + 1)..].Search("UnityFS");
|
var idx2 = data[(idx + 1)..].Search("UnityFS");
|
||||||
if (idx2 != -1)
|
if (idx2 != -1)
|
||||||
{
|
{
|
||||||
stream = new BlockStream(stream, idx + idx2 + 1);
|
stream = new SubStream(stream, idx + idx2 + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream = new BlockStream(stream, idx);
|
stream = new SubStream(stream, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +371,7 @@ namespace AssetStudio
|
|||||||
reader.Position = 0;
|
reader.Position = 0;
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
var stream = new BlockStream(reader.BaseStream, idx);
|
var stream = new SubStream(reader.BaseStream, idx);
|
||||||
return new FileReader(reader.FullPath, stream);
|
return new FileReader(reader.FullPath, stream);
|
||||||
}
|
}
|
||||||
public static FileReader ParseHelixWaltz2(FileReader reader)
|
public static FileReader ParseHelixWaltz2(FileReader reader)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace AssetStudio
|
|||||||
public int[] version => assetsFile.version;
|
public int[] version => assetsFile.version;
|
||||||
public BuildType buildType => assetsFile.buildType;
|
public BuildType buildType => assetsFile.buildType;
|
||||||
|
|
||||||
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo, Game game) : base(reader.BaseStream, reader.Endian)
|
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo, Game game) : base(new SubStream(reader.BaseStream, objectInfo.byteStart, objectInfo.byteSize), reader.Endian)
|
||||||
{
|
{
|
||||||
this.assetsFile = assetsFile;
|
this.assetsFile = assetsFile;
|
||||||
Game = game;
|
Game = game;
|
||||||
@@ -41,9 +41,11 @@ namespace AssetStudio
|
|||||||
m_Version = assetsFile.header.m_Version;
|
m_Version = assetsFile.header.m_Version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Match(string hash) => Convert.ToHexString(serializedType.m_OldTypeHash) == hash;
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
Position = byteStart;
|
Position = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
103
AssetStudio/SubStream.cs
Normal file
103
AssetStudio/SubStream.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class SubStream : Stream
|
||||||
|
{
|
||||||
|
private readonly Stream _baseStream;
|
||||||
|
private long _offset;
|
||||||
|
private long _size;
|
||||||
|
|
||||||
|
public override bool CanRead => _baseStream.CanRead;
|
||||||
|
public override bool CanSeek => _baseStream.CanSeek;
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
|
public long Size
|
||||||
|
{
|
||||||
|
get => _size;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value > _baseStream.Length || value + _offset > _baseStream.Length)
|
||||||
|
{
|
||||||
|
throw new IOException($"{nameof(Size)} is out of stream bound");
|
||||||
|
}
|
||||||
|
_size = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Offset
|
||||||
|
{
|
||||||
|
get => _offset;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value > _baseStream.Length)
|
||||||
|
{
|
||||||
|
throw new IOException($"{nameof(Offset)} is out of stream bound");
|
||||||
|
}
|
||||||
|
if (value + _size > _baseStream.Length)
|
||||||
|
{
|
||||||
|
_size = _baseStream.Length - value;
|
||||||
|
}
|
||||||
|
_offset = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public long AbsolutePosition => _baseStream.Position;
|
||||||
|
public long Remaining => Length - Position;
|
||||||
|
|
||||||
|
public override long Length => Size;
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get => _baseStream.Position - _offset;
|
||||||
|
set => Seek(value, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubStream(Stream stream, long offset)
|
||||||
|
{
|
||||||
|
_baseStream = stream;
|
||||||
|
|
||||||
|
Offset = offset;
|
||||||
|
Size = _baseStream.Length - _offset;
|
||||||
|
Seek(0, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubStream(Stream stream, long offset, long size)
|
||||||
|
{
|
||||||
|
_baseStream = stream;
|
||||||
|
|
||||||
|
Offset = offset;
|
||||||
|
Size = size;
|
||||||
|
Seek(0, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
if (offset > _size)
|
||||||
|
{
|
||||||
|
throw new IOException("Unable to seek beyond stream bound");
|
||||||
|
}
|
||||||
|
|
||||||
|
var target = origin switch
|
||||||
|
{
|
||||||
|
SeekOrigin.Begin => offset + _offset,
|
||||||
|
SeekOrigin.Current => offset + Position,
|
||||||
|
SeekOrigin.End => offset + _size,
|
||||||
|
_ => throw new NotSupportedException()
|
||||||
|
};
|
||||||
|
|
||||||
|
_baseStream.Seek(target, SeekOrigin.Begin);
|
||||||
|
return Position;
|
||||||
|
}
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (offset > _size || Position + count > _size)
|
||||||
|
{
|
||||||
|
throw new IOException("Unable to read beyond stream bound");
|
||||||
|
}
|
||||||
|
return _baseStream.Read(buffer, offset, count);
|
||||||
|
}
|
||||||
|
public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();
|
||||||
|
public override void SetLength(long value) => throw new NotImplementedException();
|
||||||
|
public override void Flush() => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,18 +2,20 @@
|
|||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class XORStream : BlockStream
|
public class XORStream : SubStream
|
||||||
{
|
{
|
||||||
private readonly byte[] _xorpad;
|
private readonly byte[] _xorpad;
|
||||||
|
private readonly long _offset;
|
||||||
|
|
||||||
public XORStream(Stream stream, long pos, byte[] xorpad) : base(stream, pos)
|
public XORStream(Stream stream, long offset, byte[] xorpad) : base(stream, offset)
|
||||||
{
|
{
|
||||||
_xorpad = xorpad;
|
_xorpad = xorpad;
|
||||||
|
_offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
var pos = RelativePosition;
|
var pos = AbsolutePosition - _offset;
|
||||||
var read = base.Read(buffer, offset, count);
|
var read = base.Read(buffer, offset, count);
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -79,8 +79,9 @@ namespace AssetStudioCLI
|
|||||||
assemblyLoader.Load(o.DummyDllFolder.FullName);
|
assemblyLoader.Load(o.DummyDllFolder.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info("Scanning for files");
|
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 };
|
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(string.Format("Found {0} file(s)", files.Length));
|
Logger.Info(string.Format("Found {0} file(s)", files.Length));
|
||||||
|
|
||||||
if (o.MapOp.HasFlag(MapOpType.Build))
|
if (o.MapOp.HasFlag(MapOpType.Build))
|
||||||
@@ -107,6 +108,12 @@ namespace AssetStudioCLI
|
|||||||
AssetsHelper.ExportAssetsMap(assets, o.MapName, o.Output.FullName, o.MapType, resetEvent);
|
AssetsHelper.ExportAssetsMap(assets, o.MapName, o.Output.FullName, o.MapType, resetEvent);
|
||||||
resetEvent.WaitOne();
|
resetEvent.WaitOne();
|
||||||
}
|
}
|
||||||
|
if (o.MapOp.HasFlag(MapOpType.Both))
|
||||||
|
{
|
||||||
|
var resetEvent = new ManualResetEvent(false);
|
||||||
|
AssetsHelper.BuildBoth(files, o.MapName, o.Input.FullName, game, o.Output.FullName, o.MapType, resetEvent, o.NameFilter, o.ContainerFilter);
|
||||||
|
resetEvent.WaitOne();
|
||||||
|
}
|
||||||
if (o.MapOp.Equals(MapOpType.None) || o.MapOp.HasFlag(MapOpType.Load))
|
if (o.MapOp.Equals(MapOpType.None) || o.MapOp.HasFlag(MapOpType.Load))
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ namespace AssetStudioCLI
|
|||||||
None,
|
None,
|
||||||
Load,
|
Load,
|
||||||
Build,
|
Build,
|
||||||
Both,
|
List = 4,
|
||||||
List,
|
Both = 8,
|
||||||
All = Build | Load | List
|
All = Both | Load,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AssetGroupOption
|
public enum AssetGroupOption
|
||||||
@@ -127,8 +127,8 @@ namespace AssetStudioCLI
|
|||||||
using var stream = BlkUtils.Decrypt(reader, (Blk)Game);
|
using var stream = BlkUtils.Decrypt(reader, (Blk)Game);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.RelativePosition;
|
stream.Offset = stream.AbsolutePosition;
|
||||||
var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8"));
|
var dummyPath = Path.Combine(reader.FullPath, stream.AbsolutePosition.ToString("X8"));
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
||||||
switch (subReader.FileType)
|
switch (subReader.FileType)
|
||||||
@@ -153,12 +153,12 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
int total = 0;
|
int total = 0;
|
||||||
Logger.Info($"Decompressing {reader.FileName} ...");
|
Logger.Info($"Decompressing {reader.FileName} ...");
|
||||||
using var stream = new BlockStream(reader.BaseStream, 0);
|
using var stream = new SubStream(reader.BaseStream, 0);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.RelativePosition;
|
stream.Offset = stream.AbsolutePosition;
|
||||||
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
||||||
var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8"));
|
var dummyPath = Path.Combine(reader.FullPath, stream.AbsolutePosition.ToString("X8"));
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
total += ExtractBundleFile(subReader, subSavePath);
|
total += ExtractBundleFile(subReader, subSavePath);
|
||||||
} while (stream.Remaining > 0);
|
} while (stream.Remaining > 0);
|
||||||
|
|||||||
@@ -1899,8 +1899,9 @@ namespace AssetStudioGUI
|
|||||||
openFolderDialog.Title = "Select Game Folder";
|
openFolderDialog.Title = "Select Game Folder";
|
||||||
if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
|
if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
|
||||||
{
|
{
|
||||||
Logger.Info("Scanning for files");
|
Logger.Info("Scanning for files...");
|
||||||
var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray();
|
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");
|
Logger.Info($"Found {files.Length} files");
|
||||||
await Task.Run(() => AssetsHelper.BuildMap(files, name, openFolderDialog.Folder, Studio.Game));
|
await Task.Run(() => AssetsHelper.BuildMap(files, name, openFolderDialog.Folder, Studio.Game));
|
||||||
}
|
}
|
||||||
@@ -2017,8 +2018,9 @@ namespace AssetStudioGUI
|
|||||||
openFolderDialog.Title = $"Select Game Folder";
|
openFolderDialog.Title = $"Select Game Folder";
|
||||||
if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
|
if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
|
||||||
{
|
{
|
||||||
Logger.Info("Scanning for files");
|
Logger.Info("Scanning for files...");
|
||||||
var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray();
|
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");
|
Logger.Info($"Found {files.Length} files");
|
||||||
|
|
||||||
var saveFolderDialog = new OpenFolderDialog();
|
var saveFolderDialog = new OpenFolderDialog();
|
||||||
@@ -2317,7 +2319,7 @@ namespace AssetStudioGUI
|
|||||||
private void InitOpenTK()
|
private void InitOpenTK()
|
||||||
{
|
{
|
||||||
ChangeGLSize(glControl.Size);
|
ChangeGLSize(glControl.Size);
|
||||||
GL.ClearColor(Color4.Darkgray);
|
GL.ClearColor(Color4.Cadetblue);
|
||||||
pgmID = GL.CreateProgram();
|
pgmID = GL.CreateProgram();
|
||||||
LoadShader("vs", ShaderType.VertexShader, pgmID, out ShaderHandle vsID);
|
LoadShader("vs", ShaderType.VertexShader, pgmID, out ShaderHandle vsID);
|
||||||
LoadShader("fs", ShaderType.FragmentShader, pgmID, out ShaderHandle fsID);
|
LoadShader("fs", ShaderType.FragmentShader, pgmID, out ShaderHandle fsID);
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ namespace AssetStudioGUI
|
|||||||
using var stream = BlkUtils.Decrypt(reader, (Blk)Game);
|
using var stream = BlkUtils.Decrypt(reader, (Blk)Game);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.RelativePosition;
|
stream.Offset = stream.AbsolutePosition;
|
||||||
var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8"));
|
var dummyPath = Path.Combine(reader.FullPath, stream.AbsolutePosition.ToString("X8"));
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
||||||
switch (subReader.FileType)
|
switch (subReader.FileType)
|
||||||
@@ -154,12 +154,12 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
int total = 0;
|
int total = 0;
|
||||||
StatusStripUpdate($"Decompressing {reader.FileName} ...");
|
StatusStripUpdate($"Decompressing {reader.FileName} ...");
|
||||||
using var stream = new BlockStream(reader.BaseStream, 0);
|
using var stream = new SubStream(reader.BaseStream, 0);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.RelativePosition;
|
stream.Offset = stream.AbsolutePosition;
|
||||||
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
var subSavePath = Path.Combine(savePath, reader.FileName + "_unpacked");
|
||||||
var dummyPath = Path.Combine(reader.FullPath, stream.RelativePosition.ToString("X8"));
|
var dummyPath = Path.Combine(reader.FullPath, stream.AbsolutePosition.ToString("X8"));
|
||||||
var subReader = new FileReader(dummyPath, stream, true);
|
var subReader = new FileReader(dummyPath, stream, true);
|
||||||
total += ExtractBundleFile(subReader, subSavePath);
|
total += ExtractBundleFile(subReader, subSavePath);
|
||||||
} while (stream.Remaining > 0);
|
} while (stream.Remaining > 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user