Move init method analysis

This commit is contained in:
Yoshi Askharoun
2025-07-17 15:26:17 -05:00
parent 27086b73a8
commit 52d2fdb10b
4 changed files with 90 additions and 78 deletions
+10
View File
@@ -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<KeyValuePair<string, XNamespace>> GetUsedNamespaces()
{
return _namespaces
+69 -73
View File
@@ -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<object> 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<object> AnalyzeMethodForInit(uint startOffset, XElement elemToInit)
{
var methodBody = _context.GetMethodBody(startOffset);
Stack<object> 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);
+4 -4
View File
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-16"?>
<UIX xmlns="http://schemas.microsoft.com/2007/uix" xmlns:me="Me" xmlns:dialog="res://UIXControls!Dialog.uix" xmlns:iris="assembly://UIX/Microsoft.Iris" xmlns:zuneUI="assembly://ZuneShell/ZuneUI" xmlns:system="assembly://System.Private.CoreLib/System" xmlns:styles="res://ZuneShellResources!Styles.uix" xmlns:label="res://UIXControls!Label.uix" xmlns:style="res://UIXControls!Style.uix" xmlns:linkButtons="res://ZuneShellResources!LinkButtons.uix" xmlns:button="res://UIXControls!Button.uix">
<UIX xmlns="http://schemas.microsoft.com/2007/uix" xmlns:dialog="res://UIXControls!Dialog.uix" xmlns:iris="assembly://UIX/Microsoft.Iris" xmlns:zuneUI="assembly://ZuneShell/ZuneUI" xmlns:system="assembly://System.Private.CoreLib/System">
<Class Name="AboutDialog" Base="dialog:Dialog">
<Properties>
<String String="res://ZuneShellResources!AboutDialog.uix#AboutDialogContentUI" Name="ContentUI" />
<iris:Command Description="zuneUI:Shell.LoadString(zuneUI:StringId.IDS_DIALOG_OK)" Name="Cancel" />
<zuneUI:WebHelpCommand Description="zuneUI:Shell.LoadString(zuneUI:StringId.IDS_ABOUTDIALOG_TECHNICAL_SUPPORT_INFORMATION)" Url="zuneUI:Shell.LoadString(zuneUI:StringId.IDS_WWW_ZUNE_NET_SUPPORT_URL)" Name="TechSupportLink" />
<system:String String="zuneUI:Shell.LoadString(zuneUI:StringId.IDS_ABOUTDIALOG_TITLE)" Name="AccessibleDescription" />
<iris:Command Description="{zuneUI:Shell.LoadString(zuneUI:StringId.IDS_DIALOG_OK)}" Name="Cancel" />
<zuneUI:WebHelpCommand Description="{zuneUI:Shell.LoadString(zuneUI:StringId.IDS_ABOUTDIALOG_TECHNICAL_SUPPORT_INFORMATION)}" Url="{zuneUI:Shell.LoadString(zuneUI:StringId.IDS_WWW_ZUNE_NET_SUPPORT_URL)}" Name="TechSupportLink" />
<system:String String="{zuneUI:Shell.LoadString(zuneUI:StringId.IDS_ABOUTDIALOG_TITLE)}" Name="AccessibleDescription" />
</Properties>
</Class>
<UI Name="AboutDialogContentUI" Base="dialog:DialogContentUI" />
+6
View File
@@ -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