Ejemplo n.º 1
0
 public virtual void Unserialize(UndertaleReader reader)
 {
     if (reader.ReadBoolean())
     {
         // The curve data is embedded in this sequence, right here
         IsCurveEmbedded = true;
         if (reader.ReadInt32() != -1)
         {
             throw new IOException("Expected -1");
         }
         EmbeddedAnimCurve = reader.ReadUndertaleObject <UndertaleAnimationCurve>();
     }
     else
     {
         // The curve data is an asset in the project
         IsCurveEmbedded = false;
         AssetAnimCurve  = new UndertaleResourceById <UndertaleAnimationCurve, UndertaleChunkACRV>();
         AssetAnimCurve.Unserialize(reader);
     }
 }
Ejemplo n.º 2
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());
            }
        }
Ejemplo n.º 3
0
        public void Serialize(UndertaleWriter writer)
        {
            switch (GetInstructionType(Kind))
            {
            case InstructionType.SingleTypeInstruction:
            case InstructionType.DoubleTypeInstruction:
            case InstructionType.ComparisonInstruction:
            {
                writer.Write(DupExtra);
                writer.Write((byte)ComparisonKind);
                byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                writer.Write(TypePair);
                writer.Write((byte)Kind);
            }
            break;

            case InstructionType.GotoInstruction:
            {
                // TODO: see unserialize
                // TODO: why the hell is there exactly ONE number that was NOT encoded in a weird way? If you just rewrite the file with the 'fix' it differs one one byte
                uint JumpOffsetFixed = (uint)JumpOffset;
                JumpOffsetFixed &= ~0xFF800000;
                if (JumpOffsetIsWeird)
                {
                    JumpOffsetFixed |= 0x00800000;
                }
                writer.WriteInt24((int)JumpOffsetFixed);

                writer.Write((byte)Kind);
            }
            break;

            case InstructionType.PopInstruction:
            {
                writer.Write((short)TypeInst);
                byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                writer.Write(TypePair);
                writer.Write((byte)Kind);
                writer.WriteUndertaleObject(Destination);
            }
            break;

            case InstructionType.PushInstruction:
            {
                if (Type1 == DataType.Int16)
                {
                    Debug.Assert(Value.GetType() == typeof(short));
                    writer.Write((short)Value);
                }
                else if (Type1 == DataType.Variable)
                {
                    writer.Write((short)TypeInst);
                }
                else
                {
                    writer.Write((short)0);
                }
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
                switch (Type1)
                {
                case DataType.Double:
                    Debug.Assert(Value.GetType() == typeof(double));
                    writer.Write((double)Value);
                    break;

                case DataType.Float:
                    Debug.Assert(Value.GetType() == typeof(float));
                    writer.Write((float)Value);
                    break;

                case DataType.Int32:
                    Debug.Assert(Value.GetType() == typeof(int));
                    writer.Write((int)Value);
                    break;

                case DataType.Int64:
                    Debug.Assert(Value.GetType() == typeof(long));
                    writer.Write((long)Value);
                    break;

                case DataType.Boolean:
                    Debug.Assert(Value.GetType() == typeof(bool));
                    writer.Write((bool)Value ? 1 : 0);
                    break;

                case DataType.Variable:
                    Debug.Assert(Value.GetType() == typeof(Reference <UndertaleVariable>));
                    writer.WriteUndertaleObject((Reference <UndertaleVariable>)Value);
                    break;

                case DataType.String:
                    Debug.Assert(Value.GetType() == typeof(UndertaleResourceById <UndertaleString>));
                    UndertaleResourceById <UndertaleString> str = (UndertaleResourceById <UndertaleString>)Value;
                    writer.Write(str.Serialize(writer));
                    break;

                case DataType.Int16:
                    break;
                }
            }
            break;

            case InstructionType.CallInstruction:
            {
                writer.Write(ArgumentsCount);
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
                writer.WriteUndertaleObject(Function);
            }
            break;

            case InstructionType.BreakInstruction:
            {
                Debug.Assert(Value.GetType() == typeof(short));
                writer.Write((short)Value);
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
            }
            break;

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