コード例 #1
0
ファイル: Decompiler.cs プロジェクト: nommiin/Luna
        /*
         *  NOTE:
         *  This is a simple ad-hoc decompiler intended strictly for debugging purposes.
         *  Any pull requests or commits that attempt to turn this into a decompiler for
         *  the creating a GameMaker project are strictly prohibited and will be immediately
         *  declined.
         */

        public static string Decompile(List <Instruction> _instructionList)
        {
            string          _decomOutput = "";
            Stack <dynamic> _decomStack  = new Stack <dynamic>();

            foreach (Instruction _instructionGet in _instructionList)
            {
                switch (_instructionGet.Opcode)
                {
                case LOpcode.b:
                case LOpcode.bt:
                case LOpcode.bf: {
                    Instructions.Branch _instructionBranch = _instructionGet as Instructions.Branch;
                    _decomOutput += "// branch->" + _instructionBranch.Jump + "\n";
                    break;
                }

                case LOpcode.pushi: {
                    Instructions.PushImmediate _instructionPushImmediate = _instructionGet as Instructions.PushImmediate;
                    _decomStack.Push(_instructionPushImmediate.Value.ToString());
                    break;
                }

                case LOpcode.push: {
                    Instructions.Push _instructionPush = _instructionGet as Instructions.Push;
                    switch (_instructionPush.Type)
                    {
                    case LArgumentType.Variable: {
                        _decomStack.Push(_instructionPush.Variable.Name);
                        break;
                    }

                    case LArgumentType.String: {
                        _decomStack.Push("\"" + _instructionPush.Value.String + "\"");
                        break;
                    }

                    default: {
                        _decomStack.Push(_instructionPush.Value.Number.ToString());
                        break;
                    }
                    }
                    break;
                }

                case LOpcode.pop: {
                    Instructions.Pop _instructionPop = _instructionGet as Instructions.Pop;
                    switch (_instructionPop.Variable.Scope)
                    {
                    case LVariableScope.Global: {
                        _decomOutput += "global.";
                        break;
                    }

                    case LVariableScope.Instance: {
                        _decomOutput += "self.";
                        break;
                    }

                    case LVariableScope.Local: {
                        _decomOutput += "local.";
                        break;
                    }

                    case LVariableScope.Static: {
                        _decomOutput += "static.";
                        break;
                    }
                    }
                    _decomOutput += _instructionPop.Variable.Name + " = ";
                    _decomOutput += _decomStack.Pop().ToString() + ";\n";
                    break;
                }

                case LOpcode.call: {
                    Instructions.Call _instructionCall = _instructionGet as Instructions.Call;
                    _decomOutput += _instructionCall.FunctionName + "(";
                    for (int i = 0; i < _instructionCall.Count; i++)
                    {
                        _decomOutput += _decomStack.Pop().ToString();
                        if (i < _instructionCall.Count - 1)
                        {
                            _decomOutput += ", ";
                        }
                    }
                    _decomOutput += ");\n";
                    break;
                }

                case LOpcode.exit: {
                    _decomOutput += "exit;\n";
                    break;
                }
                }
            }
            return(_decomOutput);
        }
