예제 #1
0
    /// <inheritdoc />
    public void Unserialize(UndertaleReader reader)
    {
        Name          = reader.ReadUndertaleString();
        DisplayName   = reader.ReadUndertaleString();
        EmSize        = reader.ReadUInt32();
        EmSizeIsFloat = false;

        // since the float is always written negated, it has the first bit set.
        if ((EmSize & (1 << 31)) != 0)
        {
            float fsize = -BitConverter.ToSingle(BitConverter.GetBytes(EmSize), 0);
            EmSize        = (uint)fsize;
            EmSizeIsFloat = true;
        }

        Bold         = reader.ReadBoolean();
        Italic       = reader.ReadBoolean();
        RangeStart   = reader.ReadUInt16();
        Charset      = reader.ReadByte();
        AntiAliasing = reader.ReadByte();
        RangeEnd     = reader.ReadUInt32();
        Texture      = reader.ReadUndertaleObjectPointer <UndertaleTexturePageItem>();
        ScaleX       = reader.ReadSingle();
        ScaleY       = reader.ReadSingle();
        if (reader.undertaleData.GeneralInfo?.BytecodeVersion >= 17)
        {
            AscenderOffset = reader.ReadInt32();
        }
        if (reader.undertaleData.GMS2022_2)
        {
            Ascender = reader.ReadUInt32();
        }
        Glyphs = reader.ReadUndertaleObject <UndertalePointerList <Glyph> >();
    }
 public void Unserialize(UndertaleReader reader)
 {
     Name       = reader.ReadUndertaleString();
     Function   = (FunctionType)reader.ReadUInt32();
     Iterations = reader.ReadUInt32();
     Points     = reader.ReadUndertaleObject <UndertaleSimpleList <Point> >();
 }
                public void Unserialize(UndertaleReader reader)
                {
                    X     = reader.ReadSingle();
                    Value = reader.ReadSingle();

                    if (reader.ReadUInt32() != 0) // in 2.3 a int with the value of 0 would be set here,
                    {                             // it cannot be version 2.3 if this value isn't 0
                        reader.undertaleData.GMS2_3_1 = true;
                        reader.Position -= 4;
                    }
                    else
                    {
                        if (reader.ReadUInt32() == 0)             // At all points (besides the first one)
                        {
                            reader.undertaleData.GMS2_3_1 = true; // if BezierX0 equals to 0 (the above check)
                        }
                        reader.Position -= 8;                     // then BezierY0 equals to 0 as well (the current check)
                    }

                    if (reader.undertaleData.GMS2_3_1)
                    {
                        BezierX0 = reader.ReadSingle();
                        BezierY0 = reader.ReadSingle();
                        BezierX1 = reader.ReadSingle();
                        BezierY1 = reader.ReadSingle();
                    }
                    else
                    {
                        reader.Position += 4;
                    }
                }
예제 #4
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            if (Length == 0) // YYC, bytecode <= 16, chunk is empty but exists
            {
                List = null;
                return;
            }

            if (reader.undertaleData.UnsupportedBytecodeVersion)
            {
                return;
            }
            uint startPosition = reader.Position;
            uint varLength;

            if (!reader.Bytecode14OrLower)
            {
                InstanceVarCount      = reader.ReadUInt32();
                InstanceVarCountAgain = reader.ReadUInt32();
                MaxLocalVarCount      = reader.ReadUInt32();
                varLength             = 20;
            }
            else
            {
                varLength = 12;
            }
            List.Clear();
            while (reader.Position + varLength <= startPosition + Length)
            {
                List.Add(reader.ReadUndertaleObject <UndertaleVariable>());
            }
        }
