Example #1
0
        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            TextBox tb      = sender as TextBox;
            var     binding = BindingOperations.GetBindingExpression(tb, TextBox.TextProperty);

            if (binding.IsDirty)
            {
                if (ObjectReference != null)
                {
                    StringUpdateWindow dialog = new StringUpdateWindow();
                    dialog.Owner = Window.GetWindow(this);
                    dialog.ShowDialog();
                    switch (dialog.Result)
                    {
                    case StringUpdateWindow.ResultType.ChangeOneValue:
                        ObjectReference = (Application.Current.MainWindow as MainWindow).Data.Strings.MakeString(tb.Text);
                        break;

                    case StringUpdateWindow.ResultType.ChangeReferencedValue:
                        binding.UpdateSource();
                        break;

                    case StringUpdateWindow.ResultType.Cancel:
                        binding.UpdateTarget();
                        break;
                    }
                }
                else
                {
                    ObjectReference = (Application.Current.MainWindow as MainWindow).Data.Strings.MakeString(tb.Text);
                }
            }
        }
Example #2
0
        /// <inheritdoc/>
        public void Dispose()
        {
            GC.SuppressFinalize(this);

            Name  = null;
            Value = null;
        }
Example #3
0
        private void TextBox_DragOver(object sender, DragEventArgs e)
        {
            UndertaleString sourceItem = e.Data.GetData(e.Data.GetFormats()[0]) as UndertaleString;

            e.Effects = e.AllowedEffects.HasFlag(DragDropEffects.Link) && sourceItem != null ? DragDropEffects.Link : DragDropEffects.None;
            e.Handled = true;
        }
Example #4
0
 /// <inheritdoc />
 public void Unserialize(UndertaleReader reader)
 {
     InternalCount = reader.ReadInt32();
     if (InternalCount > 0)
     {
         Event = reader.ReadUndertaleString();
     }
 }
Example #5
0
 /// <inheritdoc />
 public override string ToString()
 {
     try
     {
         return(Name.Content + " (" + GetType().Name + ")");
     }
     catch
     {
         Name = new UndertaleString("EmbeddedSound Unknown Index");
     }
     return(Name.Content + " (" + GetType().Name + ")");
 }
Example #6
0
 /// <inheritdoc />
 public override string ToString()
 {
     if (Name != null)
     {
         return(Name.Content + " (" + GetType().Name + ")");
     }
     else
     {
         Name = new UndertaleString("Texture Unknown Index");
     }
     return(Name.Content + " (" + GetType().Name + ")");
 }
Example #7
0
        private static UndertaleResourceById <UndertaleString, UndertaleChunkSTRG> ParseStringReference(string line, IList <UndertaleString> strg)
        {
            string str = line;
            int    at  = str.LastIndexOf('@');
            uint?  id  = null;

            if (at >= 0)
            {
                // First make certain that this is actually an ID, not part of the string content
                if ((at - 1) == str.LastIndexOf('"'))
                {
                    if (str.Substring(at + 1) != "-1") // TODO
                    {
                        id = UInt32.Parse(str.Substring(at + 1));
                    }
                    str = str.Substring(0, at);
                }
            }
            if (!String.IsNullOrEmpty(str))
            {
                if (str[0] != '"' || str[str.Length - 1] != '"')
                {
                    throw new Exception("Bad string format");
                }
                str = UndertaleString.UnescapeText(str.Substring(1, str.Length - 2));
            }
            else
            {
                str = null;
            }
            UndertaleString strobj = id.HasValue ? strg[(int)id.Value] : null;

            if (strobj != null)
            {
                if (str != null) // Retain original value if empty string passed (push.s @300)
                {
                    strobj.Content = str;
                }
            }
            else
            {
                strobj = strg.MakeString(str);
            }
            if (!id.HasValue)
            {
                id = (uint)strg.IndexOf(strobj);
            }
            return(new UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>()
            {
                Resource = strobj, CachedId = (int)id.Value
            });
        }
