///public bool Pack(AssetsFileReader reader, LPARAM lPar, AssetsFileWriter writer, LPARAM writerPar); public bool IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry) { //todo - not fully implemented long offset = bundleHeader6.GetFileDataOffset() + entry.offset; if (entry.decompressedSize < 0x20) { return(false); } reader.Position = offset; string possibleBundleHeader = reader.ReadStringLength(7); if (possibleBundleHeader == "UnityFS") { return(false); } reader.Position = offset + 0x08; int possibleFormat = reader.ReadInt32(); if (possibleFormat > 99) { return(false); } reader.Position = offset + 0x14; string possibleVersion = reader.ReadNullTerminated(); string emptyVersion = Regex.Replace(possibleVersion, "[a-zA-Z0-9\\.]", ""); string fullVersion = Regex.Replace(possibleVersion, "[^a-zA-Z0-9\\.]", ""); return(emptyVersion == "" && fullVersion.Length > 0); }
public bool IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry) { //todo - not fully implemented long offset = bundleHeader6.GetFileDataOffset() + entry.offset; if (entry.decompressedSize < 0x30) { return(false); } reader.Position = offset; string possibleBundleHeader = reader.ReadStringLength(7); if (possibleBundleHeader == "UnityFS") { return(false); } reader.Position = offset + 0x08; int possibleFormat = reader.ReadInt32(); if (possibleFormat > 99) { return(false); } reader.Position = offset + 0x14; if (possibleFormat >= 0x16) { reader.Position += 0x1c; } string possibleVersion = ""; char curChar; while (reader.Position < reader.BaseStream.Length && (curChar = (char)reader.ReadByte()) != 0x00) { possibleVersion += curChar; if (possibleVersion.Length > 0xFF) { return(false); } } string emptyVersion = Regex.Replace(possibleVersion, "[a-zA-Z0-9\\.]", ""); string fullVersion = Regex.Replace(possibleVersion, "[^a-zA-Z0-9\\.]", ""); return(emptyVersion == "" && fullVersion.Length > 0); }
internal void GetFileRange(int index, out long offset, out long length) { if (bundleHeader3 != null) { AssetsBundleEntry entry = assetsLists3.entries[index]; offset = bundleHeader3.bundleDataOffs + entry.offset; length = entry.length; } else if (bundleHeader6 != null) { AssetBundleDirectoryInfo06 entry = bundleInf6.dirInf[index]; offset = bundleHeader6.GetFileDataOffset() + entry.offset; length = entry.decompressedSize; } else { throw new NotSupportedException(); } }
public bool Write(AssetsFileWriter writer, List <BundleReplacer> replacers, ClassDatabaseFile typeMeta = null) { bundleHeader6.Write(writer); if (bundleHeader6.fileVersion >= 7) { writer.Align16(); } AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06() { checksumLow = 0, checksumHigh = 0 }; //I could map the assets to their blocks but I don't //have any more-than-1-block files to test on //this should work just fine as far as I know newBundleInf6.blockInf = new AssetBundleBlockInfo06[] { new AssetBundleBlockInfo06 { compressedSize = 0, decompressedSize = 0, flags = 0x40 } }; //assets that did not have their data modified but need //the original info to read from the original file var newToOriginalDirInfoLookup = new Dictionary <AssetBundleDirectoryInfo06, AssetBundleDirectoryInfo06>(); List <AssetBundleDirectoryInfo06> originalDirInfos = new List <AssetBundleDirectoryInfo06>(); List <AssetBundleDirectoryInfo06> dirInfos = new List <AssetBundleDirectoryInfo06>(); List <BundleReplacer> currentReplacers = replacers.ToList(); //this is kind of useless at the moment but leaving it here //because if the AssetsFile size can be precalculated in the //future, we can use this to skip rewriting sizes long currentOffset = 0; //write all original files, modify sizes if needed and skip those to be removed for (int i = 0; i < bundleInf6.directoryCount; i++) { AssetBundleDirectoryInfo06 info = bundleInf6.dirInf[i]; originalDirInfos.Add(info); AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06() { offset = currentOffset, decompressedSize = info.decompressedSize, flags = info.flags, name = info.name }; BundleReplacer replacer = currentReplacers.FirstOrDefault(n => n.GetOriginalEntryName() == newInfo.name); if (replacer != null) { currentReplacers.Remove(replacer); if (replacer.GetReplacementType() == BundleReplacementType.AddOrModify) { newInfo = new AssetBundleDirectoryInfo06() { offset = currentOffset, decompressedSize = replacer.GetSize(), flags = info.flags, name = replacer.GetEntryName() }; } else if (replacer.GetReplacementType() == BundleReplacementType.Rename) { newInfo = new AssetBundleDirectoryInfo06() { offset = currentOffset, decompressedSize = info.decompressedSize, flags = info.flags, name = replacer.GetEntryName() }; newToOriginalDirInfoLookup[newInfo] = info; } else if (replacer.GetReplacementType() == BundleReplacementType.Remove) { continue; } } else { newToOriginalDirInfoLookup[newInfo] = info; } if (newInfo.decompressedSize != -1) { currentOffset += newInfo.decompressedSize; } dirInfos.Add(newInfo); } //write new files while (currentReplacers.Count > 0) { BundleReplacer replacer = currentReplacers[0]; if (replacer.GetReplacementType() == BundleReplacementType.AddOrModify) { AssetBundleDirectoryInfo06 info = new AssetBundleDirectoryInfo06() { offset = currentOffset, decompressedSize = replacer.GetSize(), flags = 0x04, //idk it just works (tm) name = replacer.GetEntryName() }; currentOffset += info.decompressedSize; dirInfos.Add(info); } currentReplacers.Remove(replacer); } //write the listings long bundleInfPos = writer.Position; newBundleInf6.dirInf = dirInfos.ToArray(); //this is only here to allocate enough space so it's fine if it's inaccurate newBundleInf6.Write(writer); long assetDataPos = writer.Position; //actually write the file data to the bundle now for (int i = 0; i < dirInfos.Count; i++) { AssetBundleDirectoryInfo06 info = dirInfos[i]; BundleReplacer replacer = replacers.FirstOrDefault(n => n.GetEntryName() == info.name); if (replacer != null) { if (replacer.GetReplacementType() == BundleReplacementType.AddOrModify) { long startPos = writer.Position; long endPos = replacer.Write(writer); long size = endPos - startPos; dirInfos[i].decompressedSize = size; dirInfos[i].offset = startPos - assetDataPos; } else if (replacer.GetReplacementType() == BundleReplacementType.Remove) { continue; } } else { if (newToOriginalDirInfoLookup.TryGetValue(info, out AssetBundleDirectoryInfo06 originalInfo)) { long startPos = writer.Position; reader.Position = bundleHeader6.GetFileDataOffset() + originalInfo.offset; reader.BaseStream.CopyToCompat(writer.BaseStream, originalInfo.decompressedSize); dirInfos[i].offset = startPos - assetDataPos; } } } //now that we know what the sizes are of the written files let's go back and fix them long finalSize = writer.Position; uint assetSize = (uint)(finalSize - assetDataPos); writer.Position = bundleInfPos; newBundleInf6.blockInf[0].decompressedSize = assetSize; newBundleInf6.blockInf[0].compressedSize = assetSize; newBundleInf6.dirInf = dirInfos.ToArray(); newBundleInf6.Write(writer); uint infoSize = (uint)(assetDataPos - bundleInfPos); writer.Position = 0; AssetBundleHeader06 newBundleHeader6 = new AssetBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = finalSize, compressedSize = infoSize, decompressedSize = infoSize, flags = bundleHeader6.flags & unchecked ((uint)~0x80) & unchecked ((uint)~0x3f) //unset info at end flag and compression value }; newBundleHeader6.Write(writer); return(true); }
public bool IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry) { long offset = bundleHeader6.GetFileDataOffset() + entry.offset; return(AssetsFile.IsAssetsFile(reader, offset, entry.decompressedSize)); }