public void Parse(Stream baseStream) { Reset(); using (EndianStream stream = new EndianStream(baseStream, EndianType.BigEndian)) { long startPosition = baseStream.Position; stream.AlignPosition = startPosition; int tableSize = stream.ReadInt32(); if (tableSize <= 0) { throw new Exception($"Invalid table size {tableSize} for asset file {Name}"); } int dataEnd = stream.ReadInt32(); if (dataEnd <= 0) { throw new Exception($"Invalid data end {dataEnd} for asset file {Name}"); } Generation = (FileGeneration)stream.ReadInt32(); if (!Enum.IsDefined(typeof(FileGeneration), Generation)) { throw new Exception($"Unsuported file generation {Generation} for asset file '{Name}'"); } long dataOffset = startPosition + stream.ReadUInt32(); //reference itself because sharedFileIDs start from 1 AssetsFilePtr dependency = new AssetsFilePtr(Name, string.Empty); m_dependencies.Add(dependency); if (IsTableAtTheEnd) { stream.BaseStream.Position = dataEnd - tableSize; stream.BaseStream.Position++; } else { stream.BaseStream.Position += 4; } if (IsReadVersion) { string version = stream.ReadStringZeroTerm(); Version.Parse(version); } if (IsReadPlatform) { Platform = (Platform)stream.ReadUInt32(); // reverse stream endian if ((uint)Platform > byte.MaxValue) { Platform = (Platform)BitConverterExtensions.Reverse((uint)Platform); stream.EndianType = EndianType.LittleEndian; } if (!Enum.IsDefined(typeof(Platform), Platform)) { throw new Exception($"Unsuported platform {Platform} for asset file '{Name}'"); } } if (IsReadBaseDefinitions) { BaseDefinitions = stream.ReadBoolean(); } int baseCount = stream.ReadInt32(); for (int i = 0; i < baseCount; i++) { if (IsBase5) { ReadBase5(stream); } else { ReadBase(stream); } } if (IsSkipZero) { stream.BaseStream.Position += 4; } int assetCount = stream.ReadInt32(); if (assetCount < 0) { throw new Exception($"Invalid asset count {assetCount} for asset file {Name}"); } for (int i = 0; i < assetCount; i++) { if (IsNeedAlign) { stream.AlignStream(AlignType.Align4); } long pathID; if (IsLongPathID) { pathID = stream.ReadInt64(); } else { pathID = stream.ReadInt32(); } long offset = dataOffset + stream.ReadUInt32(); int size = stream.ReadInt32(); ClassIDMap classMap; if (IsReadSubClass) { int index = stream.ReadInt32(); classMap = m_classIDs[index]; } else { int uniqueID = stream.ReadInt32(); int classID = stream.ReadUInt16(); classMap = new ClassIDMap(uniqueID, classID); stream.BaseStream.Position += 2; } if (IsSkipUnknown) { //this is a single byte, not an int32 //the next entry is aligned after this //but not the last! stream.BaseStream.Position++; } AssetInfo assetInfo = new AssetInfo(this, pathID, classMap); AssetPreloadData asset = new AssetPreloadData(assetInfo, offset, size); m_assetPreloads.Add(pathID, asset); } if (IsReadPreload) { //this looks like a list of assets that need to be preloaded in memory before anytihng else int count = stream.ReadInt32(); for (int i = 0; i < count; i++) { int num1 = stream.ReadInt32(); stream.AlignStream(AlignType.Align4); long pathID = stream.ReadInt64(); } } int dependenciesCount = stream.ReadInt32(); for (int i = 0; i < dependenciesCount; i++) { string name = stream.ReadStringZeroTerm(); stream.BaseStream.Position += 20; string fileName = stream.ReadStringZeroTerm(); dependency = new AssetsFilePtr(fileName, name); m_dependencies.Add(dependency); } foreach (AssetPreloadData preload in m_assetPreloads.Values) { preload.Parse(stream); } } }
private void ReadBase5(EndianStream stream) { int classID = stream.ReadInt32(); if (IsReadSubClass) { // same class ID with different subclasses coored several times but we need unique class ID // so create unique class ID and store corresponding class ID stream.BaseStream.Position++; int uniqueClassID; int subClassID = stream.ReadInt16(); if (subClassID == -1) { // no subclass. that meen that class ID is unique by itself uniqueClassID = classID; } else if (subClassID >= 0) { // ordinal class ID should be >= 0, so we can use whole negative int range uniqueClassID = -1 - subClassID; } else { throw new Exception($"Invalid type value {subClassID} for asset file {Name}"); } ClassIDMap id = new ClassIDMap(uniqueClassID, classID); m_classIDs.Add(id); if (classID == (int)ClassIDType.MonoBehaviour) { stream.BaseStream.Position += 16; } classID = uniqueClassID; } else if (classID < 0) { stream.BaseStream.Position += 16; } stream.BaseStream.Position += 16; if (BaseDefinitions) { ClassStruct classStruct = new ClassStruct(); classStruct.ClassID = classID; int memberCount = stream.ReadInt32(); if (memberCount < 0) { throw new Exception($"Invalid member count {memberCount}"); } int stringSize = stream.ReadInt32(); if (stringSize < 0) { throw new Exception($"Invalid string size {stringSize}"); } long stringPosition = stream.BaseStream.Position + memberCount * ClassMember.ClassSize; List <ClassMember> members = new List <ClassMember>(); for (int i = 0; i < memberCount; i++) { ReadClassMember5(stream, classStruct, members, stringPosition); } stream.BaseStream.Position += stringSize; classStruct.Members = members.ToArray(); AddClassStruct(classStruct); } }