diff --git a/libs/UIX.DecompXml/DecompileContext.cs b/libs/UIX.DecompXml/DecompileContext.cs index ac76040..bb639a1 100644 --- a/libs/UIX.DecompXml/DecompileContext.cs +++ b/libs/UIX.DecompXml/DecompileContext.cs @@ -78,6 +78,16 @@ internal class DecompileContext public PropertySchema GetImportedProperty(Operand op) => ImportTables.PropertyImports[(ushort)op.Value]; + public Instruction[] GetMethodBody(uint startOffset) + { + return Instructions + .SkipWhile(i => i.Offset < startOffset) + .OrderBy(i => i.Offset) + .TakeWhile(i => i.OpCode is not (OpCode.ReturnValue or OpCode.ReturnVoid)) + .OrderBy(i => i.Offset) + .ToArray(); + } + public IEnumerable> GetUsedNamespaces() { return _namespaces diff --git a/libs/UIX.DecompXml/Decompiler.cs b/libs/UIX.DecompXml/Decompiler.cs index cd73476..d1e2a6b 100644 --- a/libs/UIX.DecompXml/Decompiler.cs +++ b/libs/UIX.DecompXml/Decompiler.cs @@ -47,79 +47,7 @@ public class Decompiler new XAttribute("Name", name), new XAttribute("Base", baseTypeName)); - var initPropsOffset = export.InitializePropertiesOffset; - var initPropsBody = _context.Instructions - .SkipWhile(i => i.Offset < initPropsOffset) - .OrderBy(i => i.Offset) - .TakeWhile(i => i.OpCode is not (OpCode.ReturnValue or OpCode.ReturnVoid)) - .OrderBy(i => i.Offset) - .ToArray(); - - var propertyElements = new XElement[export.Properties.Length]; - - Stack stack = new([xExport]); - - for (int i = 0; i < initPropsBody.Length; i++) - { - var instruction = initPropsBody[i]; - - if (instruction.OpCode is OpCode.JumpIfDictionaryContains) - { - } - else if (instruction.OpCode is OpCode.PushConstant) - { - var constant = _context.GetConstant(instruction.Operands.First()); - stack.Push(constant); - } - else if (instruction.OpCode is OpCode.PushNull) - { - stack.Push(null); - } - else if (instruction.OpCode is OpCode.ConstructObject) - { - var type = _context.GetImportedType(instruction.Operands.ElementAt(0)); - var xObj = new XElement(_context.GetXName(type)); - stack.Push(new IrisObject(xObj, type)); - } - else if (instruction.OpCode is OpCode.MethodInvokeStatic) - { - var method = _context.GetImportedMethod(instruction.Operands.First()); - - int parameterCount = method.ParameterTypes.Length; - object[] parameters = new object[parameterCount]; - for (parameterCount--; parameterCount >= 0; parameterCount--) - parameters[parameterCount] = stack.Pop(); - - var callExpression = new IrisMethodCallExpression(method, null, parameters.Select(IrisExpression.ToExpression)); - - stack.Push(callExpression); - } - else if (instruction.OpCode is OpCode.PropertyInitialize) - { - var property = _context.GetImportedProperty(instruction.Operands.ElementAt(0)); - var value = stack.Pop(); - - var target = stack.Pop(); - var xTarget = (XElement)ToXmlFriendlyObject(target); - - PropertyAssignOnXElement(xTarget, property, IrisObject.Create(value, property.PropertyType, _context)); - - stack.Push(new IrisObject(xTarget, property.Owner)); - } - else if (instruction.OpCode is OpCode.PropertyDictionaryAdd) - { - var targetProperty = _context.GetImportedProperty(instruction.Operands.ElementAt(0)); - - var keyReference = instruction.Operands.ElementAt(1); - var key = _context.GetConstant(keyReference).Value.ToString(); - - var value = stack.Pop(); - - var targetInstance = stack.Peek() as XElement; - - PropertyDictionaryAddOnXElement(targetInstance, targetProperty, IrisObject.Create(value, null, _context), key); - } - } + AnalyzeMethodForInit(export.InitializePropertiesOffset, xExport); xRoot.Add(xExport); } @@ -154,6 +82,74 @@ public class Decompiler return sb.ToString(); } + private Stack AnalyzeMethodForInit(uint startOffset, XElement elemToInit) + { + var methodBody = _context.GetMethodBody(startOffset); + + Stack stack = new([elemToInit]); + + for (int i = 0; i < methodBody.Length; i++) + { + var instruction = methodBody[i]; + + if (instruction.OpCode is OpCode.PushConstant) + { + var constant = _context.GetConstant(instruction.Operands.First()); + stack.Push(constant); + } + else if (instruction.OpCode is OpCode.PushNull) + { + stack.Push(null); + } + else if (instruction.OpCode is OpCode.ConstructObject) + { + var type = _context.GetImportedType(instruction.Operands.ElementAt(0)); + var xObj = new XElement(_context.GetXName(type)); + stack.Push(new IrisObject(xObj, type)); + } + else if (instruction.OpCode is OpCode.MethodInvokeStatic) + { + var method = _context.GetImportedMethod(instruction.Operands.First()); + + int parameterCount = method.ParameterTypes.Length; + object[] parameters = new object[parameterCount]; + for (parameterCount--; parameterCount >= 0; parameterCount--) + parameters[parameterCount] = stack.Pop(); + + var callExpression = new IrisMethodCallExpression(method, null, parameters.Select(IrisExpression.ToExpression)); + + stack.Push(callExpression); + } + else if (instruction.OpCode is OpCode.PropertyInitialize) + { + var property = _context.GetImportedProperty(instruction.Operands.ElementAt(0)); + var value = stack.Pop(); + + var target = stack.Pop(); + var xTarget = (XElement)ToXmlFriendlyObject(target); + + PropertyAssignOnXElement(xTarget, property, IrisObject.Create(value, property.PropertyType, _context)); + + stack.Push(new IrisObject(xTarget, property.Owner)); + } + else if (instruction.OpCode is OpCode.PropertyDictionaryAdd) + { + var targetProperty = _context.GetImportedProperty(instruction.Operands.ElementAt(0)); + + var keyReference = instruction.Operands.ElementAt(1); + var key = _context.GetConstant(keyReference).Value.ToString(); + + var value = stack.Pop(); + + var targetInstance = stack.Peek() as XElement; + + PropertyDictionaryAddOnXElement(targetInstance, targetProperty, IrisObject.Create(value, null, _context), key); + } + } + + return stack; + } + private static XElement GetOrCreateElement(XElement parent, XName name) { var elem = parent.Element(name); diff --git a/test/ABOUTDIALOG.31_48_decomp.uix b/test/ABOUTDIALOG.31_48_decomp.uix index 243d972..be7698c 100644 --- a/test/ABOUTDIALOG.31_48_decomp.uix +++ b/test/ABOUTDIALOG.31_48_decomp.uix @@ -1,11 +1,11 @@ - + - - - + + + diff --git a/test/ADDTOCOLLECTION.31_48_decomp.uixa b/test/ADDTOCOLLECTION.31_48_decomp.uixa index ecde2e8..6ddb540 100644 --- a/test/ADDTOCOLLECTION.31_48_decomp.uixa +++ b/test/ADDTOCOLLECTION.31_48_decomp.uixa @@ -212,7 +212,7 @@ AddToCollection_prop: JMPD 0, 5, 486 COBJ 3 PDAD 0, @const5 - + JMPD 0, 6, 501 PSHN PDAD 0, @const6 @@ -220,18 +220,24 @@ AddToCollection_prop: AddToCollection_locl: PSHN PDAD 1, @const7 + COBJ 3 PDAD 1, @const8 + COBJ 3 PDAD 1, @const9 + COBJ 1 PDAD 1, @const10 + COBJ 8 PSHC @const11 PINI 2 INIT 8 PDAD 1, @const12 + PSHC @const11 PDAD 1, @const13 + CLIS 8 RETV