internal override void UnserializeChunk(UndertaleReader reader)
        {
            Chunks.Clear();
            uint startPos = reader.Position;

            // First, find the last chunk in the file because of padding changes
            // (also, calculate all present chunks while we're at it)
            reader.AllChunkNames = new List <string>();
            string lastChunk = "";

            while (reader.Position < reader.BaseStream.Length)
            {
                lastChunk = new string(reader.ReadChars(4));
                reader.AllChunkNames.Add(lastChunk);
                uint length = reader.ReadUInt32();
                reader.Position += length;
            }
            reader.LastChunkName = lastChunk;
            reader.Position      = startPos;

            // Now, parse the chunks
            while (reader.Position < startPos + Length)
            {
                UndertaleChunk chunk = reader.ReadUndertaleChunk();
                if (chunk != null)
                {
                    if (Chunks.ContainsKey(chunk.Name))
                    {
                        throw new IOException("Duplicate chunk " + chunk.Name);
                    }
                    Chunks.Add(chunk.Name, chunk);
                }
            }
        }
示例#2
0
        public static UndertaleChunk Unserialize(UndertaleReader reader)
        {
            string name = "(unknown)";

            try
            {
                name = new string(reader.ReadChars(4));
                uint length = reader.ReadUInt32();

                // TODO: I can't think of a cleaner way to do this...
                Type type = Type.GetType(typeof(UndertaleChunk).FullName + name);
                if (type == null)
                {
                    throw new IOException("Unknown chunk " + name + "!!!");

                    /*Debug.WriteLine("Unknown chunk " + name + "!!!");
                     * reader.Position = reader.Position + length;
                     * return null;*/
                }

                UndertaleChunk chunk = (UndertaleChunk)Activator.CreateInstance(type);
                Debug.Assert(chunk.Name == name);
                chunk.Length = length;

                Debug.WriteLine("Reading chunk " + chunk.Name);
                var lenReader = reader.EnsureLengthFromHere(chunk.Length);
                chunk.UnserializeChunk(reader);

                if (name != "FORM" && name != "AUDO") // TODO: needs a better way to detect last chunk
                {
                    UndertaleGeneralInfo generalInfo = name == "GEN8" ? ((UndertaleChunkGEN8)chunk).Object : reader.undertaleData.GeneralInfo;
                    // These versions introduced new padding
                    // all chunks now start on 16-byte boundaries
                    // (but the padding is included with length of previous chunk)
                    if (generalInfo.Major >= 2 || (generalInfo.Major == 1 && generalInfo.Build >= 9999))
                    {
                        while (reader.Position % 16 != 0)
                        {
                            if (reader.ReadByte() != 0)
                            {
                                throw new Exception("Chunk padding error");
                            }
                        }
                    }
                }

                lenReader.ToHere();

                return(chunk);
            }
            catch (UndertaleSerializationException e)
            {
                throw new UndertaleSerializationException(e.Message + " in chunk " + name);
            }
            catch (Exception e)
            {
                throw new UndertaleSerializationException(e.Message + "\nat " + reader.Position.ToString("X8") + " while reading chunk " + name, e);
            }
        }
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            Chunks.Clear();
            uint startPos = reader.Position;

            while (reader.Position < startPos + Length)
            {
                UndertaleChunk chunk = reader.ReadUndertaleChunk();
                if (chunk != null)
                {
                    if (Chunks.ContainsKey(chunk.Name))
                    {
                        throw new IOException("Duplicate chunk " + chunk.Name);
                    }
                    Chunks.Add(chunk.Name, chunk);
                }
            }
        }