コード例 #2
0
ファイル: LCode.cs プロジェクト: nommiin/Luna
        public void Parse(Game _game)
        {
            // Parse all instructions
            while (this.Reader.BaseStream.Position < this.Reader.BaseStream.Length)
            {
                this.BranchTable[this.Reader.BaseStream.Position] = this.Instructions.Count;
                Int32   _instructionGet = this.Reader.ReadInt32();
                LOpcode _opcodeGet      = Instruction.GetOpcode(_instructionGet);
                if (Instruction.Ignore.Contains(_opcodeGet) == false)
                {
                    if (Instruction.Mapping.ContainsKey(_opcodeGet) == true)
                    {
                        this.Instructions.Add(Instruction.Mapping[_opcodeGet](_instructionGet, _game, this, this.Reader));
                    }
                    else
                    {
                        throw new Exception(String.Format("Could not find instruction mapping for {0} at {1} in {2}", _opcodeGet, this.Reader.BaseStream.Position, this.Name));
                    }
                }
            }

            // Map out branching & environments
            for (int i = 0; i < this.Instructions.Count; i++)
            {
                switch (this.Instructions[i].Opcode)
                {
                case LOpcode.b:
                case LOpcode.bt:
                case LOpcode.bf: {
                    Instructions.Branch _instructionBranch = this.Instructions[i] as Instructions.Branch;
                    if (this.BranchTable.ContainsKey(_instructionBranch.Offset) == true)
                    {
                        _instructionBranch.Jump = this.BranchTable[_instructionBranch.Offset] - 1;
                    }
                    else
                    {
                        _instructionBranch.Jump = this.Instructions.Count;
                    }
                    break;
                }

                case LOpcode.pushenv: {
                    Instructions.PushEnvironment _instructionEnv = this.Instructions[i] as Instructions.PushEnvironment;
                    if (this.BranchTable.ContainsKey(_instructionEnv.Offset) == true)
                    {
                        _instructionEnv.Jump = this.BranchTable[_instructionEnv.Offset];
                    }
                    else
                    {
                        _instructionEnv.Jump = this.Instructions.Count;
                    }
                    break;
                }

                case LOpcode.popenv: {
                    Instructions.PopEnvironment _instructionEnv = this.Instructions[i] as Instructions.PopEnvironment;
                    if (this.BranchTable.ContainsKey(_instructionEnv.Offset) == true)
                    {
                        _instructionEnv.Jump = this.BranchTable[_instructionEnv.Offset];
                    }
                    else
                    {
                        _instructionEnv.Jump = this.Instructions.Count;
                    }
                    break;
                }
                }
            }

            // Check for arrays
            for (int i = 0; i < this.Instructions.Count; i++)
            {
                switch (this.Instructions[i].Opcode)
                {
                case LOpcode.setowner: {
                    // Find next pop instruction
                    for (int j = i; j < this.Instructions.Count; j++)
                    {
                        if (this.Instructions[j].Opcode == LOpcode.pop)
                        {
                            this.Instructions.RemoveAt(--i);       // push.i <id>
                            break;
                        }
                        else if (this.Instructions[j].Opcode == LOpcode.call)
                        {
                            Instructions.Call _instructionGet = this.Instructions[j] as Instructions.Call;
                            if (_instructionGet.FunctionName == "@@NewGMLArray@@")
                            {
                                this.Instructions.RemoveAt(--i);
                                break;
                            }
                        }
                    }
                    break;
                }
                }
            }

#if (!DEBUG)
            // Print out finalized bytecode
            string _bytecodeOutput = this.Name + "\n";
            for (int i = 0; i < this.Instructions.Count; i++)
            {
                _bytecodeOutput += String.Format("[{1}] - {0}", this.Instructions[i].Opcode, this.Instructions[i].Raw.ToString("X"));
                switch (this.Instructions[i].Opcode)
                {
                case LOpcode.b: {
                    Instructions.Branch _instructionGet = this.Instructions[i] as Instructions.Branch;
                    _bytecodeOutput += String.Format("(Goto={0}:{1})", this.Instructions[_instructionGet.Jump].Opcode, _instructionGet.Jump);
                    break;
                }

                case LOpcode.call: {
                    Instructions.Call _instructionGet = this.Instructions[i] as Instructions.Call;
                    _bytecodeOutput += String.Format("(Function={0})", _instructionGet.FunctionName);
                    break;
                }

                case LOpcode.pop: {
                    Instructions.Pop _instructionGet = this.Instructions[i] as Instructions.Pop;
                    _bytecodeOutput += String.Format("(Variable={0}, Scope={1})", _instructionGet.Variable.Name, _instructionGet.Data);
                    break;
                }

                case LOpcode.push: {
                    Instructions.Push _instructionGet = this.Instructions[i] as Instructions.Push;
                    switch (_instructionGet.Type)
                    {
                    case LArgumentType.Variable: {
                        _bytecodeOutput += String.Format("(Variable={0})", _instructionGet.Variable.Name);
                        break;
                    }

                    default: {
                        _bytecodeOutput += String.Format("(Value={0})", _instructionGet.Value.Value);
                        break;
                    }
                    }
                    break;
                }

                case LOpcode.pushb: {
                    Instructions.PushBuiltin _instructionGet = this.Instructions[i] as Instructions.PushBuiltin;
                    _bytecodeOutput += String.Format("(Variable={0})", _instructionGet.Variable);
                    break;
                }

                case LOpcode.pushi: {
                    Instructions.PushImmediate _instructionGet = this.Instructions[i] as Instructions.PushImmediate;
                    _bytecodeOutput += String.Format("(Value={0})", _instructionGet.Value.Value);
                    break;
                }
                }
                _bytecodeOutput += "\n";
            }
            Console.WriteLine(_bytecodeOutput);

            // Print out decompiled bytecode
            try {
                Console.WriteLine("{0}:\n---\n{1}\n---", this.Name, Runner.Debug.Decompiler.Decompile(this.Instructions));
            } catch (Exception e) {
                Console.WriteLine("Failed to decompile {0}: {1}", this.Name, e.Message);
            }
#endif
        }