Exemplo n.º 1
0
            /// <summary>
            ///  Serialize the reference chain. This functions assumes that the Reference objects have already been written to file (i.e. the CODE chunk was before FUNC/VARI,
            ///  which is normally always the case)
            /// </summary>
            public static void SerializeReferenceChain(UndertaleWriter writer, IList <UndertaleCode> codeList, IList <T> varList)
            {
                Dictionary <T, List <UndertaleInstruction> > references = CollectReferences(codeList);
                uint pos = writer.Position;

                foreach (T var in varList)
                {
                    var.Occurrences = references.ContainsKey(var) ? (uint)references[var].Count : 0;
                    if (var.Occurrences > 0)
                    {
                        var.FirstAddress = references[var][0];
                        for (int i = 0; i < references[var].Count; i++)
                        {
                            uint thisAddr = writer.GetAddressForUndertaleObject(references[var][i]);
                            int  addrDiff;
                            if (i < references[var].Count - 1)
                            {
                                uint nextAddr = writer.GetAddressForUndertaleObject(references[var][i + 1]);
                                addrDiff = (int)(nextAddr - thisAddr);
                            }
                            else
                            {
                                addrDiff = var.UnknownChainEndingValue;
                            }
                            writer.Position = writer.GetAddressForUndertaleObject(references[var][i].GetReference <T>());
                            writer.WriteInt24(addrDiff);
                        }
                    }
                    else
                    {
                        var.FirstAddress = null;
                    }
                }
                writer.Position = pos;
            }
Exemplo n.º 2
0
        internal override void SerializeChunk(UndertaleWriter writer)
        {
            // Update references
            Dictionary <UndertaleVariable, List <UndertaleInstruction> > references = UndertaleInstruction.Reference <UndertaleVariable> .CollectReferences(writer.undertaleData.Code);

            uint pos = writer.Position;

            foreach (UndertaleVariable var in List)
            {
                var.Occurrences = references.ContainsKey(var) ? (uint)references[var].Count : 0;
                if (var.Occurrences > 0)
                {
                    var.FirstAddress = references[var][0];
                    for (int i = 0; i < references[var].Count; i++)
                    {
                        uint thisAddr = writer.GetAddressForUndertaleObject(references[var][i]);
                        int  addrDiff;
                        if (i < references[var].Count - 1)
                        {
                            uint nextAddr = writer.GetAddressForUndertaleObject(references[var][i + 1]);
                            addrDiff = (int)(nextAddr - thisAddr);
                        }
                        else
                        {
                            addrDiff = var.UnknownChainEndingValue;
                        }
                        // references[var][i].GetReference<UndertaleVariable>().NextOccurrenceOffset = addrDiff;

                        /*if (addrDiff != references[var][i].GetReference<UndertaleVariable>().NextOccurrenceOffset)
                         *  Debug.WriteLine("VARI Changes at " + writer.GetAddressForUndertaleObject(references[var][i].GetReference<UndertaleVariable>()) + ": " + references[var][i].GetReference<UndertaleVariable>().NextOccurrenceOffset + " to " + addrDiff);*/
                        writer.Position = writer.GetAddressForUndertaleObject(references[var][i].GetReference <UndertaleVariable>());
                        writer.WriteInt24(addrDiff);
                    }
                }
                else
                {
                    var.FirstAddress = null;
                }
            }
            writer.Position = pos;

            writer.Write(InstanceVarCount);
            writer.Write(InstanceVarCountAgain);
            writer.Write(MaxLocalVarCount);
            foreach (UndertaleVariable var in List)
            {
                writer.WriteUndertaleObject(var);
            }
        }
Exemplo n.º 3
0
        internal override void SerializeChunk(UndertaleWriter writer)
        {
            // Update references
            Dictionary <UndertaleFunction, List <UndertaleInstruction> > references = UndertaleInstruction.Reference <UndertaleFunction> .CollectReferences(writer.undertaleData.Code);

            uint pos = writer.Position;

            // TODO: don't repeat the code from VARI, I spent 6 hours debugging the fact that I didn't copy one change from 0 to 1 between them :P
            foreach (UndertaleFunction var in Functions)
            {
                var.Occurrences = references.ContainsKey(var) ? (uint)references[var].Count : 0;
                if (var.Occurrences > 0)
                {
                    var.FirstAddress = references[var][0];
                    for (int i = 0; i < references[var].Count; i++)
                    {
                        uint thisAddr = writer.GetAddressForUndertaleObject(references[var][i]);
                        int  addrDiff;
                        if (i < references[var].Count - 1)
                        {
                            uint nextAddr = writer.GetAddressForUndertaleObject(references[var][i + 1]);
                            addrDiff = (int)(nextAddr - thisAddr);
                        }
                        else
                        {
                            addrDiff = var.UnknownChainEndingValue;
                        }
                        // references[var][i].GetReference<UndertaleFunction>().NextOccurrenceOffset = addrDiff;

                        /*if (addrDiff != references[var][i].GetReference<UndertaleFunction>().NextOccurrenceOffset)
                         *  Debug.WriteLine("FUNC Changes at " + writer.GetAddressForUndertaleObject(references[var][i].GetReference<UndertaleFunction>()) + ": " + references[var][i].GetReference<UndertaleFunction>().NextOccurrenceOffset + " to " + addrDiff);*/
                        writer.Position = writer.GetAddressForUndertaleObject(references[var][i].GetReference <UndertaleFunction>());
                        writer.WriteInt24(addrDiff);
                    }
                }
                else
                {
                    var.FirstAddress = null;
                }
            }
            writer.Position = pos;

            writer.WriteUndertaleObject(Functions);
            writer.WriteUndertaleObject(CodeLocals);
        }
Exemplo n.º 4
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());
            }
        }
Exemplo n.º 5
0
 public void Serialize(UndertaleWriter writer)
 {
     NextOccurrenceOffset = 0xdead;
     writer.WriteInt24(NextOccurrenceOffset);
     writer.Write((byte)Type);
 }
        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:
            {
                // See unserialize
                if (JumpOffsetPopenvExitMagic)
                {
                    writer.WriteInt24(0xF00000);
                }
                else
                {
                    uint JumpOffsetFixed = (uint)JumpOffset;
                    JumpOffsetFixed &= ~0xFF800000;
                    writer.WriteInt24((int)JumpOffsetFixed);
                }

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

            case InstructionType.PopInstruction:
            {
                if (Type1 == DataType.Int16)
                {
                    // Special scenario - the swap instruction
                    // TODO: Figure out the proper syntax, see #129
                    writer.Write(SwapExtra);
                    byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                    writer.Write(TypePair);
                    writer.Write((byte)Kind);
                }
                else
                {
                    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, UndertaleChunkSTRG>));
                    writer.WriteUndertaleObject((UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>)Value);
                    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());
            }
        }