예제 #5
0
        public void Unserialize(UndertaleReader reader)
        {
            Name              = reader.ReadUndertaleString();
            Playback          = (PlaybackType)reader.ReadUInt32();
            PlaybackSpeed     = reader.ReadSingle();
            PlaybackSpeedType = (AnimSpeedType)reader.ReadUInt32();
            Length            = reader.ReadSingle();
            OriginX           = reader.ReadInt32();
            OriginY           = reader.ReadInt32();
            Volume            = reader.ReadSingle();

            BroadcastMessages = reader.ReadUndertaleObject <UndertaleSimpleList <Keyframe <BroadcastMessage> > >();

            Tracks = reader.ReadUndertaleObject <UndertaleSimpleList <Track> >();

            FunctionIDs = new Dictionary <int, UndertaleString>();
            int count = reader.ReadInt32();

            for (int i = 0; i < count; i++)
            {
                int key = reader.ReadInt32();
                FunctionIDs[key] = reader.ReadUndertaleString();
            }

            Moments = reader.ReadUndertaleObject <UndertaleSimpleList <Keyframe <Moment> > >();
        }
        public void Unserialize(UndertaleReader reader, uint endPosition)
        {
            uint count = reader.ReadUInt32();

            Clear();
            List <uint> pointers = new List <uint>();

            for (uint i = 0; i < count; i++)
            {
                try
                {
                    uint ptr = reader.ReadUInt32();
                    pointers.Add(ptr);
                    Add(reader.GetUndertaleObjectAtAddress <T>(ptr));
                }
                catch (UndertaleSerializationException e)
                {
                    throw new UndertaleSerializationException(e.Message + "\nwhile reading pointer to item " + (i + 1) + " of " + count + " in a list of " + typeof(T).FullName, e);
                }
            }
            if (Count > 0 && reader.Position != reader.GetAddressForUndertaleObject(this[0]))
            {
                int skip = (int)reader.GetAddressForUndertaleObject(this[0]) - (int)reader.Position;
                if (skip > 0)
                {
                    //Console.WriteLine("Skip " + skip + " bytes of blobs");
                    reader.Position = reader.Position + (uint)skip;
                }
                else
                {
                    throw new IOException("First list item starts inside the pointer list?!?!");
                }
            }
            for (uint i = 0; i < count; i++)
            {
                try
                {
                    (this[(int)i] as PrePaddedObject)?.UnserializePrePadding(reader);
                    if ((i + 1) < count)
                    {
                        reader.ReadUndertaleObject(this[(int)i], (int)(pointers[(int)i + 1] - reader.Position));
                    }
                    else
                    {
                        reader.ReadUndertaleObject(this[(int)i], (int)(endPosition - reader.Position));
                    }
                    if (i != count - 1)
                    {
                        (this[(int)i] as PaddedObject)?.UnserializePadding(reader);
                    }
                }
                catch (UndertaleSerializationException e)
                {
                    throw new UndertaleSerializationException(e.Message + "\nwhile reading item " + (i + 1) + " of " + count + " in a list of " + typeof(T).FullName, e);
                }
            }
        }
예제 #7
0
 public void Unserialize(UndertaleReader reader, bool readLength = true)
 {
     _PointerLocation = reader.Position;
     _Position = reader.ReadUInt32();
     if (readLength)
         _Length = reader.ReadUInt32();
     
     IsNull = (_Position == 0x00000000u);
 }
 public void Unserialize(UndertaleReader reader)
 {
     Scaled = reader.ReadUInt32();
     if (reader.undertaleData.GeneralInfo.Major >= 2)
     {
         GeneratedMips = reader.ReadUInt32();
     }
     TextureData = reader.ReadUndertaleObjectPointer <TexData>();
 }
 public void Unserialize(UndertaleReader reader)
 {
     Name      = reader.ReadUndertaleString();
     ID        = reader.ReadUInt32();
     Kind      = reader.ReadUInt32();
     RetType   = (UndertaleExtensionVarType)reader.ReadUInt32();
     ExtName   = reader.ReadUndertaleString();
     Arguments = reader.ReadUndertaleObject <UndertaleSimpleList <UndertaleExtensionFunctionArg> >();
 }
