예제 #1
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            base.UnserializeChunk(reader);

            // padding
            while (reader.Position % 0x80 != 0)
            {
                if (reader.ReadByte() != 0)
                {
                    throw new IOException("Padding error in STRG");
                }
            }
        }
예제 #2
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            base.UnserializeChunk(reader);

            // texture blobs
            foreach (UndertaleEmbeddedTexture obj in List)
            {
                obj.UnserializeBlob(reader);
            }

            // padding
            reader.Position += (4 - (reader.Position % 4)) % 4 - 1;
            if (reader.ReadByte() != 0)
            {
                throw new IOException("Padding error!");
            }
        }
예제 #3
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            base.UnserializeChunk(reader);

            // texture blobs
            foreach (UndertaleEmbeddedTexture obj in List)
            {
                obj.UnserializeBlob(reader);
                obj.Name = new UndertaleString("Texture " + List.IndexOf(obj).ToString());
            }

            // padding
            while (reader.Position % 4 != 0)
            {
                if (reader.ReadByte() != 0)
                {
                    throw new IOException("Padding error!");
                }
            }
        }
예제 #4
0
        internal override void UnserializeChunk(UndertaleReader reader)
        {
            if (reader.undertaleData.GeneralInfo.Major < 2)
            {
                throw new InvalidOperationException();
            }

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

            if (reader.ReadUInt32() != 1)
            {
                throw new IOException("Expected TAGS version 1");
            }

            base.UnserializeChunk(reader);
        }
예제 #5
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>());
            }
        }
예제 #6
0
 public void Unserialize(UndertaleReader reader)
 {
     DisableDebugger = reader.ReadByte() != 0 ? true : false;
     BytecodeVersion = reader.ReadByte();
     Unknown         = reader.ReadUInt16();
     Filename        = reader.ReadUndertaleString();
     Config          = reader.ReadUndertaleString();
     LastObj         = reader.ReadUInt32();
     LastTile        = reader.ReadUInt32();
     GameID          = reader.ReadUInt32();
     byte[] GuidData = reader.ReadBytes(16);
     DirectPlayGuid          = new Guid(GuidData);
     Name                    = reader.ReadUndertaleString();
     Major                   = reader.ReadUInt32();
     Minor                   = reader.ReadUInt32();
     Release                 = reader.ReadUInt32();
     Build                   = reader.ReadUInt32();
     DefaultWindowWidth      = reader.ReadUInt32();
     DefaultWindowHeight     = reader.ReadUInt32();
     Info                    = (InfoFlags)reader.ReadUInt32();
     LicenseMD5              = reader.ReadBytes(16);
     LicenseCRC32            = reader.ReadUInt32();
     Timestamp               = reader.ReadUInt64();
     DisplayName             = reader.ReadUndertaleString();
     ActiveTargets           = reader.ReadUInt64();
     FunctionClassifications = (FunctionClassification)reader.ReadUInt64();
     SteamAppID              = reader.ReadInt32();
     DebuggerPort            = reader.ReadUInt32();
     RoomOrder               = reader.ReadUndertaleObject <UndertaleSimpleResourcesList <UndertaleRoom, UndertaleChunkROOM> >();
     if (Major >= 2)
     {
         // Begin parsing random UID, and verify it based on original algorithm
         GMS2RandomUID = new List <long>();
         Random random      = new Random((int)(Timestamp & 4294967295L));
         long   firstRandom = (long)random.Next() << 32 | (long)random.Next();
         if (reader.ReadInt64() != firstRandom)
         {
             //throw new IOException("Unexpected random UID");
         }
         long  infoNumber = (long)(Timestamp - 1000);
         ulong temp       = (ulong)infoNumber;
         temp = ((temp << 56 & 18374686479671623680UL) | (temp >> 8 & 71776119061217280UL) |
                 (temp << 32 & 280375465082880UL) | (temp >> 16 & 1095216660480UL) | (temp << 8 & 4278190080UL) |
                 (temp >> 24 & 16711680UL) | (temp >> 16 & 65280UL) | (temp >> 32 & 255UL));
         infoNumber  = (long)temp;
         infoNumber ^= firstRandom;
         infoNumber  = ~infoNumber;
         infoNumber ^= ((long)GameID << 32 | (long)GameID);
         infoNumber ^= ((long)(DefaultWindowWidth + (int)Info) << 48 |
                        (long)(DefaultWindowHeight + (int)Info) << 32 |
                        (long)(DefaultWindowHeight + (int)Info) << 16 |
                        (long)(DefaultWindowWidth + (int)Info));
         infoNumber ^= BytecodeVersion;
         int infoLocation = (int)(Math.Abs((int)(Timestamp & 65535L) / 7 + (GameID - DefaultWindowWidth) + RoomOrder.Count) % 4);
         for (int i = 0; i < 4; i++)
         {
             if (i == infoLocation)
             {
                 long curr = reader.ReadInt64();
                 curr = infoNumber;
                 GMS2RandomUID.Add(curr);
             }
             else
             {
                 int first  = reader.ReadInt32();
                 int second = reader.ReadInt32();
                 first  = random.Next();
                 second = random.Next();
                 GMS2RandomUID.Add(((long)first << 32) | (long)second);
             }
         }
         GMS2FPS             = reader.ReadSingle();
         GMS2AllowStatistics = reader.ReadBoolean();
         GMS2GameGUID        = reader.ReadBytes(16);
     }
     reader.undertaleData.UnsupportedBytecodeVersion = BytecodeVersion < 14 || BytecodeVersion > 17;
     reader.Bytecode14OrLower = BytecodeVersion <= 14;
 }
