예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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);
            }
        }