diff --git a/UndertaleModLib/Decompiler/Assembler.cs b/UndertaleModLib/Decompiler/Assembler.cs index 5d94fa781..4c5881344 100644 --- a/UndertaleModLib/Decompiler/Assembler.cs +++ b/UndertaleModLib/Decompiler/Assembler.cs @@ -17,13 +17,13 @@ public static class Assembler public static UndertaleInstruction AssembleOne(string source, IList funcs, IList vars, IList strg, Dictionary localvars = null) { string label; - UndertaleInstruction instr = AssembleOne(source, funcs, vars, strg, localvars, out label); + UndertaleInstruction instr = AssembleOne(source, funcs, vars, strg, localvars, out label, null); if (label != null) throw new Exception("Cannot use labels in this context"); return instr; } - public static UndertaleInstruction AssembleOne(string source, IList funcs, IList vars, IList strg, Dictionary localvars, out string label) + public static UndertaleInstruction AssembleOne(string source, IList funcs, IList vars, IList strg, Dictionary localvars, out string label, UndertaleInstruction.InstanceType? prevInstType) { label = null; string line = source; @@ -80,7 +80,7 @@ public static UndertaleInstruction AssembleOne(string source, IList Assemble(string source, IList= 2 && instructions[instructions.Count - 2].Kind == UndertaleInstruction.Opcode.PushI ? (UndertaleInstruction.InstanceType?)(short)instructions[instructions.Count - 2].Value : null); instr.Address = addr; if (labelTgt != null) labelTargets.Add(instr, labelTgt); @@ -248,7 +248,7 @@ private static UndertaleResourceById ParseStringReference(strin return new UndertaleResourceById("STRG") { Resource = strobj, CachedId = (int)id.Value }; } - private static UndertaleInstruction.Reference ParseVariableReference(string line, IList vars, Dictionary localvars, ref UndertaleInstruction.InstanceType instance) + private static UndertaleInstruction.Reference ParseVariableReference(string line, IList vars, Dictionary localvars, ref UndertaleInstruction.InstanceType instance, UndertaleInstruction.InstanceType? prevInstType) { string str = line; string inst = null; @@ -274,7 +274,7 @@ private static UndertaleInstruction.Reference ParseVariableRe } else { - instance = UndertaleInstruction.InstanceType.StackTopOrGlobal; // TODO: I think this isn't a thing that exists, 0 would be just object index 0 + instance = UndertaleInstruction.InstanceType.Undefined; } UndertaleInstruction.VariableType type = UndertaleInstruction.VariableType.Normal; if (str[0] == '[') @@ -288,15 +288,23 @@ private static UndertaleInstruction.Reference ParseVariableRe } } + UndertaleInstruction.InstanceType realinstance = instance; + // for arrays, the type is on the stack which totally breaks things + // This is an ugly hack to handle that + if (type == UndertaleInstruction.VariableType.Array && prevInstType.HasValue) + realinstance = prevInstType.Value; + if (realinstance >= 0) + realinstance = UndertaleInstruction.InstanceType.Self; + + UndertaleVariable varobj; - if (instance == UndertaleInstruction.InstanceType.Local) + if (realinstance == UndertaleInstruction.InstanceType.Local) { varobj = localvars.ContainsKey(str) ? localvars[str] : null; } else { - UndertaleInstruction.InstanceType i = instance; // ugh - varobj = vars.Where((x) => x.Name.Content == str && x.InstanceType == i).FirstOrDefault(); + varobj = vars.Where((x) => x.Name.Content == str && x.InstanceType == realinstance).FirstOrDefault(); } if (varobj == null) throw new Exception("Bad variable!"); diff --git a/UndertaleModLib/Decompiler/Decompiler.cs b/UndertaleModLib/Decompiler/Decompiler.cs index 889a6a0fd..21f9b0b26 100644 --- a/UndertaleModLib/Decompiler/Decompiler.cs +++ b/UndertaleModLib/Decompiler/Decompiler.cs @@ -384,7 +384,7 @@ public override string ToString() var instTypeVal = TryGetInstType(); if (instTypeVal.HasValue) { - if (instTypeVal.Value != UndertaleInstruction.InstanceType.StackTopOrGlobal) + if (instTypeVal.Value != UndertaleInstruction.InstanceType.Undefined) { name = instTypeVal.Value.ToString().ToLower() + "." + name; } diff --git a/UndertaleModLib/Models/UndertaleCode.cs b/UndertaleModLib/Models/UndertaleCode.cs index 9d9f3cd82..d4263c326 100644 --- a/UndertaleModLib/Models/UndertaleCode.cs +++ b/UndertaleModLib/Models/UndertaleCode.cs @@ -133,14 +133,14 @@ public enum DataType : byte public enum InstanceType : short { - StackTopOrGlobal = 0, + Undefined = 0, // actually, this is just object 0, but also occurs in places where no instance type was set Self = -1, Other = -2, All = -3, Noone = -4, Global = -5, - Unknown = -6, + Builtin = -6, // Note: Used only in UndertaleVariable.VarID (which is not really even InstanceType) Local = -7, // anything > 0 => GameObjectIndex @@ -524,7 +524,7 @@ public string ToString(UndertaleCode code, IList vars) sb.Append("." + Type1.ToOpcodeParam()); sb.Append("." + Type2.ToOpcodeParam()); sb.Append(" "); - if (Type1 == DataType.Variable && TypeInst != InstanceType.StackTopOrGlobal) + if (Type1 == DataType.Variable && TypeInst != InstanceType.Undefined) { sb.Append(TypeInst.ToString().ToLower()); sb.Append("."); @@ -535,7 +535,7 @@ public string ToString(UndertaleCode code, IList vars) case InstructionType.PushInstruction: sb.Append("." + Type1.ToOpcodeParam()); sb.Append(" "); - if (Type1 == DataType.Variable && TypeInst != InstanceType.StackTopOrGlobal) + if (Type1 == DataType.Variable && TypeInst != InstanceType.Undefined) { sb.Append(TypeInst.ToString().ToLower()); sb.Append("."); diff --git a/UndertaleModLib/UndertaleData.cs b/UndertaleModLib/UndertaleData.cs index f4565227d..d6ce04a2e 100644 --- a/UndertaleModLib/UndertaleData.cs +++ b/UndertaleModLib/UndertaleData.cs @@ -134,7 +134,7 @@ public static UndertaleFunction EnsureDefined(this IList list return func; } - public static UndertaleVariable EnsureDefined(this IList list, string name, UndertaleInstruction.InstanceType inst, IList strg, UndertaleData data) + public static UndertaleVariable EnsureDefined(this IList list, string name, UndertaleInstruction.InstanceType inst, bool isBuiltin, IList strg, UndertaleData data) { if (inst == UndertaleInstruction.InstanceType.Local) throw new InvalidOperationException("Use DefineLocal instead"); @@ -147,7 +147,7 @@ public static UndertaleVariable EnsureDefined(this IList list { Name = strg.MakeString(name), InstanceType = inst, - VarID = (int)data.InstanceVarCount++, + VarID = isBuiltin ? (int)UndertaleInstruction.InstanceType.Builtin : (int)data.InstanceVarCount++, UnknownChainEndingValue = 0 // TODO: seems to work... }; data.InstanceVarCountAgain = data.InstanceVarCount; @@ -167,6 +167,7 @@ public static UndertaleVariable DefineLocal(this IList list, }; if (idx >= data.MaxLocalVarCount) data.MaxLocalVarCount = idx + 1; + list.Add(vari); return vari; } } diff --git a/UndertaleModTool/Editors/UndertaleCodeEditor.xaml.cs b/UndertaleModTool/Editors/UndertaleCodeEditor.xaml.cs index 54c5a3af3..badfd27f0 100644 --- a/UndertaleModTool/Editors/UndertaleCodeEditor.xaml.cs +++ b/UndertaleModTool/Editors/UndertaleCodeEditor.xaml.cs @@ -140,7 +140,7 @@ private void DisassembleCode(UndertaleCode code) par.Inlines.Add(new Run("." + instr.Type1.ToOpcodeParam()) { Foreground = typeBrush }); par.Inlines.Add(new Run("." + instr.Type2.ToOpcodeParam()) { Foreground = typeBrush }); par.Inlines.Add(new Run(" ")); - if (instr.Type1 == UndertaleInstruction.DataType.Variable && instr.TypeInst != UndertaleInstruction.InstanceType.StackTopOrGlobal) + if (instr.Type1 == UndertaleInstruction.DataType.Variable && instr.TypeInst != UndertaleInstruction.InstanceType.Undefined) { par.Inlines.Add(new Run(instr.TypeInst.ToString().ToLower()) { Foreground = typeBrush }); par.Inlines.Add(new Run(".")); @@ -156,7 +156,7 @@ private void DisassembleCode(UndertaleCode code) case UndertaleInstruction.InstructionType.PushInstruction: par.Inlines.Add(new Run("." + instr.Type1.ToOpcodeParam()) { Foreground = typeBrush }); par.Inlines.Add(new Run(" ")); - if (instr.Type1 == UndertaleInstruction.DataType.Variable && instr.TypeInst != UndertaleInstruction.InstanceType.StackTopOrGlobal) + if (instr.Type1 == UndertaleInstruction.DataType.Variable && instr.TypeInst != UndertaleInstruction.InstanceType.Undefined) { par.Inlines.Add(new Run(instr.TypeInst.ToString().ToLower()) { Foreground = typeBrush }); par.Inlines.Add(new Run("."));