//Reading names requires a high random access, set readNames to false if you don't need them public AssetsFileTable(AssetsFile pFile, bool readNames = true) { this.pFile = pFile; reader = pFile.reader; readerPar = pFile.readerPar; reader.bigEndian = pFile.header.endianness == 1 ? true : false; reader.BaseStream.Position = pFile.AssetTablePos; assetFileInfoCount = pFile.AssetCount; pAssetFileInfo = new AssetFileInfoEx[assetFileInfoCount]; for (int i = 0; i < assetFileInfoCount; i++) { AssetFileInfoEx assetFileInfoSet = new AssetFileInfoEx(); assetFileInfoSet.Read(pFile.header.format, reader.Position, reader, pFile.header.endianness == 1 ? true : false); assetFileInfoSet.absoluteFilePos = pFile.header.offs_firstFile + assetFileInfoSet.offs_curFile; assetFileInfoSet.curFileType = (uint)pFile.typeTree.pTypes_Unity5[assetFileInfoSet.curFileTypeOrIndex].classId; //todo: fix this variable (it can be from a different variable (index)) pAssetFileInfo[i] = assetFileInfoSet; //-Check 0x111FB for readNames stuff } }
public void Read(AssetsFileReader reader) { reader.bigEndian = false; header = reader.ReadStringLength(4); if (header != "cldb") { throw new Exception("header not detected. is this a cldb file?"); } fileVersion = reader.ReadByte(); flags = 0; if (fileVersion == 4) { flags = reader.ReadByte(); } switch (fileVersion) { case 1: compressionType = 0; break; case 2: compressionType = reader.ReadByte(); break; case 3: case 4: compressionType = reader.ReadByte(); compressedSize = reader.ReadUInt32(); uncompressedSize = reader.ReadUInt32(); break; default: return; } unityVersionCount = reader.ReadByte(); unityVersions = new string[unityVersionCount]; for (int i = 0; i < unityVersionCount; i++) { unityVersions[i] = reader.ReadCountString(); } stringTableLen = reader.ReadUInt32(); stringTablePos = reader.ReadUInt32(); }
public void Read(AssetsFileReader reader, uint format) { version = reader.ReadUInt16(); depth = reader.ReadByte(); isArray = reader.ReadByte(); typeStringOffset = reader.ReadUInt32(); nameStringOffset = reader.ReadUInt32(); size = reader.ReadInt32(); index = reader.ReadUInt32(); flags = reader.ReadUInt32(); if (format >= 0x12) { unknown = reader.ReadBytes(8); } else { unknown = new byte[0]; } }
public byte[] unknown; //0x18 public ulong Read(ulong absFilePos, AssetsFileReader reader, uint format, bool bigEndian) { version = reader.ReadUInt16(); depth = reader.ReadByte(); isArray = reader.ReadByte(); typeStringOffset = reader.ReadUInt32(); nameStringOffset = reader.ReadUInt32(); size = reader.ReadUInt32(); index = reader.ReadUInt32(); flags = reader.ReadUInt32(); if (format >= 0x12) { unknown = reader.ReadBytes(8); } else { unknown = new byte[0]; } return(reader.Position); }
public void Read(AssetsFileReader reader, int version, byte flags) { classId = reader.ReadInt32(); baseClass = reader.ReadInt32(); name = new ClassDatabaseFileString(); name.Read(reader); if ((flags & 1) != 0) { assemblyFileName = new ClassDatabaseFileString(); assemblyFileName.Read(reader); } uint fieldCount = reader.ReadUInt32(); fields = new List <ClassDatabaseTypeField>(); for (int i = 0; i < fieldCount; i++) { ClassDatabaseTypeField cdtf = new ClassDatabaseTypeField(); cdtf.Read(reader, version); fields.Add(cdtf); } }
public void Read(AssetsFileReader reader) { metadataSize = reader.ReadUInt32(); fileSize = reader.ReadUInt32(); format = reader.ReadUInt32(); firstFileOffset = reader.ReadUInt32(); if (format < 9) { endianness = reader.ReadByte(); } else { endianness = 0; } reader.bigEndian = endianness == 1 ? true : false; if (format >= 9) { unknown = reader.ReadBytes(3); } reader.Align(); }
public uint dwUnknown; //actually belongs to the asset list; stored for .assets format < 14 public void Read(AssetsFileReader reader, uint version) { unityVersion = reader.ReadNullTerminated(); this.version = reader.ReadUInt32(); if (version >= 0x0D) { hasTypeTree = reader.ReadBoolean(); } fieldCount = reader.ReadInt32(); unity5Types = new List <Type_0D>(); for (int i = 0; i < fieldCount; i++) { Type_0D type0d = new Type_0D(); type0d.Read(hasTypeTree, reader, version); unity5Types.Add(type0d); } if (version < 0x0E) { dwUnknown = reader.ReadUInt24(); } }//Minimum AssetsFile format : 6
public override bool Init(AssetsFileReader entryReader, long entryPos, long entrySize, ClassDatabaseFile typeMeta = null) { if (assetsFile != null) { return(false); } this.typeMeta = typeMeta; entryReader.Position = entryPos; //memorystream for alignment issue MemoryStream ms = new MemoryStream(); AssetsFileReader r = new AssetsFileReader(ms); AssetsFileWriter w = new AssetsFileWriter(ms); { w.Write(entryReader.ReadBytes((int)entrySize)); ms.Position = 0; assetsFile = new AssetsFile(r); } return(true); }
public ulong Read(bool hasTypeTree, ulong absFilePos, AssetsFileReader reader, uint version, uint typeVersion, bool bigEndian) { classId = reader.ReadInt32(); if (version >= 0x10) { unknown16_1 = reader.ReadByte(); } if (version >= 0x11) { scriptIndex = reader.ReadUInt16(); } //if ((version < 0x11 && classId < 0) || (version >= 0x11 && scriptIndex != 0xFFFF)) //original is if (classId == 114) //if ((version < 0x11 && classId < 0) || (version >= 0x11 && scriptIndex != 0xFFFF)) if ((version < 0x11 && classId < 0) || (version >= 0x11 && classId == 114)) { unknown1 = reader.ReadUInt32(); unknown2 = reader.ReadUInt32(); unknown3 = reader.ReadUInt32(); unknown4 = reader.ReadUInt32(); } unknown5 = reader.ReadUInt32(); unknown6 = reader.ReadUInt32(); unknown7 = reader.ReadUInt32(); unknown8 = reader.ReadUInt32(); if (hasTypeTree) { typeFieldsExCount = reader.ReadUInt32(); stringTableLen = reader.ReadUInt32(); pTypeFieldsEx = new TypeField_0D[typeFieldsExCount]; for (int i = 0; i < typeFieldsExCount; i++) { TypeField_0D typefield0d = new TypeField_0D(); typefield0d.Read(reader.Position, reader, version, bigEndian); pTypeFieldsEx[i] = typefield0d; } pStringTable = Encoding.UTF8.GetString(reader.ReadBytes((int)stringTableLen)); } return(reader.Position); }
public void Read(AssetsFileReader reader) { reader.bigEndian = false; magic = reader.ReadStringLength(4); fileVersion = reader.ReadByte(); compressionType = reader.ReadByte(); stringTableOffset = reader.ReadUInt32(); stringTableLenUncompressed = reader.ReadUInt32(); stringTableLenCompressed = reader.ReadUInt32(); fileBlockSize = reader.ReadUInt32(); fileCount = reader.ReadUInt32(); files = new List <ClassDatabaseFileRef>(); for (int i = 0; i < fileCount; i++) { files.Add(new ClassDatabaseFileRef() { offset = reader.ReadUInt32(), length = reader.ReadUInt32(), name = reader.ReadStringLength(15) }); } }
public AssetsFile(AssetsFileReader reader) { this.reader = reader; readerPar = reader.BaseStream; header = new AssetsFileHeader(); header.Read(reader); typeTree = new TypeTree(); typeTree.Read(reader, header.format); AssetCount = reader.ReadUInt32(); if (header.format == 15) { reader.Position += 3; } else { reader.Align(); } AssetTablePos = Convert.ToUInt32(reader.BaseStream.Position); reader.BaseStream.Position += AssetFileInfo.GetSize(header.format) * AssetCount; if (header.format == 15) { reader.BaseStream.Position -= 3; } if (header.format > 0x0B) { preloadTable = new PreloadList(); preloadTable.Read(reader); } if (header.format == 15) { reader.Align(); } dependencies = new AssetsFileDependencyList(); dependencies.Read(reader); }
public void Read(AssetsFileReader reader) { metadataSize = reader.ReadUInt32(); fileSize = reader.ReadUInt32(); format = reader.ReadUInt32(); firstFileOffset = reader.ReadUInt32(); endianness = reader.ReadByte(); //todo "fileSize - metadataSize" for v<9 but I have no files to test on unknown = reader.ReadBytes(3); reader.Align(); if (format >= 0x16) { metadataSize = reader.ReadUInt32(); fileSize = reader.ReadInt64(); firstFileOffset = reader.ReadInt64(); } reader.bigEndian = endianness == 1; if (format >= 0x16) { unknown1 = reader.ReadUInt32(); //seen as 0x00 everywhere unknown2 = reader.ReadUInt32(); //seen as 0x1b in bundles and 0x00 everywhere else } }
public ulong Read(AssetsFileReader reader, ulong filePos) { reader.bigEndian = false; header = reader.ReadStringLength(4); if (header != "cldb") { return(reader.Position); } fileVersion = reader.ReadByte(); switch (fileVersion) { case 1: break; case 3: compressionType = reader.ReadByte(); if (compressionType != 0) { return(reader.Position); } compressedSize = reader.ReadUInt32(); uncompressedSize = reader.ReadUInt32(); break; default: return(reader.Position); } unityVersionCount = reader.ReadByte(); pUnityVersions = new string[unityVersionCount]; for (int i = 0; i < unityVersionCount; i++) { pUnityVersions[i] = reader.ReadCountString(); } stringTableLen = reader.ReadUInt32(); stringTablePos = reader.ReadUInt32(); return(reader.Position); }
public void Read(bool hasTypeTree, AssetsFileReader reader, uint version) { classId = reader.ReadInt32(); if (version >= 0x10) { unknown16_1 = reader.ReadByte(); } if (version >= 0x11) { scriptIndex = reader.ReadUInt16(); } if ((version < 0x11 && classId < 0) || (version >= 0x11 && classId == 114)) { scriptHash1 = reader.ReadUInt32(); scriptHash2 = reader.ReadUInt32(); scriptHash3 = reader.ReadUInt32(); scriptHash4 = reader.ReadUInt32(); } typeHash1 = reader.ReadUInt32(); typeHash2 = reader.ReadUInt32(); typeHash3 = reader.ReadUInt32(); typeHash4 = reader.ReadUInt32(); if (hasTypeTree) { typeFieldsExCount = reader.ReadUInt32(); stringTableLen = reader.ReadUInt32(); typeFieldsEx = new TypeField_0D[typeFieldsExCount]; for (int i = 0; i < typeFieldsExCount; i++) { TypeField_0D typefield0d = new TypeField_0D(); typefield0d.Read(reader, version); typeFieldsEx[i] = typefield0d; } stringTable = Encoding.UTF8.GetString(reader.ReadBytes((int)stringTableLen)); } }
public AssetsFile(AssetsFileReader reader) { this.reader = reader; readerPar = reader.BaseStream; header = new AssetsFileHeader(); header.Read(reader); typeTree = new TypeTree(); typeTree.Read(reader, header.format); assetCount = reader.ReadUInt32(); reader.Align(); assetTablePos = (uint)reader.BaseStream.Position; int assetInfoSize = AssetFileInfo.GetSize(header.format); if (0x0F <= header.format && header.format <= 0x10) { //for these two versions, the asset info is not aligned //for the last entry, so we have to do some weird stuff reader.BaseStream.Position += ((assetInfoSize + 3) >> 2 << 2) * (assetCount - 1) + assetInfoSize; } else { reader.BaseStream.Position += AssetFileInfo.GetSize(header.format) * assetCount; } if (header.format > 0x0B) { preloadTable = new PreloadList(); preloadTable.Read(reader); } dependencies = new AssetsFileDependencyList(); dependencies.Read(reader); }
public AssetTypeValueField ReadType(AssetsFileReader reader, ulong filePos, AssetTypeValueField valueField, bool bigEndian) { if (valueField.templateField.isArray) { if (valueField.templateField.childrenCount == 2) { EnumValueTypes sizeType = valueField.templateField.children[0].valueType; if (sizeType == EnumValueTypes.ValueType_Int32 || sizeType == EnumValueTypes.ValueType_UInt32) { valueField.childrenCount = reader.ReadUInt32(); valueField.pChildren = new AssetTypeValueField[valueField.childrenCount]; for (int i = 0; i < valueField.childrenCount; i++) { valueField.pChildren[i] = new AssetTypeValueField(); valueField.pChildren[i].templateField = valueField.templateField.children[1]; valueField.pChildren[i] = ReadType(reader, reader.Position, valueField.pChildren[i], bigEndian); } if (valueField.templateField.align) { reader.Align(); } AssetTypeArray ata = new AssetTypeArray(); ata.size = valueField.childrenCount; valueField.value = new AssetTypeValue(EnumValueTypes.ValueType_Array, 0); valueField.value.Set(ata); } else { Debug.WriteLine("Invalid array value type! Found an unexpected " + sizeType.ToString() + " type instead!"); } } else { Debug.WriteLine("Invalid array!"); } } else { EnumValueTypes type = valueField.templateField.valueType; if (type != 0) { valueField.value = new AssetTypeValue(type, 0); } if (type == EnumValueTypes.ValueType_String) { valueField.value.Set(reader.ReadCountStringInt32()); reader.Align(); } else { valueField.childrenCount = valueField.templateField.childrenCount; if (valueField.childrenCount == 0) { valueField.pChildren = new AssetTypeValueField[0]; switch (valueField.templateField.valueType) { case EnumValueTypes.ValueType_Int8: valueField.value.Set(reader.ReadSByte()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.ValueType_UInt8: case EnumValueTypes.ValueType_Bool: valueField.value.Set(reader.ReadByte()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.ValueType_Int16: valueField.value.Set(reader.ReadInt16()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.ValueType_UInt16: valueField.value.Set(reader.ReadUInt16()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.ValueType_Int32: valueField.value.Set(reader.ReadInt32()); break; case EnumValueTypes.ValueType_UInt32: valueField.value.Set(reader.ReadUInt32()); break; case EnumValueTypes.ValueType_Int64: valueField.value.Set(reader.ReadInt64()); break; case EnumValueTypes.ValueType_UInt64: valueField.value.Set(reader.ReadUInt64()); break; case EnumValueTypes.ValueType_Float: valueField.value.Set(reader.ReadSingle()); break; case EnumValueTypes.ValueType_Double: valueField.value.Set(reader.ReadDouble()); break; } } else { valueField.pChildren = new AssetTypeValueField[valueField.childrenCount]; for (int i = 0; i < valueField.childrenCount; i++) { valueField.pChildren[i] = new AssetTypeValueField(); valueField.pChildren[i].templateField = valueField.templateField.children[i]; valueField.pChildren[i] = ReadType(reader, reader.Position, valueField.pChildren[i], bigEndian); } if (valueField.templateField.align) { reader.Align(); } } } } return(valueField); }
///public bool From07(TypeField_07 typeField) public void MakeValue(AssetsFileReader reader, out AssetTypeValueField valueField) { valueField = new AssetTypeValueField(); valueField.templateField = this; valueField = ReadType(reader, valueField); }
///public bool Write(AssetsFileReader reader, LPARAM readerPar, /// AssetsFileWriter writer, LPARAM writerPar, /// /// class BundleReplacer **pReplacers, size_t replacerCount, /// AssetsFileVerifyLogger errorLogger = NULL, ClassDatabaseFile* typeMeta = NULL); //-todo, use a faster custom bundle decompressor. currently a copy paste of unity studio's public bool Unpack(AssetsFileReader reader, AssetsFileWriter writer) { if (Read(reader, true)) { reader.Position = bundleHeader6.GetBundleInfoOffset(); MemoryStream blocksInfoStream; AssetsFileReader memReader; switch (bundleHeader6.flags & 0x3F) { case 1: blocksInfoStream = SevenZipHelper.StreamDecompress(new MemoryStream(reader.ReadBytes((int)bundleHeader6.compressedSize))); break; case 2: case 3: byte[] uncompressedBytes = new byte[bundleHeader6.decompressedSize]; using (var mstream = new MemoryStream(reader.ReadBytes((int)bundleHeader6.compressedSize))) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, (int)bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; default: blocksInfoStream = null; break; } if ((bundleHeader6.flags & 0x3F) != 0) { using (memReader = new AssetsFileReader(blocksInfoStream)) { bundleInf6.Read(0, memReader); } } reader.Position = bundleHeader6.GetFileDataOffset(); byte[][] blocksData = new byte[bundleInf6.blockCount][]; for (int i = 0; i < bundleInf6.blockCount; i++) { AssetsBundleBlockInfo06 info = bundleInf6.blockInf[i]; byte[] data = reader.ReadBytes((int)info.compressedSize); switch (info.flags & 0x3F) { case 0: blocksData[i] = data; break; case 1: blocksData[i] = new byte[info.decompressedSize]; using (MemoryStream mstream = new MemoryStream(data)) { MemoryStream decoder = SevenZipHelper.StreamDecompress(mstream, info.decompressedSize); decoder.Read(blocksData[i], 0, (int)info.decompressedSize); decoder.Dispose(); } break; case 2: case 3: blocksData[i] = new byte[info.decompressedSize]; using (MemoryStream mstream = new MemoryStream(data)) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(blocksData[i], 0, (int)info.decompressedSize); decoder.Dispose(); } break; } } AssetsBundleHeader06 newBundleHeader6 = new AssetsBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = bundleHeader6.decompressedSize, decompressedSize = bundleHeader6.decompressedSize, flags = bundleHeader6.flags & 0x40 //set compression and block position to 0 }; ulong fileSize = newBundleHeader6.GetFileDataOffset(); for (int i = 0; i < bundleInf6.blockCount; i++) { fileSize += bundleInf6.blockInf[i].decompressedSize; } newBundleHeader6.totalFileSize = fileSize; AssetsBundleBlockAndDirectoryList06 newBundleInf6 = new AssetsBundleBlockAndDirectoryList06() { checksumLow = 0, //-todo, figure out how to make real checksums, uabe sets these to 0 too checksumHigh = 0, blockCount = bundleInf6.blockCount, directoryCount = bundleInf6.directoryCount }; newBundleInf6.blockInf = new AssetsBundleBlockInfo06[newBundleInf6.blockCount]; for (int i = 0; i < newBundleInf6.blockCount; i++) { newBundleInf6.blockInf[i] = new AssetsBundleBlockInfo06(); newBundleInf6.blockInf[i].compressedSize = bundleInf6.blockInf[i].decompressedSize; newBundleInf6.blockInf[i].decompressedSize = bundleInf6.blockInf[i].decompressedSize; newBundleInf6.blockInf[i].flags = (ushort)(bundleInf6.blockInf[i].flags & 0xC0); //set compression to none } newBundleInf6.dirInf = new AssetsBundleDirectoryInfo06[newBundleInf6.directoryCount]; for (int i = 0; i < newBundleInf6.directoryCount; i++) { newBundleInf6.dirInf[i].offset = bundleInf6.dirInf[i].offset; newBundleInf6.dirInf[i].decompressedSize = bundleInf6.dirInf[i].decompressedSize; newBundleInf6.dirInf[i].flags = bundleInf6.dirInf[i].flags; newBundleInf6.dirInf[i].name = bundleInf6.dirInf[i].name; } newBundleHeader6.Write(writer, 0); newBundleInf6.Write(writer, writer.Position); for (int i = 0; i < newBundleInf6.blockCount; i++) { writer.Write(blocksData[i]); } return(true); } return(false); }
public bool IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry) { long offset = bundleHeader6.GetFileDataOffset() + entry.offset; return(AssetsFile.IsAssetsFile(reader, offset, entry.decompressedSize)); }
public bool Unpack(AssetsFileReader reader, AssetsFileWriter writer) { reader.Position = 0; if (Read(reader, true)) { reader.Position = bundleHeader6.GetBundleInfoOffset(); MemoryStream blocksInfoStream; AssetsFileReader memReader; int compressedSize = (int)bundleHeader6.compressedSize; switch (bundleHeader6.GetCompressionType()) { case 1: using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { blocksInfoStream = SevenZipHelper.StreamDecompress(mstream); } break; case 2: case 3: byte[] uncompressedBytes = new byte[bundleHeader6.decompressedSize]; using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, (int)bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; default: blocksInfoStream = null; break; } if (bundleHeader6.GetCompressionType() != 0) { using (memReader = new AssetsFileReader(blocksInfoStream)) { memReader.Position = 0; bundleInf6.Read(0, memReader); } } AssetBundleHeader06 newBundleHeader6 = new AssetBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = bundleHeader6.decompressedSize, decompressedSize = bundleHeader6.decompressedSize, flags = bundleHeader6.flags & 0x40 //set compression and block position to 0 }; long fileSize = newBundleHeader6.GetFileDataOffset(); for (int i = 0; i < bundleInf6.blockCount; i++) { fileSize += bundleInf6.blockInf[i].decompressedSize; } newBundleHeader6.totalFileSize = fileSize; AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06() { checksumLow = 0, //-todo, figure out how to make real checksums, uabe sets these to 0 too checksumHigh = 0, blockCount = bundleInf6.blockCount, directoryCount = bundleInf6.directoryCount }; newBundleInf6.blockInf = new AssetBundleBlockInfo06[newBundleInf6.blockCount]; for (int i = 0; i < newBundleInf6.blockCount; i++) { newBundleInf6.blockInf[i] = new AssetBundleBlockInfo06() { compressedSize = bundleInf6.blockInf[i].decompressedSize, decompressedSize = bundleInf6.blockInf[i].decompressedSize, flags = (ushort)(bundleInf6.blockInf[i].flags & 0xC0) //set compression to none }; } newBundleInf6.dirInf = new AssetBundleDirectoryInfo06[newBundleInf6.directoryCount]; for (int i = 0; i < newBundleInf6.directoryCount; i++) { newBundleInf6.dirInf[i] = new AssetBundleDirectoryInfo06() { offset = bundleInf6.dirInf[i].offset, decompressedSize = bundleInf6.dirInf[i].decompressedSize, flags = bundleInf6.dirInf[i].flags, name = bundleInf6.dirInf[i].name }; } newBundleHeader6.Write(writer); if (newBundleHeader6.fileVersion >= 7) { writer.Align16(); } newBundleInf6.Write(writer); reader.Position = bundleHeader6.GetFileDataOffset(); for (int i = 0; i < newBundleInf6.blockCount; i++) { AssetBundleBlockInfo06 info = bundleInf6.blockInf[i]; switch (info.GetCompressionType()) { case 0: reader.BaseStream.CopyToCompat(writer.BaseStream, info.compressedSize); break; case 1: SevenZipHelper.StreamDecompress(reader.BaseStream, writer.BaseStream, info.compressedSize, info.decompressedSize); break; case 2: case 3: using (MemoryStream tempMs = new MemoryStream()) { reader.BaseStream.CopyToCompat(tempMs, info.compressedSize); tempMs.Position = 0; using (Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs)) { decoder.CopyToCompat(writer.BaseStream, info.decompressedSize); } } break; } } return(true); } return(false); }
public bool Read(AssetsFileReader reader) { header = new ClassDatabasePackageHeader(); header.Read(reader); files = new List <ClassDatabaseFile>(); long firstFile = reader.Position; AssetsFileReader newReader = reader; if ((header.compressionType & 0x80) == 0) //multiple compressed blocks { //untested! //the compression is handled by the cldbs themselves for (int i = 0; i < header.fileCount; i++) { newReader.Position = firstFile + header.files[i].offset; byte[] data = newReader.ReadBytes((int)header.files[i].length); using (MemoryStream ms = new MemoryStream(data)) using (AssetsFileReader r = new AssetsFileReader(ms)) { ClassDatabaseFile file = new ClassDatabaseFile(); file.Read(r); files.Add(file); } } } else //one compressed block { if ((header.compressionType & 0x20) == 0) //file block compressed { firstFile = 0; int compressedSize = (int)(header.stringTableOffset - newReader.Position); int uncompressedSize = (int)header.fileBlockSize; MemoryStream ms; if ((header.compressionType & 0x1f) == 1) //lz4 { byte[] uncompressedBytes = new byte[uncompressedSize]; using (MemoryStream tempMs = new MemoryStream(newReader.ReadBytes(compressedSize))) { Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs); decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } ms = new MemoryStream(uncompressedBytes); } else if ((header.compressionType & 0x1f) == 2) //lzma { byte[] dbg = newReader.ReadBytes(compressedSize); using (MemoryStream tempMs = new MemoryStream(dbg)) { ms = SevenZipHelper.StreamDecompress(tempMs, uncompressedSize); } } else { valid = false; return(valid); } newReader = new AssetsFileReader(ms); newReader.bigEndian = false; } for (int i = 0; i < header.fileCount; i++) { newReader.Position = firstFile + header.files[i].offset; byte[] data = newReader.ReadBytes((int)header.files[i].length); using (MemoryStream ms = new MemoryStream(data)) using (AssetsFileReader r = new AssetsFileReader(ms)) { ClassDatabaseFile file = new ClassDatabaseFile(); file.Read(r); files.Add(file); } } } newReader = reader; newReader.Position = header.stringTableOffset; if ((header.compressionType & 0x40) == 0) //string table is compressed { int compressedSize = (int)header.stringTableLenCompressed; int uncompressedSize = (int)header.stringTableLenUncompressed; MemoryStream ms; if ((header.compressionType & 0x1f) == 1) //lz4 { byte[] uncompressedBytes = new byte[uncompressedSize]; using (MemoryStream tempMs = new MemoryStream(newReader.ReadBytes(compressedSize))) { Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs); decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } ms = new MemoryStream(uncompressedBytes); } else if ((header.compressionType & 0x1f) == 2) //lzma { using (MemoryStream tempMs = new MemoryStream(newReader.ReadBytes(compressedSize))) { ms = SevenZipHelper.StreamDecompress(tempMs, uncompressedSize); } } else { valid = false; return(valid); } newReader = new AssetsFileReader(ms); newReader.bigEndian = false; } stringTable = newReader.ReadBytes((int)header.stringTableLenUncompressed); for (int i = 0; i < header.fileCount; i++) { files[i].stringTable = stringTable; } valid = true; return(valid); }
public long leastSignificant; //0-63 //big-endian public ulong Read(ulong absFilePos, AssetsFileReader reader) { mostSignificant = reader.ReadInt64(); leastSignificant = reader.ReadInt64(); return(reader.Position); }
public AssetTypeValueField ReadType(AssetsFileReader reader, AssetTypeValueField valueField) { if (valueField.templateField.isArray) { if (valueField.templateField.childrenCount == 2) { EnumValueTypes sizeType = valueField.templateField.children[0].valueType; if (sizeType == EnumValueTypes.Int32 || sizeType == EnumValueTypes.UInt32) { if (valueField.templateField.valueType == EnumValueTypes.ByteArray) { valueField.childrenCount = 0; valueField.children = new AssetTypeValueField[0]; int size = reader.ReadInt32(); byte[] data = reader.ReadBytes(size); if (valueField.templateField.align) { reader.Align(); } AssetTypeByteArray atba = new AssetTypeByteArray(); atba.size = (uint)size; atba.data = data; valueField.value = new AssetTypeValue(EnumValueTypes.ByteArray, atba); } else { valueField.childrenCount = reader.ReadInt32(); valueField.children = new AssetTypeValueField[valueField.childrenCount]; for (int i = 0; i < valueField.childrenCount; i++) { valueField.children[i] = new AssetTypeValueField(); valueField.children[i].templateField = valueField.templateField.children[1]; valueField.children[i] = ReadType(reader, valueField.children[i]); } if (valueField.templateField.align) { reader.Align(); } AssetTypeArray ata = new AssetTypeArray(); ata.size = valueField.childrenCount; valueField.value = new AssetTypeValue(EnumValueTypes.Array, ata); } } else { throw new Exception("Invalid array value type! Found an unexpected " + sizeType.ToString() + " type instead!"); } } else { throw new Exception("Invalid array!"); } } else { EnumValueTypes type = valueField.templateField.valueType; if (type != 0) { valueField.value = new AssetTypeValue(type, null); } if (type == EnumValueTypes.String) { int length = reader.ReadInt32(); valueField.value.Set(reader.ReadBytes(length)); reader.Align(); } else { valueField.childrenCount = valueField.templateField.childrenCount; if (valueField.childrenCount == 0) { valueField.children = new AssetTypeValueField[0]; switch (valueField.templateField.valueType) { case EnumValueTypes.Int8: valueField.value.Set(reader.ReadSByte()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.UInt8: case EnumValueTypes.Bool: valueField.value.Set(reader.ReadByte()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.Int16: valueField.value.Set(reader.ReadInt16()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.UInt16: valueField.value.Set(reader.ReadUInt16()); if (valueField.templateField.align) { reader.Align(); } break; case EnumValueTypes.Int32: valueField.value.Set(reader.ReadInt32()); break; case EnumValueTypes.UInt32: valueField.value.Set(reader.ReadUInt32()); break; case EnumValueTypes.Int64: valueField.value.Set(reader.ReadInt64()); break; case EnumValueTypes.UInt64: valueField.value.Set(reader.ReadUInt64()); break; case EnumValueTypes.Float: valueField.value.Set(reader.ReadSingle()); break; case EnumValueTypes.Double: valueField.value.Set(reader.ReadDouble()); break; } } else { valueField.children = new AssetTypeValueField[valueField.childrenCount]; for (int i = 0; i < valueField.childrenCount; i++) { valueField.children[i] = new AssetTypeValueField(); valueField.children[i].templateField = valueField.templateField.children[i]; valueField.children[i] = ReadType(reader, valueField.children[i]); } if (valueField.templateField.align) { reader.Align(); } } } } return(valueField); }
public long leastSignificant; //0-63 //big-endian public void Read(AssetsFileReader reader) { mostSignificant = reader.ReadInt64(); leastSignificant = reader.ReadInt64(); }
public override bool Init(AssetsFileReader entryReader, long entryPos, long entrySize, ClassDatabaseFile typeMeta = null) { return(true); }
public bool Pack(AssetsFileReader reader, AssetsFileWriter writer, AssetBundleCompressionType compType, bool blockDirAtEnd = true) { reader.Position = 0; writer.Position = 0; if (Read(reader, false)) { AssetBundleHeader06 newHeader = new AssetBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = 0, decompressedSize = 0, flags = (uint)(0x43 | (blockDirAtEnd ? 0x80 : 0x00)) }; AssetBundleBlockAndDirectoryList06 newBlockAndDirList = new AssetBundleBlockAndDirectoryList06() { checksumLow = 0, checksumHigh = 0, blockCount = 0, blockInf = null, directoryCount = bundleInf6.directoryCount, dirInf = bundleInf6.dirInf }; //write header now and overwrite it later long startPos = writer.Position; newHeader.Write(writer); if (newHeader.fileVersion >= 7) { writer.Align16(); } int headerSize = (int)(writer.Position - startPos); long totalCompressedSize = 0; List <AssetBundleBlockInfo06> newBlocks = new List <AssetBundleBlockInfo06>(); List <Stream> newStreams = new List <Stream>(); //used if blockDirAtEnd == false long fileDataOffset = bundleHeader6.GetFileDataOffset(); int fileDataLength = (int)(bundleHeader6.totalFileSize - fileDataOffset); SegmentStream bundleDataStream = new SegmentStream(reader.BaseStream, fileDataOffset, fileDataLength); switch (compType) { case AssetBundleCompressionType.LZMA: { Stream writeStream; if (blockDirAtEnd) { writeStream = writer.BaseStream; } else { writeStream = GetTempFileStream(); } long writeStreamStart = writeStream.Position; SevenZipHelper.Compress(bundleDataStream, writeStream); uint writeStreamLength = (uint)(writeStream.Position - writeStreamStart); AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = writeStreamLength, decompressedSize = (uint)fileDataLength, flags = 0x41 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); if (!blockDirAtEnd) { newStreams.Add(writeStream); } break; } case AssetBundleCompressionType.LZ4: { //compress into 0x20000 blocks BinaryReader bundleDataReader = new BinaryReader(bundleDataStream); byte[] uncompressedBlock = bundleDataReader.ReadBytes(0x20000); while (uncompressedBlock.Length != 0) { Stream writeStream; if (blockDirAtEnd) { writeStream = writer.BaseStream; } else { writeStream = GetTempFileStream(); } byte[] compressedBlock = LZ4Codec.Encode32HC(uncompressedBlock, 0, uncompressedBlock.Length); if (compressedBlock.Length > uncompressedBlock.Length) { writeStream.Write(uncompressedBlock, 0, uncompressedBlock.Length); AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = (uint)uncompressedBlock.Length, decompressedSize = (uint)uncompressedBlock.Length, flags = 0x0 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); } else { writeStream.Write(compressedBlock, 0, compressedBlock.Length); AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = (uint)compressedBlock.Length, decompressedSize = (uint)uncompressedBlock.Length, flags = 0x3 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); } if (!blockDirAtEnd) { newStreams.Add(writeStream); } uncompressedBlock = bundleDataReader.ReadBytes(0x20000); } break; } case AssetBundleCompressionType.NONE: { AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06() { compressedSize = (uint)fileDataLength, decompressedSize = (uint)fileDataLength, flags = 0x00 }; totalCompressedSize += blockInfo.compressedSize; newBlocks.Add(blockInfo); if (blockDirAtEnd) { bundleDataStream.CopyToCompat(writer.BaseStream); } else { newStreams.Add(bundleDataStream); } break; } } newBlockAndDirList.blockInf = newBlocks.ToArray(); byte[] bundleInfoBytes; using (MemoryStream memStream = new MemoryStream()) { AssetsFileWriter infoWriter = new AssetsFileWriter(memStream); newBlockAndDirList.Write(infoWriter); bundleInfoBytes = memStream.ToArray(); } //listing is usually lz4 even if the data blocks are lzma byte[] bundleInfoBytesCom = LZ4Codec.Encode32HC(bundleInfoBytes, 0, bundleInfoBytes.Length); long totalFileSize = headerSize + bundleInfoBytesCom.Length + totalCompressedSize; newHeader.totalFileSize = totalFileSize; newHeader.decompressedSize = (uint)bundleInfoBytes.Length; newHeader.compressedSize = (uint)bundleInfoBytesCom.Length; if (!blockDirAtEnd) { writer.Write(bundleInfoBytesCom); foreach (Stream newStream in newStreams) { newStream.Position = 0; newStream.CopyToCompat(writer.BaseStream); newStream.Close(); } } else { writer.Write(bundleInfoBytesCom); } writer.Position = 0; newHeader.Write(writer); if (newHeader.fileVersion >= 7) { writer.Align16(); } return(true); } return(false); }
public bool Pack(AssetsFileReader reader, AssetsFileWriter writer, AssetBundleCompressionType compType) { reader.Position = 0; writer.Position = 0; if (Read(reader, false)) { AssetBundleHeader06 newHeader = new AssetBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = 0, decompressedSize = 0, flags = 0x43 }; AssetBundleBlockAndDirectoryList06 newBlockAndDirList = new AssetBundleBlockAndDirectoryList06() { checksumLow = 0, checksumHigh = 0, blockCount = 0, blockInf = null, directoryCount = bundleInf6.directoryCount, dirInf = bundleInf6.dirInf }; List <AssetBundleBlockInfo06> newBlocks = new List <AssetBundleBlockInfo06>(); reader.Position = bundleHeader6.GetFileDataOffset(); int fileDataLength = (int)(bundleHeader6.totalFileSize - reader.Position); byte[] fileData = reader.ReadBytes(fileDataLength); //todo, we just write everything to memory and then write to file //we could calculate the blocks we need ahead of time and correctly //size the block listing before this so we can write directly to file byte[] compressedFileData; switch (compType) { case AssetBundleCompressionType.LZMA: { compressedFileData = SevenZipHelper.Compress(fileData); newBlocks.Add(new AssetBundleBlockInfo06() { compressedSize = (uint)compressedFileData.Length, decompressedSize = (uint)fileData.Length, flags = 0x41 }); break; } case AssetBundleCompressionType.LZ4: { using (var memStreamCom = new MemoryStream()) using (var binaryWriter = new BinaryWriter(memStreamCom)) { using (var memStreamUnc = new MemoryStream(fileData)) using (var binaryReader = new BinaryReader(memStreamUnc)) { //compress into 0x20000 blocks byte[] uncompressedBlock = binaryReader.ReadBytes(131072); while (uncompressedBlock.Length != 0) { byte[] compressedBlock = LZ4Codec.Encode32HC(uncompressedBlock, 0, uncompressedBlock.Length); if (compressedBlock.Length > uncompressedBlock.Length) { newBlocks.Add(new AssetBundleBlockInfo06() { compressedSize = (uint)uncompressedBlock.Length, decompressedSize = (uint)uncompressedBlock.Length, flags = 0x0 }); binaryWriter.Write(uncompressedBlock); } else { newBlocks.Add(new AssetBundleBlockInfo06() { compressedSize = (uint)compressedBlock.Length, decompressedSize = (uint)uncompressedBlock.Length, flags = 0x3 }); binaryWriter.Write(compressedBlock); } uncompressedBlock = binaryReader.ReadBytes(131072); } } compressedFileData = memStreamCom.ToArray(); } break; } case AssetBundleCompressionType.NONE: { compressedFileData = fileData; newBlocks.Add(new AssetBundleBlockInfo06() { compressedSize = (uint)fileData.Length, decompressedSize = (uint)fileData.Length, flags = 0x00 }); break; } default: { return(false); } } newBlockAndDirList.blockInf = newBlocks.ToArray(); byte[] bundleInfoBytes; using (var memStream = new MemoryStream()) { var afw = new AssetsFileWriter(memStream); newBlockAndDirList.Write(afw); bundleInfoBytes = memStream.ToArray(); } if (bundleInfoBytes == null || bundleInfoBytes.Length == 0) { return(false); } //listing is usually lz4 even if the data blocks are lzma byte[] bundleInfoBytesCom = LZ4Codec.Encode32HC(bundleInfoBytes, 0, bundleInfoBytes.Length); byte[] bundleHeaderBytes = null; using (var memStream = new MemoryStream()) { var afw = new AssetsFileWriter(memStream); newHeader.Write(afw); bundleHeaderBytes = memStream.ToArray(); } if (bundleHeaderBytes == null || bundleHeaderBytes.Length == 0) { return(false); } uint totalFileSize = (uint)(bundleHeaderBytes.Length + bundleInfoBytesCom.Length + compressedFileData.Length); newHeader.totalFileSize = totalFileSize; newHeader.decompressedSize = (uint)bundleInfoBytes.Length; newHeader.compressedSize = (uint)bundleInfoBytesCom.Length; newHeader.Write(writer); if (newHeader.fileVersion >= 7) { writer.Align16(); } writer.Write(bundleInfoBytesCom); writer.Write(compressedFileData); return(true); } return(false); }
public static bool IsAssetsFile(string filePath) { using AssetsFileReader reader = new AssetsFileReader(filePath); return(IsAssetsFile(reader, 0, reader.BaseStream.Length)); }
public override bool Init(AssetBundleFile bundleFile, AssetsFileReader entryReader, long entryPos, long entrySize) { return(true); }
public bool Read(AssetsFileReader reader) { header = new ClassDatabaseFileHeader(); header.Read(reader); if (header.header != "cldb" || (header.fileVersion != 4 && header.fileVersion != 3 && header.fileVersion != 1)) { valid = false; return(valid); } classes = new List <ClassDatabaseType>(); long classTablePos = reader.Position; AssetsFileReader newReader = reader; if (header.compressionType != 0) { classTablePos = 0; MemoryStream ms; if (header.compressionType == 1) //lz4 { byte[] uncompressedBytes = new byte[header.uncompressedSize]; using (MemoryStream tempMs = new MemoryStream(reader.ReadBytes((int)header.compressedSize))) { Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs); decoder.Read(uncompressedBytes, 0, (int)header.uncompressedSize); decoder.Dispose(); } ms = new MemoryStream(uncompressedBytes); } else if (header.compressionType == 2) //lzma { using (MemoryStream tempMs = new MemoryStream(reader.ReadBytes((int)header.compressedSize))) { ms = SevenZipHelper.StreamDecompress(tempMs); } } else { valid = false; return(valid); } newReader = new AssetsFileReader(ms); newReader.bigEndian = false; } newReader.Position = header.stringTablePos; stringTable = newReader.ReadBytes((int)header.stringTableLen); newReader.Position = classTablePos; uint size = newReader.ReadUInt32(); for (int i = 0; i < size; i++) { ClassDatabaseType cdt = new ClassDatabaseType(); cdt.Read(newReader, header.fileVersion, header.flags); classes.Add(cdt); } valid = true; return(valid); }