Example #8
0
        private static UndertaleResourceById <UndertaleString, UndertaleChunkSTRG> ParseStringReference(string line, IList <UndertaleString> strg)
        {
            string str = line;
            int    at  = str.LastIndexOf('@');
            uint?  id  = null;

            if (at >= 0)
            {
                if (str.Substring(at + 1) != "-1") // TODO
                {
                    id = UInt32.Parse(str.Substring(at + 1));
                }
                str = str.Substring(0, at);
            }
            if (!String.IsNullOrEmpty(str))
            {
                if (str[0] != '"' || str[str.Length - 1] != '"')
                {
                    throw new Exception("Bad string format");
                }
                str = str.Substring(1, str.Length - 2);
            }
            UndertaleString strobj = id.HasValue ? strg[(int)id.Value] : null;

            if (strobj != null)
            {
                strobj.Content = str;
            }
            else
            {
                strobj = strg.MakeString(str);
            }
            if (!id.HasValue)
            {
                id = (uint)strg.IndexOf(strobj);
            }
            return(new UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>()
            {
                Resource = strobj, CachedId = (int)id.Value
            });
        }
    /// <summary>
    /// Creates <paramref name="content"/> as a new <see cref="UndertaleString"/>,
    /// adds it to a <see cref="List{T}"/> of <see cref="UndertaleString"/> if it does not exist yet, and returns it.
    /// </summary>
    /// <param name="list">The <see cref="List{T}"/> of <see cref="UndertaleString"/>.</param>
    /// <param name="content">The string to create a <see cref="UndertaleString"/> of.</param>
    /// <returns><paramref name="content"/> as a <see cref="UndertaleString"/>.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="content"/> is null.</exception>
    public static UndertaleString MakeString(this IList <UndertaleString> list, string content)
    {
        if (content == null)
        {
            throw new ArgumentNullException(nameof(content));
        }

        // TODO: without reference counting the strings, this may leave unused strings in the array
        foreach (UndertaleString str in list)
        {
            if (str.Content == content)
            {
                return(str);
            }
        }

        UndertaleString newString = new UndertaleString(content);

        list.Add(newString);
        return(newString);
    }
    /// <summary>
    /// Creates <paramref name="content"/> as a new <see cref="UndertaleString"/>,
    /// adds it to a <see cref="List{T}"/> of <see cref="UndertaleString"/> if it does not exist yet, and returns it.
    /// </summary>
    /// <param name="list">The <see cref="List{T}"/> of <see cref="UndertaleString"/>.</param>
    /// <param name="content">The string to create a <see cref="UndertaleString"/> of.</param>
    /// <param name="index">The index where the newly created <see cref="UndertaleString"/> is located in <paramref name="list"/>.</param>
    /// <returns><paramref name="content"/> as a <see cref="UndertaleString"/>.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="content"/> is null.</exception>
    public static UndertaleString MakeString(this IList <UndertaleString> list, string content, out int index)
    {
        if (content == null)
        {
            throw new ArgumentNullException(nameof(content));
        }

        // TODO: without reference counting the strings, this may leave unused strings in the array
        for (int i = 0; i < list.Count; i++)
        {
            UndertaleString str = list[i];
            if (str.Content == content)
            {
                index = i;
                return(str);
            }
        }

        UndertaleString newString = new UndertaleString(content);

        index = list.Count;
        list.Add(newString);
        return(newString);
    }
Example #11
0
        public void DisassembleAndReassembleAllScripts()
        {
            Parallel.ForEach(data.Code, (code) =>
            {
                //Console.WriteLine(code.Name.Content);

                bool knownBug = false;
                foreach (var instr in code.Instructions)
                {
                    if (instr.Value?.GetType() == typeof(UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>))
                    {
                        UndertaleString str = ((UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>)instr.Value).Resource;
                        if (str.Content.Contains("\n") || str.Content.Contains("\"")) // see #28
                        {
                            knownBug = true;
                        }
                    }
                }
                if (knownBug)
                {
                    Console.WriteLine("SKIPPING " + code.Name.Content + ", known bug");
                    return;
                }

                string disasm;
                try
                {
                    disasm = code.Disassemble(data.Variables, data.CodeLocals.For(code));
                }
                catch (Exception e)
                {
                    throw new Exception("Failed to disassemble script " + code.Name.Content, e);
                }

                IList <UndertaleInstruction> reasm = Assembler.Assemble(disasm, data.Functions, data.Variables, data.Strings);
                Assert.AreEqual(code.Instructions.Count, reasm.Count, "Reassembled instruction count didn't match the disassembly for script " + code.Name.Content);
                for (int i = 0; i < code.Instructions.Count; i++)
                {
                    string errMsg = "Instruction at " + code.Instructions[i].Address.ToString("D5") + " didn't match for script: " + code.Name.Content;
                    Assert.AreEqual(code.Instructions[i].Kind, reasm[i].Kind, errMsg);
                    Assert.AreEqual(code.Instructions[i].ComparisonKind, reasm[i].ComparisonKind, errMsg);
                    Assert.AreEqual(code.Instructions[i].Type1, reasm[i].Type1, errMsg);
                    Assert.AreEqual(code.Instructions[i].Type2, reasm[i].Type2, errMsg);
                    Assert.AreEqual(code.Instructions[i].TypeInst, reasm[i].TypeInst, errMsg);
                    Assert.AreEqual(code.Instructions[i].Extra, reasm[i].Extra, errMsg);
                    Assert.AreEqual(code.Instructions[i].SwapExtra, reasm[i].SwapExtra, errMsg);
                    Assert.AreEqual(code.Instructions[i].ArgumentsCount, reasm[i].ArgumentsCount, errMsg);
                    Assert.AreEqual(code.Instructions[i].JumpOffsetPopenvExitMagic, reasm[i].JumpOffsetPopenvExitMagic, errMsg);
                    if (!code.Instructions[i].JumpOffsetPopenvExitMagic)
                    {
                        Assert.AreEqual(code.Instructions[i].JumpOffset, reasm[i].JumpOffset, errMsg);
                    }
                    Assert.AreSame(code.Instructions[i].Destination?.Target, reasm[i].Destination?.Target, errMsg);
                    Assert.AreEqual(code.Instructions[i].Destination?.Type, reasm[i].Destination?.Type, errMsg);
                    Assert.AreSame(code.Instructions[i].Function?.Target, reasm[i].Function?.Target, errMsg);
                    Assert.AreEqual(code.Instructions[i].Function?.Type, reasm[i].Function?.Type, errMsg);

                    Assert.AreEqual(code.Instructions[i].Value?.GetType(), reasm[i].Value?.GetType(), errMsg);
                    if (code.Instructions[i].Value?.GetType() == typeof(double))
                    {
                        Assert.AreEqual((double)code.Instructions[i].Value, (double)reasm[i].Value, Math.Abs((double)code.Instructions[i].Value) * (1e-5), errMsg); // see issue #53
                    }
                    else if (code.Instructions[i].Value?.GetType() == typeof(float))
                    {
                        Assert.AreEqual((float)code.Instructions[i].Value, (float)reasm[i].Value, Math.Abs((float)code.Instructions[i].Value) * (1e-5), errMsg); // see issue #53
                    }
                    else if (code.Instructions[i].Value?.GetType() == typeof(UndertaleInstruction.Reference <UndertaleVariable>))
                    {
                        Assert.AreSame(((UndertaleInstruction.Reference <UndertaleVariable>)code.Instructions[i].Value).Target, ((UndertaleInstruction.Reference <UndertaleVariable>)reasm[i].Value).Target, errMsg);
                    }
                    else if (code.Instructions[i].Value?.GetType() == typeof(UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>))
                    {
                        Assert.AreSame(((UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>)code.Instructions[i].Value).Resource, ((UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>)reasm[i].Value).Resource, errMsg);
                    }
                    else
                    {
                        Assert.AreEqual(code.Instructions[i].Value, reasm[i].Value, errMsg);
                    }
                }
            });
        }
 public void Unserialize(UndertaleReader reader)
 {
     SourceCode = reader.ReadUndertaleString();
 }
 /// <inheritdoc />
 public void Unserialize(UndertaleReader reader)
 {
     Name = reader.ReadUndertaleString();
 }
