Exemple #1
0
        public string Decompile(ILuaFile luaFile)
        {
            var function = new IR.Function();

            GenerateIRHKS(function, luaFile.MainFunction);

            return(function.ToString());
        }
Exemple #2
0
        public static FunctionMethod Emit(IR.Function function, MethodFactory methodFactory, FunctionLookup functionLookup)
        {
            Contract.Requires(function != null);
            Contract.Requires(methodFactory != null);
            Contract.Requires(functionLookup != null);

            var emitter = new FunctionEmitter(function, methodFactory, functionLookup);

            emitter.EmitBody();
            return(emitter.Method);
        }
Exemple #3
0
        static void Main(string[] args)
        {
            Encoding outEncoding = Encoding.UTF8;
            // Super bad arg parser until I decide to use a better libary
            bool   writeFile   = true;
            string outfilename = null;
            string infilename  = null;
            int    arg         = 0;

            try
            {
                if (args[arg] == "-d")
                {
                    writeFile = false;
                    arg++;
                }
                else if (args[arg] == "-o")
                {
                    outfilename = args[arg + 1];
                    arg        += 2;
                }
                infilename = args[arg];
                if (outfilename == null)
                {
                    outfilename = Path.GetFileNameWithoutExtension(infilename) + ".dec.lua";
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Usage: DSLuaDecompiler.exe [options] inputfile.lua\n-o outputfile.lua\n-d Print output in console");
            }

            Console.OutputEncoding = outEncoding;
            using (FileStream stream = File.OpenRead(infilename))
            {
                BinaryReaderEx br   = new BinaryReaderEx(false, stream);
                var            lua  = new LuaFile(br);
                IR.Function    main = new IR.Function();
                //LuaDisassembler.DisassembleFunction(lua.MainFunction);
                if (lua.Version == LuaFile.LuaVersion.Lua50)
                {
                    LuaDisassembler.GenerateIR50(main, lua.MainFunction);
                    outEncoding = Encoding.GetEncoding("shift_jis");
                }
                else if (lua.Version == LuaFile.LuaVersion.Lua51HKS)
                {
                    LuaDisassembler.GenerateIRHKS(main, lua.MainFunction);
                    outEncoding = Encoding.UTF8;
                }
                else if (lua.Version == LuaFile.LuaVersion.Lua53Smash)
                {
                    LuaDisassembler.GenerateIR53(main, lua.MainFunction);
                    outEncoding = Encoding.UTF8;
                }

                if (writeFile)
                {
                    File.WriteAllText(outfilename, main.ToString(), outEncoding);
                }
                else
                {
                    Console.WriteLine(main.ToString());
                }
            }
        }
Exemple #4
0
        public static void GenerateIRHKS(IR.Function irfun, ILuaFunction fun)
        {
            // First register closures for all the children
            for (int i = 0; i < fun.ChildFunctions.Count; i++)
            {
                var cfun = new IR.Function();
                // Upval count needs to be set for child functions for analysis to be correct
                cfun.UpvalCount = fun.ChildFunctions[i].Upvalues.Count;
                irfun.AddClosure(cfun);
            }

            SymbolTable.BeginScope();
            var parameters = new List <IR.Identifier>();

            for (uint i = 0; i < fun.Header.ParameterCount; i++)
            {
                parameters.Add(SymbolTable.GetRegister(i));
            }
            irfun.SetParameters(parameters);

            for (int i = 0; i < fun.Instructions.Count * 4; i += 4)
            {
                var instruction = fun.Instructions[i / 4];
                //uint opcode = instruction & 0x3F;
                // Uhhh thanks again hork
                var opcode = instruction.OpCode;
                var a      = instruction.A;
                var c      = instruction.C;
                var b      = instruction.B;
                var szero  = instruction.ExtraCBit;

                var  bx  = instruction.Bx;
                var  sbx = instruction.SBx;
                uint addr;
                var  pc = i / 4;

                List <IR.Expression>          args         = null;
                List <IR.IdentifierReference> rets         = null;
                List <IR.IInstruction>        instructions = new List <IR.IInstruction>();
                IR.Assignment assn;
                switch (opcode)
                {
                case LuaOpCode.HKS_OPCODE_MOVE:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), Register((uint)b));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_LOADK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), ToConstantIR(fun.Constants[(int)bx]));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_LOADBOOL:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.Constant(b == 1));
                    assn.NilAssignmentReg = a;
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    if (c > 0)
                    {
                        instructions.Add(new IR.Jump(irfun.GetLabel((uint)((i / 4) + 2))));
                    }
                    break;

                case LuaOpCode.HKS_OPCODE_LOADNIL:
                    var nlist = new List <IR.IdentifierReference>();
                    for (int arg = (int)a; arg <= b; arg++)
                    {
                        nlist.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)arg)));
                    }
                    assn = new IR.Assignment(nlist, new IR.Constant(IR.Constant.ConstantType.ConstNil));
                    assn.NilAssignmentReg = a;
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_GETUPVAL:
                    if (b >= irfun.UpvalueBindings.Count)
                    {
                        //throw new Exception("Reference to unbound upvalue");
                    }

                    Identifier up = irfun.UpvalueBindings[(int)b];
                    up.IsClosureBound = true;
                    instructions.Add(new IR.Assignment(SymbolTable.GetRegister(a), new IR.IdentifierReference(up)));
                    break;

                case LuaOpCode.HKS_OPCODE_SETUPVAL:
                case LuaOpCode.HKS_OPCODE_SETUPVAL_R1:
                    up = SymbolTable.GetUpvalue((uint)b);
                    if (fun.Upvalues.Any() && !up.UpvalueResolved)
                    {
                        up.Name            = fun.Upvalues[(int)b].Name;
                        up.UpvalueResolved = true;
                    }
                    instructions.Add(new IR.Assignment(up, new IR.IdentifierReference(SymbolTable.GetRegister(a))));
                    break;

                case LuaOpCode.HKS_OPCODE_GETGLOBAL_MEM:
                case LuaOpCode.HKS_OPCODE_GETGLOBAL:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.IdentifierReference(SymbolTable.GetGlobal(fun.Constants[(int)bx].ToString())));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_GETTABLE_S:
                case LuaOpCode.HKS_OPCODE_GETTABLE:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.IdentifierReference(SymbolTable.GetRegister((uint)b), RKIRHKS(fun, c, szero)));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SETGLOBAL:
                    instructions.Add(new IR.Assignment(SymbolTable.GetGlobal(fun.Constants[(int)bx].ToString()), new IR.IdentifierReference(SymbolTable.GetRegister(a))));
                    break;

                case LuaOpCode.HKS_OPCODE_NEWTABLE:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.InitializerList(new List <IR.Expression>()));
                    assn.VarargAssignmentReg = a;
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SELF:
                    instructions.Add(new IR.Assignment(SymbolTable.GetRegister(a + 1), Register((uint)b)));
                    instructions.Add(new IR.Assignment(SymbolTable.GetRegister(a), new IR.IdentifierReference(SymbolTable.GetRegister((uint)b), RKIRHKS(fun, c, szero))));
                    break;

                case LuaOpCode.HKS_OPCODE_ADD:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpAdd));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_ADD_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpAdd));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SUB:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpSub));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SUB_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpSub));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_MUL:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpMul));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_MUL_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpMul));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_DIV:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpDiv));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_DIV_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpDiv));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_MOD:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpMod));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_MOD_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpMod));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_POW:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpPow));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_POW_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpPow));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_UNM:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a),
                                             new IR.UnaryOp(new IR.IdentifierReference(SymbolTable.GetRegister((uint)b)), IR.UnaryOp.OperationType.OpNegate));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_NOT:
                case LuaOpCode.HKS_OPCODE_NOT_R1:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a),
                                             new IR.UnaryOp(new IR.IdentifierReference(SymbolTable.GetRegister((uint)b)), IR.UnaryOp.OperationType.OpNot));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_LEN:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a),
                                             new IR.UnaryOp(new IR.IdentifierReference(SymbolTable.GetRegister((uint)b)), IR.UnaryOp.OperationType.OpLength));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SHIFT_LEFT:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpShiftLeft));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SHIFT_LEFT_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpShiftLeft));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SHIFT_RIGHT:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpShiftRight));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_SHIFT_RIGHT_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpShiftRight));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_BITWISE_AND:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpBAnd));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_BITWISE_AND_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpBAnd));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_BITWISE_OR:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), IR.BinOp.OperationType.OpBOr));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_BITWISE_OR_BK:
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), IR.BinOp.OperationType.OpBOr));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_CONCAT:
                    args = new List <IR.Expression>();
                    for (int arg = (int)b; arg <= c; arg++)
                    {
                        args.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)arg)));
                    }
                    assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.Concat(args));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_JMP:
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 1 + sbx))));
                    break;

                case LuaOpCode.HKS_OPCODE_EQ:
                    var operation = IR.BinOp.OperationType.OpEqual;
                    if (a == 1)
                    {
                        operation = IR.BinOp.OperationType.OpNotEqual;
                    }
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 2)), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), operation)));
                    break;

                case LuaOpCode.HKS_OPCODE_EQ_BK:
                    operation = IR.BinOp.OperationType.OpEqual;
                    if (a == 1)
                    {
                        operation = IR.BinOp.OperationType.OpNotEqual;
                    }
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 2)), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), operation)));
                    break;

                case LuaOpCode.HKS_OPCODE_LT:
                    operation = IR.BinOp.OperationType.OpLessThan;
                    if (a == 1)
                    {
                        operation = IR.BinOp.OperationType.OpGreaterEqual;
                    }
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 2)), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), operation)));
                    break;

                case LuaOpCode.HKS_OPCODE_LT_BK:
                    operation = IR.BinOp.OperationType.OpLessThan;
                    if (a == 1)
                    {
                        operation = IR.BinOp.OperationType.OpGreaterEqual;
                    }
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 2)), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), operation)));
                    break;

                case LuaOpCode.HKS_OPCODE_LE:
                    operation = IR.BinOp.OperationType.OpLessEqual;
                    if (a == 1)
                    {
                        operation = IR.BinOp.OperationType.OpGreaterThan;
                    }
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 2)), new IR.BinOp(Register((uint)b), RKIRHKS(fun, c, szero), operation)));
                    break;

                case LuaOpCode.HKS_OPCODE_LE_BK:
                    operation = IR.BinOp.OperationType.OpLessEqual;
                    if (a == 1)
                    {
                        operation = IR.BinOp.OperationType.OpGreaterThan;
                    }
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 2)), new IR.BinOp(ToConstantIR(fun.Constants[(int)b]), Register((uint)c), operation)));
                    break;

                case LuaOpCode.HKS_OPCODE_TEST:
                case LuaOpCode.HKS_OPCODE_TEST_R1:
                    // This op is weird
                    if (c == 0)
                    {
                        instructions.Add(new IR.Jump(irfun.GetLabel((uint)((i / 4) + 2)), Register((uint)a)));
                    }
                    else
                    {
                        instructions.Add(new IR.Jump(irfun.GetLabel((uint)((i / 4) + 2)), new IR.UnaryOp(Register((uint)a), IR.UnaryOp.OperationType.OpNot)));
                    }
                    break;

                case LuaOpCode.HKS_OPCODE_TESTSET:
                    // This op is weird
                    if (c == 0)
                    {
                        instructions.Add(new IR.Jump(irfun.GetLabel((uint)((i / 4) + 2)), new IR.BinOp(RKIR(fun, b), new IR.Constant(0.0), IR.BinOp.OperationType.OpNotEqual)));
                    }
                    else
                    {
                        instructions.Add(new IR.Jump(irfun.GetLabel((uint)((i / 4) + 2)), new IR.BinOp(RKIR(fun, b), new IR.Constant(0.0), IR.BinOp.OperationType.OpEqual)));
                    }
                    instructions.Add(new IR.Assignment(SymbolTable.GetRegister(a), new IR.IdentifierReference(SymbolTable.GetRegister(b))));
                    break;

                case LuaOpCode.HKS_OPCODE_SETTABLE:
                case LuaOpCode.HKS_OPCODE_SETTABLE_S:
                    instructions.Add(new IR.Assignment(new IR.IdentifierReference(SymbolTable.GetRegister(a), Register(b)), RKIRHKS(fun, c, szero)));
                    break;

                case LuaOpCode.HKS_OPCODE_TAILCALL:
                case LuaOpCode.HKS_OPCODE_TAILCALL_I:
                case LuaOpCode.HKS_OPCODE_TAILCALL_I_R1:
                    args = new List <IR.Expression>();
                    for (int arg = (int)a + 1; arg < a + b; arg++)
                    {
                        args.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)arg)));
                    }
                    var funCall = new IR.FunctionCall(new IR.IdentifierReference(SymbolTable.GetRegister(a)), args);
                    funCall.IsIndeterminantArgumentCount = (b == 0);
                    funCall.BeginArg = a + 1;
                    instructions.Add(new IR.Return(funCall));
                    break;

                case LuaOpCode.HKS_OPCODE_SETTABLE_S_BK:
                    instructions.Add(new IR.Assignment(new IR.IdentifierReference(SymbolTable.GetRegister(a), ToConstantIR(fun.Constants[(int)b])), RKIRHKS(fun, c, szero)));
                    break;

                case LuaOpCode.HKS_OPCODE_CALL_I:
                case LuaOpCode.HKS_OPCODE_CALL_I_R1:
                case LuaOpCode.HKS_OPCODE_CALL:
                    args = new List <IR.Expression>();
                    rets = new List <IR.IdentifierReference>();
                    for (int arg = (int)a + 1; arg < a + b; arg++)
                    {
                        args.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)arg)));
                    }
                    for (int r = (int)a + 1; r < a + c; r++)
                    {
                        rets.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)r - 1)));
                    }
                    if (c == 0)
                    {
                        rets.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)a)));
                    }
                    funCall = new IR.FunctionCall(new IR.IdentifierReference(SymbolTable.GetRegister(a)), args);
                    funCall.IsIndeterminantArgumentCount = (b == 0);
                    funCall.IsIndeterminantReturnCount   = (c == 0);
                    funCall.BeginArg = a + 1;
                    assn             = new IR.Assignment(rets, funCall);
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_RETURN:
                    args = new List <IR.Expression>();
                    if (b != 0)
                    {
                        for (int arg = (int)a; arg < a + b - 1; arg++)
                        {
                            args.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)arg)));
                        }
                    }
                    var ret = new IR.Return(args);
                    if (b == 0)
                    {
                        ret.BeginRet = a;
                        ret.IsIndeterminantReturnCount = true;
                    }
                    instructions.Add(ret);
                    break;

                case LuaOpCode.HKS_OPCODE_FORLOOP:
                    instructions.Add(new IR.Assignment(new IR.IdentifierReference(SymbolTable.GetRegister(a)), new IR.BinOp(new IR.IdentifierReference(SymbolTable.GetRegister(a)),
                                                                                                                            new IR.IdentifierReference(SymbolTable.GetRegister(a + 2)), IR.BinOp.OperationType.OpAdd)));
                    var jmp = new IR.Jump(irfun.GetLabel((uint)(pc + 1 + sbx)), new IR.BinOp(new IR.IdentifierReference(SymbolTable.GetRegister(a)),
                                                                                             new IR.IdentifierReference(SymbolTable.GetRegister(a + 1)), IR.BinOp.OperationType.OpLoopCompare));
                    var pta = new IR.Assignment(SymbolTable.GetRegister(a + 3), Register((uint)a));
                    pta.PropogateAlways     = true;
                    jmp.PostTakenAssignment = pta;
                    instructions.Add(jmp);
                    break;

                case LuaOpCode.HKS_OPCODE_TFORLOOP:
                    args = new List <IR.Expression>();
                    rets = new List <IR.IdentifierReference>();
                    args.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)a + 1)));
                    args.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)a + 2)));
                    if (c == 0)
                    {
                        rets.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)a + 3)));
                    }
                    else
                    {
                        for (int r = (int)a + 3; r <= a + c + 2; r++)
                        {
                            rets.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)r)));
                        }
                    }
                    var fcall = new IR.FunctionCall(new IR.IdentifierReference(SymbolTable.GetRegister(a)), args);
                    fcall.IsIndeterminantReturnCount = (c == 0);
                    assn = new IR.Assignment(rets, fcall);
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)((i / 4) + 2)), new IR.BinOp(Register((uint)a + 3), new IR.Constant(IR.Constant.ConstantType.ConstNil), IR.BinOp.OperationType.OpEqual)));
                    instructions.Add(new IR.Assignment(SymbolTable.GetRegister(a + 2), new IR.IdentifierReference(SymbolTable.GetRegister(a + 3))));
                    break;

                case LuaOpCode.HKS_OPCODE_FORPREP:
                    // The VM technically does a subtract, but we don't actually emit it since it simplifies things to map better to the high level Lua
                    //instructions.Add(new IR.Assignment(new IR.IdentifierReference(SymbolTable.GetRegister(a)), new IR.BinOp(new IR.IdentifierReference(SymbolTable.GetRegister(a)),
                    //    new IR.IdentifierReference(SymbolTable.GetRegister(a + 2)), IR.BinOp.OperationType.OpSub)));
                    instructions.Add(new IR.Jump(irfun.GetLabel((uint)(pc + 1 + sbx))));
                    break;

                case LuaOpCode.HKS_OPCODE_SETLIST:
                    if (b == 0)
                    {
                        if (c == 1)
                        {
                            assn = new IR.Assignment(SymbolTable.GetRegister(a), Register(a + 1));
                            assn.VarargAssignmentReg   = a;
                            assn.IsIndeterminantVararg = true;
                            CheckLocal(assn, fun, pc);
                            instructions.Add(assn);
                        }
                    }
                    else
                    {
                        for (int j = 1; j <= b; j++)
                        {
                            assn = new IR.Assignment(new IR.IdentifierReference(SymbolTable.GetRegister(a), new IR.Constant((double)(c - 1) * 32 + j)),
                                                     new IR.IdentifierReference(SymbolTable.GetRegister(a + (uint)j)));
                            CheckLocal(assn, fun, pc);
                            instructions.Add(assn);
                        }
                    }
                    break;

                case LuaOpCode.HKS_OPCODE_CLOSURE:
                    instructions.Add(new IR.Assignment(SymbolTable.GetRegister(a), new IR.Closure(irfun.LookupClosure(bx))));
                    break;

                case LuaOpCode.HKS_OPCODE_GETFIELD:
                case LuaOpCode.HKS_OPCODE_GETFIELD_R1:
                    assn = new IR.Assignment(Register((uint)a), new IR.IdentifierReference(SymbolTable.GetRegister((uint)b), new IR.Constant(fun.Constants[(int)c].ToString())));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_DATA:
                    if (a != 0)
                    {
                        IR.Function closureFunc = null;
                        int         index       = pc;

                        while (index >= 0)
                        {
                            if (fun.Instructions[index].OpCode == LuaOpCode.HKS_OPCODE_CLOSURE)
                            {
                                closureFunc = irfun.LookupClosure(fun.Instructions[index].Bx);
                                break;
                            }
                            index--;
                        }

                        if (closureFunc == null)
                        {
                            continue;
                        }

                        if (a == 1)
                        {
                            closureFunc.UpvalueBindings.Add(SymbolTable.GetRegister(c));
                        }
                        else if (a == 2)
                        {
                            closureFunc.UpvalueBindings.Add(irfun.UpvalueBindings[(int)c]);
                        }
                    }
                    else
                    {
                        instructions.Add(new Data());
                    }
                    break;

                case LuaOpCode.HKS_OPCODE_SETFIELD:
                case LuaOpCode.HKS_OPCODE_SETFIELD_R1:
                    assn = new IR.Assignment(new IR.IdentifierReference(SymbolTable.GetRegister(a), new IR.Constant(fun.Constants[(int)b].ToString())), RKIRHKS(fun, c, szero));
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    break;

                case LuaOpCode.HKS_OPCODE_VARARG:
                    var vargs = new List <IR.IdentifierReference>();
                    for (int arg = (int)a; arg <= a + b - 1; arg++)
                    {
                        vargs.Add(new IR.IdentifierReference(SymbolTable.GetRegister((uint)arg)));
                    }
                    if (b != 0)
                    {
                        assn = new IR.Assignment(vargs, new IR.IdentifierReference(SymbolTable.GetVarargs()));
                    }
                    else
                    {
                        assn = new IR.Assignment(SymbolTable.GetRegister(a), new IR.IdentifierReference(SymbolTable.GetVarargs()));
                        assn.IsIndeterminantVararg = true;
                        assn.VarargAssignmentReg   = a;
                    }
                    CheckLocal(assn, fun, pc);
                    instructions.Add(assn);
                    irfun.IsVarargs = true;
                    break;

                case LuaOpCode.HKS_OPCODE_CLOSE:
                    // LUA source : close all variables in the stack up to (>=) R(A)
                    // Let's ignore this for now, doesn't print anything and don't know if it affects SSA
                    instructions.Add(new Close());
                    break;

                default:
                    Console.WriteLine($@"Missing op: {opcode} {a} {b} {c}");
                    instructions.Add(new IR.PlaceholderInstruction(($@"{opcode} {a} {b} {c}")));
                    break;
                }
                foreach (var inst in instructions)
                {
                    inst.OpLocation = i / 4;
                    irfun.AddInstruction(inst);
                }
            }
            irfun.ApplyLabels();

            // Simple post-ir and idiom recognition analysis passes
            irfun.ResolveVarargListAssignment(SymbolTable);
            irfun.MergeMultiBoolAssignment();
            irfun.EliminateRedundantAssignments();
            irfun.MergeConditionalJumps();
            irfun.MergeConditionalAssignments();
            //irfun.PeepholeOptimize();
            irfun.CheckControlFlowIntegrity();
            irfun.RemoveUnusedLabels();
            irfun.ClearDataInstructions();

            // Control flow graph construction and SSA conversion
            irfun.ConstructControlFlowGraph();
            irfun.ResolveIndeterminantArguments(SymbolTable);
            irfun.CompleteLua51Loops();

            // Upval resolution
            irfun.RegisterClosureUpvalues53(SymbolTable.GetAllRegistersInScope());

            irfun.ConvertToSSA(SymbolTable.GetAllRegistersInScope());

            // Data flow passes
            irfun.EliminateDeadAssignments(true);
            irfun.PerformExpressionPropogation();
            irfun.DetectListInitializers();

            // CFG passes
            irfun.StructureCompoundConditionals();
            irfun.DetectLoops();
            irfun.DetectLoopConditionals();
            irfun.DetectTwoWayConditionals();
            irfun.SimplifyIfElseFollowChain();

            irfun.EliminateDeadAssignments(true);
            irfun.PerformExpressionPropogation();
            irfun.VerifyLivenessNoInterference();

            // Convert out of SSA and rename variables
            irfun.DropSSADropSubscripts();
            irfun.AnnotateLocalDeclarations();

            irfun.RenameVariables();
            irfun.Parenthesize();
            irfun.AddEmptyLines();
            irfun.SearchInlineClosures();

            irfun.RemoveUnnecessaryReturns();

            // Convert to AST
            irfun.ConvertToAST(true);

            // Now generate IR for all the child closures
            for (int i = 0; i < fun.ChildFunctions.Count; i++)
            {
                GenerateIRHKS(irfun.LookupClosure((uint)i), fun.ChildFunctions[i]);
            }
            SymbolTable.EndScope();
        }