예제 #7
0
        public static UndertaleChunk Unserialize(UndertaleReader reader)
        {
            string name = "(unknown)";

            try
            {
                name = 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 != reader.LastChunkName)
                {
                    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))
                    {
                        int  e   = reader.undertaleData.PaddingAlignException;
                        uint pad = (e == -1 ? 16 : (uint)e);
                        while (reader.Position % pad != 0)
                        {
                            if (reader.ReadByte() != 0)
                            {
                                reader.Position -= 1;
                                if (reader.Position % 4 == 0)
                                {
                                    reader.undertaleData.PaddingAlignException = 4;
                                }
                                else
                                {
                                    reader.undertaleData.PaddingAlignException = 1;
                                }
                                break;
                            }
                        }
                    }
                }

                lenReader.ToHere();

                return(chunk);
            }
            catch (UndertaleSerializationException e)
            {
                throw new UndertaleSerializationException(e.Message + " in chunk " + name, e);
            }
            catch (Exception e)
            {
                throw new UndertaleSerializationException(e.Message + "\nat " + reader.Position.ToString("X8") + " while reading chunk " + name, e);
            }
        }
예제 #8
0
        public void Unserialize(UndertaleReader reader)
        {
            uint instructionStartAddress = reader.Position;

            reader.ReadByte(); reader.ReadByte(); reader.ReadByte(); // skip for now, we'll read them later
            Kind            = (Opcode)reader.ReadByte();
            reader.Position = instructionStartAddress;
            switch (GetInstructionType(Kind))
            {
            case InstructionType.SingleTypeInstruction:
            case InstructionType.DoubleTypeInstruction:
            case InstructionType.ComparisonInstruction:
            {
                DupExtra = reader.ReadByte();
                if (DupExtra != 0 && Kind != Opcode.Dup)
                {
                    throw new IOException("Invalid padding in " + Kind.ToString().ToUpper());
                }
                ComparisonKind = (ComparisonType)reader.ReadByte();
                if ((Kind == Opcode.Cmp) != ((byte)ComparisonKind != 0))
                {
                    throw new IOException("Got unexpected comparison type in " + Kind.ToString().ToUpper() + " (should be only in CMP)");
                }
                byte TypePair = reader.ReadByte();
                Type1 = (DataType)(TypePair & 0xf);
                Type2 = (DataType)(TypePair >> 4);
                if (GetInstructionType(Kind) == InstructionType.SingleTypeInstruction && Type2 != (byte)0)
                {
                    throw new IOException("Second type should be 0 in " + Kind.ToString().ToUpper());
                }
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
            }
            break;

            case InstructionType.GotoInstruction:
            {
                uint v = reader.ReadUInt24();

                // TODO: This is SO WRONG that I don't even believe it. Is that Int24 or Int23?!?!
                uint r = v & 0x003FFFFF;

                if ((v & 0x00C00000) != 0)
                {
                    r |= 0xFFC00000;
                }

                JumpOffset        = (int)r;
                JumpOffsetIsWeird = (v & 0x00800000) != 0;

                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
            }
            break;

            case InstructionType.PopInstruction:
            {
                TypeInst = (InstanceType)reader.ReadInt16();
                byte TypePair = reader.ReadByte();
                Type1 = (DataType)(TypePair & 0xf);
                Type2 = (DataType)(TypePair >> 4);
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
                Destination = reader.ReadUndertaleObject <Reference <UndertaleVariable> >();
            }
            break;

            case InstructionType.PushInstruction:
            {
                short val = reader.ReadInt16();
                Type1 = (DataType)reader.ReadByte();
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
                switch (Type1)
                {
                case DataType.Double:
                    Value = reader.ReadDouble();
                    break;

                case DataType.Float:
                    Value = reader.ReadSingle();
                    break;

                case DataType.Int32:
                    Value = reader.ReadInt32();
                    break;

                case DataType.Int64:
                    Value = reader.ReadInt64();
                    break;

                case DataType.Boolean:
                    Value = (reader.ReadUInt32() == 1);             // TODO: double check
                    break;

                case DataType.Variable:
                    TypeInst = (InstanceType)val;
                    Value    = reader.ReadUndertaleObject <Reference <UndertaleVariable> >();
                    break;

                case DataType.String:
                    UndertaleResourceById <UndertaleString> str = new UndertaleResourceById <UndertaleString>("STRG");
                    str.Unserialize(reader, reader.ReadInt32());
                    Value = str;
                    break;

                case DataType.Int16:
                    Value = val;
                    break;
                }
            }
            break;

            case InstructionType.CallInstruction:
            {
                ArgumentsCount = reader.ReadUInt16();
                Type1          = (DataType)reader.ReadByte();
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
                Function = reader.ReadUndertaleObject <Reference <UndertaleFunction> >();
            }
            break;

            case InstructionType.BreakInstruction:
            {
                Value = reader.ReadInt16();
                Type1 = (DataType)reader.ReadByte();
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
            }
            break;

            default:
                throw new IOException("Unknown opcode " + Kind.ToString().ToUpper());
            }
        }
