Esempio n. 1
0
        public CodeBody Decompile()
        {
            // Skip native funcs
            var Func = DataContainer as ME3Function;
            if (Func != null && Func.FunctionFlags.HasFlag(FunctionFlags.Native))
            {
                var comment = new ExpressionOnlyStatement(null, null, new SymbolReference(null, null, null, "// Native function"));
                return new CodeBody(new List<Statement>() { comment }, null, null);
            }

            Position = 0;
            _totalPadding = 0;
            CurrentScope = new Stack<int>();
            var statements = new List<Statement>();
            StatementLocations = new Dictionary<UInt16, Statement>();
            StartPositions = new Stack<UInt16>();
            Scopes = new List<List<Statement>>();
            LabelTable = new List<LabelTableEntry>();
            ForEachScopes = new Stack<UInt16>();

            DecompileDefaultParameterValues(statements);

            Scopes.Add(statements);
            CurrentScope.Push(Scopes.Count - 1);
            while (Position < Size && !CurrentIs(StandardByteCodes.EndOfScript))
            {
                var current = DecompileStatement();
                if (current == null && CurrentByte == (byte)StandardByteCodes.EndOfScript)
                    break; // Natural end after label table, no error
                if (current == null)
                    break; // TODO: ERROR!

                statements.Add(current);
            }
            CurrentScope.Pop(); ;
            AddStateLabels();

            return new CodeBody(statements, null, null);
        }
Esempio n. 2
0
 public bool VisitNode(ExpressionOnlyStatement node)
 {
     throw new NotImplementedException();
 }
Esempio n. 3
0
        public bool VisitNode(ExpressionOnlyStatement node)
        {
            // expression;
            Write("");
            node.Value.AcceptVisitor(this);

            return true;
        }
Esempio n. 4
0
        public Statement DecompileStatement()
        {
            StartPositions.Push((UInt16)Position);
            var token = CurrentByte;

            switch (token)
            {
                // return [expression];
                case (byte)StandardByteCodes.Return:
                    return DecompileReturn();

                // switch (expression)
                case (byte)StandardByteCodes.Switch:
                    return DecompileSwitch();

                // case expression :
                case (byte)StandardByteCodes.Case:
                    return DecompileCase();

                // if (expression) // while / for / do until
                case (byte)StandardByteCodes.JumpIfNot:
                    return DecompileConditionalJump();

                // continue
                case (byte)StandardByteCodes.Jump: // TODO: UDK seems to compile this from break when inside ForEach, handle?
                    return DecompileJump();

                // continue (iterator)
                case (byte)StandardByteCodes.IteratorNext:
                    PopByte(); // pop iteratornext token
                    return DecompileJump();

                // break;
                case (byte)StandardByteCodes.IteratorPop:
                    return DecompileIteratorPop();

                // stop;
                case (byte)StandardByteCodes.Stop:
                    PopByte();
                    var stopStatement = new StopStatement(null, null);
                    StatementLocations.Add(StartPositions.Pop(), stopStatement);
                    return stopStatement;

                // Goto label
                case (byte)StandardByteCodes.GotoLabel:
                    PopByte();
                    var labelExpr = DecompileExpression();
                    var func = new SymbolReference(null, null, null, "goto");
                    var call = new FunctionCall(func, new List<Expression>() { labelExpr }, null, null);
                    var gotoLabel = new ExpressionOnlyStatement(null, null, call);
                    StatementLocations.Add(StartPositions.Pop(), gotoLabel);
                    return gotoLabel;

                // assignable expression = expression;
                case (byte)StandardByteCodes.Let:
                case (byte)StandardByteCodes.LetBool:
                case (byte)StandardByteCodes.LetDelegate:
                    return DecompileAssign();

                // [skip x bytes]
                case (byte)StandardByteCodes.Skip: // TODO: this should never occur as statement, possibly remove?
                    PopByte();
                    ReadUInt16();
                    StartPositions.Pop();
                    return DecompileStatement();

                case (byte)StandardByteCodes.Nothing:
                    PopByte();
                    StartPositions.Pop();
                    return DecompileStatement(); // TODO, should probably have a nothing expression or statement, this is ugly

                // foreach IteratorFunction(...)
                case (byte)StandardByteCodes.Iterator:
                    return DecompileForEach();

                // foreach arrayName(valuevariable[, indexvariable])
                case (byte)StandardByteCodes.DynArrayIterator:
                    return DecompileForEach(isDynArray: true);

                case (byte)StandardByteCodes.LabelTable:
                    DecompileLabelTable();
                    StartPositions.Pop();
                    return DecompileStatement();

                #region unsupported

                case (byte)StandardByteCodes.OptIfLocal: // TODO: verify, handle syntax
                    return DecompileConditionalJump(isOpt: true);

                case (byte)StandardByteCodes.OptIfInstance: // TODO: verify, handle syntax
                    return DecompileConditionalJump(isOpt: true);

                #endregion

                default:
                    var expr = DecompileExpression();
                    if (expr != null)
                    {
                        var statement = new ExpressionOnlyStatement(null, null, expr);
                        StatementLocations.Add(StartPositions.Pop(), statement);
                        return statement;
                    }

                    // ERROR!
                    break;
            }

            return null;
        }
Esempio n. 5
0
        private void DecompileDefaultParameterValues(List<Statement> statements)
        {
            OptionalParams = new Stack<FunctionParameter>();
            var func = DataContainer as ME3Function;
            if (func != null) // Gets all optional params for default value parsing
            {
                for (int n = 0; n < Parameters.Count; n++)
                {
                    if (func.Parameters[n].PropertyFlags.HasFlag(PropertyFlags.OptionalParm))
                        OptionalParams.Push(Parameters[n]);
                }
            }

            while (CurrentByte == (byte)StandardByteCodes.DefaultParmValue
                || CurrentByte == (byte)StandardByteCodes.Nothing)
            {
                StartPositions.Push((UInt16)Position);
                var token = PopByte();
                if (token == (byte)StandardByteCodes.DefaultParmValue) // default value assigned
                {

                    ReadInt16(); //MemSize of value
                    var value = DecompileExpression();
                    PopByte(); // end of value

                    var builder = new CodeBuilderVisitor(); // what a wonderful hack, TODO.
                    value.AcceptVisitor(builder);

                    if (OptionalParams.Count != 0)
                    {
                        var parm = OptionalParams.Pop();
                        parm.Variables.First().Name += " = " + builder.GetCodeString();
                        StartPositions.Pop();
                    }
                    else
                    {       // TODO: weird, research how to deal with this
                        var comment = new SymbolReference(null, null, null, "// Orphaned Default Parm: " + builder.GetCodeString());
                        var statement = new ExpressionOnlyStatement(null, null, comment);
                        StatementLocations.Add(StartPositions.Pop(), statement);
                        statements.Add(statement);
                    }
                }
            }
        }