Exemple #5
0
        static void Main(string[] args)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Encoding outEncoding = Encoding.UTF8;
            // Super bad arg parser until I decide to use a better libary
            bool   writeFile   = true;
            string outfilename = null;
            string infilename  = null;
            int    arg         = 0;

            try
            {
                if (args[arg] == "-d")
                {
                    writeFile = false;
                    arg++;
                }
                else if (args[arg] == "-o")
                {
                    outfilename = args[arg + 1];
                    arg        += 2;
                }
                infilename = args[arg];
                if (outfilename == null)
                {
                    outfilename = Path.GetFileNameWithoutExtension(infilename) + ".dec.lua";
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Usage: DSLuaDecompiler.exe [options] inputfile.lua\n-o outputfile.lua\n-d Print output in console");
            }

            Console.OutputEncoding = outEncoding;
            //infilename = $@"E:\SteamLibrary\steamapps\common\DARK SOULS III\Game\script\aicommon-luabnd-dcx\script\ai\out\bin\goal_list.lua";
            //infilename = $@"C:\Users\katalash\Downloads\script_interroot (1)\script_interroot\ai\out\approach_target.lua.out";
            //infilename = $@"E:\soulsmodsstuff\soulsmodsgh\og\DSMapStudio\DecompileAllScripts\bin\Debug\net5.0\output\mismatches\aicommon.luabnd\walk_around_on_failed_path.lua";
            using (FileStream stream = File.OpenRead(infilename))
            {
                BinaryReaderEx br   = new BinaryReaderEx(false, stream);
                var            lua  = new LuaFile(br);
                IR.Function    main = new IR.Function();
                //LuaDisassembler.DisassembleFunction(lua.MainFunction);
                if (lua.Version == LuaFile.LuaVersion.Lua50)
                {
                    LuaDisassembler.GenerateIR50(main, lua.MainFunction);
                    outEncoding = Encoding.GetEncoding("shift_jis");
                }
                else if (lua.Version == LuaFile.LuaVersion.Lua51HKS)
                {
                    LuaDisassembler.GenerateIRHKS(main, lua.MainFunction);
                    outEncoding = Encoding.UTF8;
                }
                else if (lua.Version == LuaFile.LuaVersion.Lua53Smash)
                {
                    LuaDisassembler.GenerateIR53(main, lua.MainFunction, true);
                    outEncoding = Encoding.UTF8;
                }

                if (writeFile)
                {
                    File.WriteAllText(outfilename, main.ToString(), outEncoding);
                }
                else
                {
                    Console.WriteLine(main.ToString());
                }
            }
        }