예제 #10
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            if (reader.undertaleData.GeneralInfo?.BytecodeVersion >= 17)
            {
                /* This code performs four checks to identify GM2022.2.
                 * First, as you've seen, is the bytecode version.
                 * Second, we assume it is. If there are no Glyphs, we are vindicated by the impossibility of null values there.
                 * Third, we check that the Glyph Length is less than the chunk length. If it's going outside the chunk, that means
                 * that the length was misinterpreted.
                 * Fourth, in case of a terrible fluke causing this to appear valid erroneously, we verify that each pointer leads into the next.
                 * And if someone builds their game so the first pointer is absolutely valid length data and the next font is valid glyph data-
                 * screw it, call Jacky720 when someone constructs that and you want to mod it.
                 * Maybe try..catch on the whole shebang?
                 */
                uint positionToReturn = reader.Position;
                if (reader.ReadUInt32() > 0) // Font count
                {
                    uint firstFontPointer = reader.ReadUInt32();
                    reader.Position = firstFontPointer + 48; // There are 48 bytes of existing metadata.
                    uint glyphsLength = reader.ReadUInt32();
                    reader.undertaleData.GMS2022_2 = true;
                    if ((glyphsLength * 4) > this.Length)
                    {
                        reader.undertaleData.GMS2022_2 = false;
                    }
                    else if (glyphsLength != 0)
                    {
                        List <uint> glyphPointers = new List <uint>();
                        for (uint i = 0; i < glyphsLength; i++)
                        {
                            glyphPointers.Add(reader.ReadUInt32());
                        }
                        foreach (uint pointer in glyphPointers)
                        {
                            if (reader.Position != pointer)
                            {
                                reader.undertaleData.GMS2022_2 = false;
                                break;
                            }

                            reader.Position += 14;
                            ushort kerningLength = reader.ReadUInt16();
                            reader.Position += (uint)4 * kerningLength;  // combining read/write would apparently break
                        }
                    }
                }
                reader.Position = positionToReturn;
            }

            base.UnserializeChunk(reader);

            Padding = reader.ReadBytes(512);
        }
예제 #11
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            uint startPosition = reader.Position;

            InstanceVarCount      = reader.ReadUInt32();
            InstanceVarCountAgain = reader.ReadUInt32();
            MaxLocalVarCount      = reader.ReadUInt32();
            List.Clear();
            while (reader.Position + 20 <= startPosition + Length)
            {
                List.Add(reader.ReadUndertaleObject <UndertaleVariable>());
            }
        }
예제 #12
0
        public void Unserialize(UndertaleReader reader)
        {
            Clear();
            uint count = reader.ReadUInt32();

            Util.DebugUtil.Assert(count % 2 == 0);
            count /= 2;
            for (int i = 0; i < count; i++)
            {
                Add(new DebugInfoPair()
                {
                    BytecodeOffset = reader.ReadUInt32(), SourceCodeOffset = reader.ReadUInt32()
                });
            }
        }
예제 #13
0
    /// <inheritdoc />
    public void Unserialize(UndertaleReader reader)
    {
        uint len = reader.ReadUInt32();

        Data = reader.ReadBytes((int)len);
        Util.DebugUtil.Assert(Data.Length == len);
    }
예제 #14
0
        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);
                }
            }
        }
예제 #15
0
 public void Unserialize(UndertaleReader reader)
 {
     Name        = reader.ReadUndertaleString();
     Occurrences = reader.ReadUInt32();
     if (Occurrences > 0)
     {
         if (reader.GMS2_3)
         {
             GMS2_3       = true;
             FirstAddress = reader.GetUndertaleObjectAtAddress <UndertaleInstruction>(reader.ReadUInt32() - 4);
         }
         else
         {
             FirstAddress = reader.ReadUndertaleObjectPointer <UndertaleInstruction>();
         }
         UndertaleInstruction.Reference <UndertaleFunction> .ParseReferenceChain(reader, this);
     }
     else
     {
         if (reader.ReadInt32() != -1)
         {
             throw new Exception("Function with no occurrences, but still has a first occurrence address");
         }
         FirstAddress = null;
     }
 }