Example #14
0
 private void Remove_Click(object sender, RoutedEventArgs e)
 {
     ObjectReference = null;
 }
Example #15
0
        /// <inheritdoc />
        public void Unserialize(UndertaleReader reader)
        {
            // This reads the string content immediately, if necessary (which it should be)
            UndertaleString ForceReadString()
            {
                UndertaleString res      = reader.ReadUndertaleString();
                uint            returnTo = reader.Position;

                reader.Position = reader.GetOffsetMapRev()[res];
                reader.ReadUndertaleObject <UndertaleString>();
                reader.Position = returnTo;
                return(res);
            }

            ModelName       = ForceReadString();
            Name            = reader.ReadUndertaleString();
            BuiltinName     = reader.ReadInt32();
            Traits          = reader.ReadInt32();
            IsCreationTrack = reader.ReadBoolean();

            int tagCount      = reader.ReadInt32();
            int ownedResCount = reader.ReadInt32();
            int trackCount    = reader.ReadInt32();

            Tags = new List <int>();
            for (int i = 0; i < tagCount; i++)
            {
                Tags.Add(reader.ReadInt32());
            }

            OwnedResources = new List <UndertaleResource>();
            for (int i = 0; i < ownedResCount; i++)
            {
                GMAnimCurveString = ForceReadString();
                if (GMAnimCurveString.Content != "GMAnimCurve")
                {
                    throw new IOException("Expected GMAnimCurve");
                }
                UndertaleAnimationCurve res = new UndertaleAnimationCurve();
                res.Unserialize(reader);
                OwnedResources.Add(res);
            }

            Tracks = new List <Track>();
            for (int i = 0; i < trackCount; i++)
            {
                Tracks.Add(reader.ReadUndertaleObject <Track>());
            }

            // Now, handle specific keyframe/etc. data
            switch (ModelName.Content)
            {
            case "GMAudioTrack":
                Keyframes = reader.ReadUndertaleObject <AudioKeyframes>();
                break;

            case "GMInstanceTrack":
                Keyframes = reader.ReadUndertaleObject <InstanceKeyframes>();
                break;

            case "GMGraphicTrack":
                Keyframes = reader.ReadUndertaleObject <GraphicKeyframes>();
                break;

            case "GMSequenceTrack":
                Keyframes = reader.ReadUndertaleObject <SequenceKeyframes>();
                break;

            case "GMSpriteFramesTrack":
                Keyframes = reader.ReadUndertaleObject <SpriteFramesKeyframes>();
                break;

            case "GMAssetTrack":     // TODO?
                throw new NotImplementedException("GMAssetTrack not implemented, report this");

            case "GMBoolTrack":
                Keyframes = reader.ReadUndertaleObject <BoolKeyframes>();
                break;

            case "GMStringTrack":
                Keyframes = reader.ReadUndertaleObject <StringKeyframes>();
                break;

            // TODO?
            //case "GMIntTrack":
            //  Keyframes = reader.ReadUndertaleObject<IntKeyframes>();
            //  break;
            case "GMRealTrack":
            case "GMColourTrack":
                Keyframes = reader.ReadUndertaleObject <RealKeyframes>();
                break;
            }
        }