Exemple #6
0
        internal FunctionEmitter(IR.Function function, MethodFactory methodFactory, FunctionLookup functionLookup)
        {
            Contract.Requires(function != null);
            Contract.Requires(methodFactory != null);
            Contract.Requires(functionLookup != null);

            this.declaration    = function;
            this.functionLookup = functionLookup;
            var signature = new FunctionSignature(function.Inputs.Select(i => i.StaticRepr), function.Outputs.Select(o => o.StaticRepr));

            // Determine the method signature
            var parameterDescriptors = new List <ParameterDescriptor>();

            foreach (var input in function.Inputs)
            {
                locals.Add(input, VariableLocation.Parameter(parameterDescriptors.Count));
                parameterDescriptors.Add(new ParameterDescriptor(input.StaticCliType, ParameterAttributes.None, input.Name));
            }

            Type returnType = typeof(void);

            if (function.Outputs.Length == 1)
            {
                returnType = function.Outputs[0].StaticCliType;                 // 1 output, use return value
            }
            else if (function.Outputs.Length >= 2)
            {
                // 2 or more outputs, use 'out' parameters
                foreach (var output in function.Outputs)
                {
                    string name = output.Name;
                    if (locals.ContainsKey(output))
                    {
                        // inout parameter, rename not to clash with input
                        name += "$out";
                    }
                    else
                    {
                        locals.Add(output, VariableLocation.Parameter(parameterDescriptors.Count));
                    }

                    var parameterType = output.StaticCliType.MakeByRefType();
                    parameterDescriptors.Add(new ParameterDescriptor(parameterType, ParameterAttributes.Out, name));
                }
            }

            // Create the method and get its IL generator
            ILGenerator ilGenerator;
            var         methodInfo = methodFactory(function.Name, parameterDescriptors, returnType, out ilGenerator);

            this.method = new FunctionMethod(methodInfo, signature);

            cil = new ILGeneratorMethodBodyWriter(ilGenerator);
            cil = new MethodBodyVerifier(new MethodBodyVerificationContext
            {
                Method         = methodInfo,
                ParameterTypes = parameterDescriptors.Select(p => p.Type).ToArray(),
                ReturnType     = returnType,
                HasInitLocals  = true,
                MaxStackSize   = ushort.MaxValue
            }, cil);

            temporaryPool = new TemporaryLocalPool(cil, "$temp");

            if (function.Outputs.Length == 1)
            {
                // Declare a local variable for the return value
                var output     = function.Outputs[0];
                var localIndex = cil.DeclareLocal(output.StaticCliType, output.Name);
                if (!function.Inputs.Contains(output))
                {
                    locals.Add(output, VariableLocation.Local(localIndex));
                }
            }
        }