예제 #16
0
        public void Unserialize(UndertaleReader reader)
        {
            Name        = reader.ReadUndertaleString();
            Occurrences = reader.ReadUInt32();
            if (Occurrences > 0)
            {
                FirstAddress = reader.ReadUndertaleObjectPointer <UndertaleInstruction>();

                // Parse the chain of references
                UndertaleInstruction.Reference <UndertaleFunction> reference = null;
                uint addr = reader.GetAddressForUndertaleObject(FirstAddress);
                for (int i = 0; i < Occurrences; i++)
                {
                    reference = reader.GetUndertaleObjectAtAddress <UndertaleInstruction>(addr).GetReference <UndertaleFunction>();
                    if (reference == null)
                    {
                        throw new IOException("Failed to find reference at " + addr);
                    }
                    reference.Target = this;
                    addr            += (uint)reference.NextOccurrenceOffset;
                }
                UnknownChainEndingValue = reference.NextOccurrenceOffset;
            }
            else
            {
                if (reader.ReadInt32() != -1)
                {
                    throw new Exception("Function with no occurrences, but still has a first occurrence address");
                }
                FirstAddress = null;
            }
        }
예제 #17
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            if (reader.undertaleData.GeneralInfo.Major < 2)
            {
                throw new InvalidOperationException();
            }

            // Apparently SEQN can be empty
            if (Length == 0)
            {
                return;
            }

            // Padding
            while (reader.Position % 4 != 0)
            {
                if (reader.ReadByte() != 0)
                {
                    throw new IOException("Padding error!");
                }
            }

            uint version = reader.ReadUInt32();

            if (version != 1)
            {
                throw new IOException("Expected SEQN version 1, got " + version.ToString());
            }

            base.UnserializeChunk(reader);
        }
예제 #18
0
        public void Unserialize(UndertaleReader reader)
        {
            Name = reader.ReadUndertaleString();

            int momentCount = reader.ReadInt32();

            // Read the time points for each moment
            uint[] timePoints          = new uint[momentCount];
            int[]  unnecessaryPointers = new int[momentCount];
            for (int i = 0; i < momentCount; i++)
            {
                timePoints[i]          = reader.ReadUInt32();
                unnecessaryPointers[i] = reader.ReadInt32();
            }

            // Read the actions for each moment
            for (int i = 0; i < momentCount; i++)
            {
                if (reader.Position != unnecessaryPointers[i])
                {
                    throw new UndertaleSerializationException("Invalid action list pointer");
                }

                // Read action list and assign time point (put into list)
                var timeEvent = reader.ReadUndertaleObject <UndertalePointerList <UndertaleGameObject.EventAction> >();
                Moments.Add(new UndertaleTimelineMoment(timePoints[i], timeEvent));
            }
        }
예제 #19
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);
            }
        }
 public void Unserialize(UndertaleReader reader)
 {
     Filename      = reader.ReadUndertaleString();
     CleanupScript = reader.ReadUndertaleString();
     InitScript    = reader.ReadUndertaleString();
     Kind          = (UndertaleExtensionKind)reader.ReadUInt32();
     Functions     = reader.ReadUndertaleObject <UndertalePointerList <UndertaleExtensionFunction> >();
 }
예제 #21
0
 public void Unserialize(UndertaleReader reader)
 {
     Name      = reader.ReadUndertaleString();
     IsSmooth  = reader.ReadBoolean();
     IsClosed  = reader.ReadBoolean();
     Precision = reader.ReadUInt32();
     Points    = reader.ReadUndertaleObject <UndertaleSimpleList <PathPoint> >();
 }
예제 #22
0
 public override void Unserialize(UndertaleReader reader)
 {
     base.Unserialize(reader);
     if (reader.ReadUInt32() != 0)
     {
         throw new IOException("Expected 0 in Audio keyframe");
     }
     Mode = reader.ReadInt32();
 }
 /// <summary>
 /// Deserializes from a specified <see cref="UndertaleReader"/> to the current data file.
 /// </summary>
 /// <param name="reader">Where to deserialize from.</param>
 /// <param name="includeName">Whether to include <see cref="Name"/> in the deserialization.</param>
 public void Unserialize(UndertaleReader reader, bool includeName)
 {
     if (includeName)
     {
         Name = reader.ReadUndertaleString();
     }
     GraphType = (GraphTypeEnum)reader.ReadUInt32();
     Channels  = reader.ReadUndertaleObject <UndertaleSimpleList <Channel> >();
 }