예제 #9
0
 public void Unserialize(UndertaleReader reader)
 {
     NextOccurrenceOffset = reader.ReadInt24();
     Type = (VariableType)reader.ReadByte();
 }
        public void Unserialize(UndertaleReader reader)
        {
            uint instructionStartAddress = reader.Position;

            reader.ReadByte(); reader.ReadByte(); reader.ReadByte(); // skip for now, we'll read them later
            Kind            = (Opcode)reader.ReadByte();
            reader.Position = instructionStartAddress;
            switch (GetInstructionType(Kind))
            {
            case InstructionType.SingleTypeInstruction:
            case InstructionType.DoubleTypeInstruction:
            case InstructionType.ComparisonInstruction:
            {
                DupExtra = reader.ReadByte();
                if (DupExtra != 0 && Kind != Opcode.Dup)
                {
                    throw new IOException("Invalid padding in " + Kind.ToString().ToUpper());
                }
                ComparisonKind = (ComparisonType)reader.ReadByte();
                if ((Kind == Opcode.Cmp) != ((byte)ComparisonKind != 0))
                {
                    throw new IOException("Got unexpected comparison type in " + Kind.ToString().ToUpper() + " (should be only in CMP)");
                }
                byte TypePair = reader.ReadByte();
                Type1 = (DataType)(TypePair & 0xf);
                Type2 = (DataType)(TypePair >> 4);
                if (GetInstructionType(Kind) == InstructionType.SingleTypeInstruction && Type2 != (byte)0)
                {
                    throw new IOException("Second type should be 0 in " + Kind.ToString().ToUpper());
                }
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
            }
            break;

            case InstructionType.GotoInstruction:
            {
                uint v = reader.ReadUInt24();

                JumpOffsetPopenvExitMagic = (v & 0x800000) != 0;

                // The rest is int23 signed value, so make sure
                uint r = v & 0x003FFFFF;
                if (JumpOffsetPopenvExitMagic && v != 0xF00000)
                {
                    throw new Exception("Popenv magic doesn't work, call issue #90 again");
                }
                else
                {
                    if ((v & 0x00C00000) != 0)
                    {
                        r |= 0xFFC00000;
                    }
                    JumpOffset = (int)r;
                }

                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
            }
            break;

            case InstructionType.PopInstruction:
            {
                TypeInst = (InstanceType)reader.ReadInt16();
                byte TypePair = reader.ReadByte();
                Type1 = (DataType)(TypePair & 0xf);
                Type2 = (DataType)(TypePair >> 4);
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
                if (Type1 == DataType.Int16)
                {
                    // Special scenario - the swap instruction
                    // TODO: Figure out the proper syntax, see #129
                    SwapExtra = (ushort)TypeInst;
                    TypeInst  = 0;
                }
                else
                {
                    Destination = reader.ReadUndertaleObject <Reference <UndertaleVariable> >();
                }
            }
            break;

            case InstructionType.PushInstruction:
            {
                short val = reader.ReadInt16();
                Type1 = (DataType)reader.ReadByte();
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
                switch (Type1)
                {
                case DataType.Double:
                    Value = reader.ReadDouble();
                    break;

                case DataType.Float:
                    Value = reader.ReadSingle();
                    break;

                case DataType.Int32:
                    Value = reader.ReadInt32();
                    break;

                case DataType.Int64:
                    Value = reader.ReadInt64();
                    break;

                case DataType.Boolean:
                    Value = (reader.ReadUInt32() == 1);             // TODO: double check
                    break;

                case DataType.Variable:
                    TypeInst = (InstanceType)val;
                    Value    = reader.ReadUndertaleObject <Reference <UndertaleVariable> >();
                    break;

                case DataType.String:
                    Value = reader.ReadUndertaleObject <UndertaleResourceById <UndertaleString, UndertaleChunkSTRG> >();
                    break;

                case DataType.Int16:
                    Value = val;
                    break;
                }
            }
            break;

            case InstructionType.CallInstruction:
            {
                ArgumentsCount = reader.ReadUInt16();
                Type1          = (DataType)reader.ReadByte();
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
                Function = reader.ReadUndertaleObject <Reference <UndertaleFunction> >();
            }
            break;

            case InstructionType.BreakInstruction:
            {
                Value = reader.ReadInt16();
                Type1 = (DataType)reader.ReadByte();
                if (reader.ReadByte() != (byte)Kind)
                {
                    throw new Exception("really shouldn't happen");
                }
            }
            break;

            default:
                throw new IOException("Unknown opcode " + Kind.ToString().ToUpper());
            }
        }