예제 #24
0
        public void Unserialize(UndertaleReader reader)
        {
            Unknown1      = reader.ReadUInt32();
            LanguageCount = reader.ReadUInt32();
            EntryCount    = reader.ReadUInt32();

            // Read the identifiers for each entry
            for (int i = 0; i < EntryCount; i++)
            {
                EntryIDs.Add(reader.ReadUndertaleString());
            }

            // Read the data for each language
            for (int i = 0; i < LanguageCount; i++)
            {
                LanguageData ld = new LanguageData();
                ld.Unserialize(reader, EntryCount);
                Languages.Add(ld);
            }
        }
예제 #25
0
 internal override void UnserializeChunk(UndertaleReader reader)
 {
     if (reader.undertaleData.GeneralInfo.Major < 2)
     {
         throw new InvalidOperationException();
     }
     if (reader.ReadUInt32() != 1)
     {
         throw new IOException("Expected TGIN version 1");
     }
     base.UnserializeChunk(reader);
 }
예제 #26
0
        public void Unserialize(UndertaleReader reader)
        {
            uint count = reader.ReadUInt32();

            Name = reader.ReadUndertaleString();
            Locals.Clear();
            for (uint i = 0; i < count; i++)
            {
                Locals.Add(reader.ReadUndertaleObject <LocalVar>());
            }
            Debug.Assert(Locals.Count == count);
        }
예제 #27
0
 internal override void UnserializeChunk(UndertaleReader reader)
 {
     if (reader.undertaleData.GeneralInfo.Major < 2)
     {
         throw new InvalidOperationException();
     }
     if (reader.ReadUInt32() != 1)
     {
         throw new Exception("Should be hardcoded 1");
     }
     base.UnserializeChunk(reader);
 }
예제 #28
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            if (Length == 0)
            {
                throw new Exception("This game uses YYC (YoYo Compiler). This is currently not supported.");
            }
            if (reader.undertaleData.UnsupportedBytecodeVersion)
            {
                return;
            }
            uint startPosition = reader.Position;

            InstanceVarCount      = reader.ReadUInt32();
            InstanceVarCountAgain = reader.ReadUInt32();
            MaxLocalVarCount      = reader.ReadUInt32();
            List.Clear();
            while (reader.Position + 20 <= startPosition + Length)
            {
                List.Add(reader.ReadUndertaleObject <UndertaleVariable>());
            }
        }
예제 #29
0
 public void Unserialize(UndertaleReader reader)
 {
     Unknown1    = reader.ReadUInt32();
     Unknown2    = reader.ReadUInt32();
     Info        = (OptionsFlags)reader.ReadUInt64();
     Scale       = reader.ReadInt32();
     WindowColor = reader.ReadUInt32();
     ColorDepth  = reader.ReadUInt32();
     Resolution  = reader.ReadUInt32();
     Frequency   = reader.ReadUInt32();
     VertexSync  = reader.ReadUInt32();
     Priority    = reader.ReadUInt32();
     BackImage   = reader.ReadUndertaleObject <UndertaleSprite.TextureEntry>();
     FrontImage  = reader.ReadUndertaleObject <UndertaleSprite.TextureEntry>();
     LoadImage   = reader.ReadUndertaleObject <UndertaleSprite.TextureEntry>();
     LoadAlpha   = reader.ReadUInt32();
     Constants   = reader.ReadUndertaleObject <UndertaleSimpleList <Constant> >();
 }
예제 #30
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            uint count = reader.ReadUInt32();

            for (int i = 0; i < count; i++)
            {
                Align &= (reader.ReadUInt32() % Alignment == 0);
            }
            for (int i = 0; i < count; i++)
            {
                if (Align)
                {
                    while (reader.Position % Alignment != 0)
                    {
                        if (reader.ReadByte() != 0)
                        {
                            throw new IOException("AlignUpdatedListChunk padding error");
                        }
                    }
                }
                List.Add(reader.ReadUndertaleObject <T>());
            }
        }