예제 #1
0
        int decompileFile(string file)
        {
            string name   = Path.GetFileNameWithoutExtension(file);
            var    stream = new FileStream(file, FileMode.Open);
            var    pcc    = new PCCFile(new PCCStreamReader(stream), name);

            pcc.DeserializeTables();
            pcc.DeserializeObjects();
            var deps = pcc.ImportPackageNames;

            pcc.ResolveLinks();
            var dumpPath = outputTextField.Text + @"\" + pcc.Name + @"\";

            System.IO.Directory.CreateDirectory(dumpPath);

            foreach (var exp in pcc.Exports.Where(e => e.ClassName.ToLower() == "class"))
            {
                var obj         = exp.Object as ME3Class;
                var convert     = new ME3ObjectConverter(obj);
                var ast         = convert.ConvertClass();
                var CodeBuilder = new CodeBuilderVisitor();
                ast.AcceptVisitor(CodeBuilder);
                File.WriteAllLines(dumpPath + exp.ObjectName + ".txt", CodeBuilder.GetCodeLines());
            }
            stream.Close();
            return(1);
        }
예제 #2
0
        public Expression DecompileContext(bool isClass = false)
        {
            PopByte();

            var left = DecompileExpression();

            if (left == null)
            {
                return(null); // ERROR
            }
            ReadInt16();      // discard MemSize value. (size of expr-right in half-bytes)
            ReadObject();     // discard RetValRef.
            ReadByte();       // discard unknown byte.

            isInClassContext = isClass;
            var right = DecompileExpression();

            if (right == null)
            {
                return(null); // ERROR
            }
            isInClassContext = false;

            if (isClass)
            {
                var builder = new CodeBuilderVisitor(); // what a wonderful hack, TODO.
                left.AcceptVisitor(builder);
                var str = builder.GetCodeString() + ".static";
                left = new SymbolReference(null, null, null, str);
            }

            StartPositions.Pop();
            return(new CompositeSymbolRef(left, right, null, null));
        }
예제 #3
0
        public static (ASTNode node, string text) DecompileExport(ExportEntry export, FileLib lib = null)
        {
            try
            {
                ASTNode astNode = null;
                switch (export.ClassName)
                {
                case "Class":
                    astNode = ME3ObjectToASTConverter.ConvertClass(export.GetBinaryData <UClass>(), true, lib);
                    break;

                case "Function":
                    astNode = ME3ObjectToASTConverter.ConvertFunction(export.GetBinaryData <UFunction>(), lib: lib);
                    break;

                case "State":
                    astNode = ME3ObjectToASTConverter.ConvertState(export.GetBinaryData <UState>(), lib: lib);
                    break;

                case "Enum":
                    astNode = ME3ObjectToASTConverter.ConvertEnum(export.GetBinaryData <UEnum>());
                    break;

                case "ScriptStruct":
                    astNode = ME3ObjectToASTConverter.ConvertStruct(export.GetBinaryData <UScriptStruct>());
                    break;

                default:
                    if (export.ClassName.EndsWith("Property") && ObjectBinary.From(export) is UProperty uProp)
                    {
                        astNode = ME3ObjectToASTConverter.ConvertVariable(uProp);
                    }
                    else
                    {
                        astNode = ME3ObjectToASTConverter.ConvertDefaultProperties(export);
                    }

                    break;
                }

                if (astNode != null)
                {
                    var codeBuilder = new CodeBuilderVisitor();
                    astNode.AcceptVisitor(codeBuilder);
                    return(astNode, codeBuilder.GetCodeString());
                }
            }
            catch (Exception e) when(!App.IsDebug)
            {
                return(null, $"Error occured while decompiling {export?.InstancedFullPath}:\n\n{e.FlattenException()}");
            }

            return(null, "Could not decompile!");
        }
예제 #4
0
        public Expression DecompileAssert()
        {
            PopByte();
            var unkn1 = ReadUInt16(); // memoff?
            var unkn2 = ReadByte();   // true/false?
            var expr  = DecompileExpression();

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

            expr.AcceptVisitor(builder);

            StartPositions.Pop();
            return(new SymbolReference(null, null, null, "ASSERT[" + unkn1.ToString("X4") + "|" + unkn2.ToString("X2") + "](" + builder.ToString() + ")"));
        }
예제 #5
0
        public Expression DecompileDynArrFunction(String name, bool secondArg = false, bool withoutMemOffs = false, bool withoutTrailingByte = false)
        {
            PopByte();
            var arr = DecompileExpression();

            if (arr == null)
            {
                return(null);
            }

            if (!withoutMemOffs)
            {
                ReadInt16(); // MemSize
            }
            var args = new List <Expression>();

            if (secondArg)
            {
                var prop = DecompileExpression();
                if (prop == null)
                {
                    return(null);
                }
                args.Add(prop);
            }

            var value = DecompileExpression();

            if (value == null)
            {
                return(null);
            }
            args.Add(value);

            if (!withoutTrailingByte)
            {
                PopByte();                          // EndFuncParms
            }
            var builder = new CodeBuilderVisitor(); // what a wonderful hack, TODO.

            arr.AcceptVisitor(builder);

            StartPositions.Pop();
            // TODO: ugly solution, should be reworked once dynarrays are in the AST.
            return(new FunctionCall(new SymbolReference(null, null, null, builder.GetCodeString() + "." + name), args, null, null));
        }
예제 #6
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);
                    }
                }
            }
        }
예제 #7
0
        public void TestLoadUncompressed()
        {
            var loaded = new List <PCCFile>();

            /*var corepath = @"G:\Code\ME3\temp\Core.pcc";
             * var corestream = new FileStream(corepath, FileMode.Open);
             * var corepcc = new PCCFile(new PCCStreamReader(corestream), "Core");
             * Assert.IsTrue(corepcc.DeserializeTables());
             * Assert.IsTrue(corepcc.DeserializeObjects());
             * corepcc.ResolveLinks();
             * loaded.Add(corepcc);
             *
             * var enginepath = @"G:\Code\ME3\temp\Engine.pcc";
             * var enginestream = new FileStream(enginepath, FileMode.Open);
             * var enginepcc = new PCCFile(new PCCStreamReader(enginestream), "Engine");
             * Assert.IsTrue(enginepcc.DeserializeTables());
             * Assert.IsTrue(enginepcc.DeserializeObjects());
             * Assert.IsTrue(enginepcc.ResolveLinks());
             * enginepcc.LoadDependencies(loaded);
             * loaded.Add(enginepcc);
             *
             * var frameworkpath = @"G:\Code\ME3\temp\GameFramework.pcc";
             * var frameworkstream = new FileStream(frameworkpath, FileMode.Open);
             * var frameworkpcc = new PCCFile(new PCCStreamReader(frameworkstream), "GameFramework");
             * Assert.IsTrue(frameworkpcc.DeserializeTables());
             * Assert.IsTrue(frameworkpcc.DeserializeObjects());
             * Assert.IsTrue(frameworkpcc.ResolveLinks());
             * frameworkpcc.LoadDependencies(loaded);
             * loaded.Add(frameworkpcc);
             *
             * var onlinepath = @"G:\Code\ME3\temp\SFXOnlineFoundation.pcc";
             * var onlinestream = new FileStream(onlinepath, FileMode.Open);
             * var onlinepcc = new PCCFile(new PCCStreamReader(onlinestream), "SFXOnlineFoundation");
             * Assert.IsTrue(onlinepcc.DeserializeTables());
             * Assert.IsTrue(onlinepcc.DeserializeObjects());
             * Assert.IsTrue(onlinepcc.ResolveLinks());
             * onlinepcc.LoadDependencies(loaded);
             * loaded.Add(onlinepcc);
             *
             * var uipath = @"G:\Code\ME3\temp\GFxUI.pcc";
             * var uistream = new FileStream(uipath, FileMode.Open);
             * var uipcc = new PCCFile(new PCCStreamReader(uistream), "GFxUI");
             * Assert.IsTrue(uipcc.DeserializeTables());
             * Assert.IsTrue(uipcc.DeserializeObjects());
             * Assert.IsTrue(uipcc.ResolveLinks());
             * uipcc.LoadDependencies(loaded);
             * loaded.Add(uipcc);
             *
             * var wwisepath = @"G:\Code\ME3\temp\WwiseAudio.pcc";
             * var wwisestream = new FileStream(wwisepath, FileMode.Open);
             * var wwisepcc = new PCCFile(new PCCStreamReader(wwisestream), "WwiseAudio");
             * Assert.IsTrue(wwisepcc.DeserializeTables());
             * Assert.IsTrue(wwisepcc.DeserializeObjects());
             * Assert.IsTrue(wwisepcc.ResolveLinks());
             * wwisepcc.LoadDependencies(loaded);
             * loaded.Add(wwisepcc);
             *
             * var SFXGamepath = @"G:\Code\ME3\temp\SFXGame.pcc";
             * var SFXGamestream = new FileStream(SFXGamepath, FileMode.Open);
             * var SFXGamepcc = new PCCFile(new PCCStreamReader(SFXGamestream), "SFXGame");
             * Assert.IsTrue(SFXGamepcc.DeserializeTables());
             * Assert.IsTrue(SFXGamepcc.DeserializeObjects());
             * Assert.IsTrue(SFXGamepcc.ResolveLinks());
             * SFXGamepcc.LoadDependencies(loaded);
             * loaded.Add(SFXGamepcc); */

            //var path = @"G:\Code\ME3\temp\SFXWeapon_Pistol_Carnifex.pcc";
            //var stream = new FileStream(path, FileMode.Open);
            //var pcc = new PCCFile(new PCCStreamReader(stream), "SFXWeapon_Pistol_Carnifex");

            //var path = @"G:\Code\ME3\temp\SFXWeapon_Heavy_ArcProjector.pcc";
            //var stream = new FileStream(path, FileMode.Open);
            //var pcc = new PCCFile(new PCCStreamReader(stream), "SFXWeapon_Heavy_ArcProjector");

            //var path = @"G:\Code\ME3\temp\SFXPawn_Brute.pcc";
            //var stream = new FileStream(path, FileMode.Open);
            //var pcc = new PCCFile(new PCCStreamReader(stream), "SFXPawn_Brute");

            //var path = @"G:\Code\ME3\temp\Asari_Adept_MP.pcc";
            //var stream = new FileStream(path, FileMode.Open);
            //var pcc = new PCCFile(new PCCStreamReader(stream), "Asari_Adept_MP");

            var path   = @"G:\Code\ME3\temp\SFXGame.pcc";
            var stream = new FileStream(path, FileMode.Open);
            var pcc    = new PCCFile(new PCCStreamReader(stream), "SFXGame");

            //var path = @"G:\Code\ME3\temp\BIOP_MP_COMMON.pcc";
            //var stream = new FileStream(path, FileMode.Open);
            //var pcc = new PCCFile(new PCCStreamReader(stream), "BIOP_MP_COMMON");

            //var path = @"G:\Code\ME3\temp\TM\BioD_ProMar_750Finale.pcc";
            //var stream = new FileStream(path, FileMode.Open);
            //var pcc = new PCCFile(new PCCStreamReader(stream), "BioD_ProMar_750Finale");

            Assert.IsTrue(pcc.DeserializeTables());
            Assert.IsTrue(pcc.DeserializeObjects());
            var deps = pcc.ImportPackageNames;

            /*foreach (var dep in deps.Where(x => !loaded.Any(p => p.Name == x)))
             * {
             *  var depPath = @"G:\Code\ME3\temp\" + dep + ".pcc";
             *  var depStream = new FileStream(depPath, FileMode.Open);
             *  var depPCC = new PCCFile(new PCCStreamReader(depStream), dep);
             *  Assert.IsTrue(depPCC.DeserializeTables());
             *  Assert.IsTrue(depPCC.DeserializeObjects());
             *  loaded.Add(depPCC);
             * }
             *
             * pcc.LoadDependencies(loaded);*/
            Assert.IsTrue(pcc.ResolveLinks());

            var dumpPath = @"G:\Code\ME3\temp\dump\" + pcc.Name + @"\";

            System.IO.Directory.CreateDirectory(dumpPath);

            foreach (var exp in pcc.Exports.Where(e => e.ClassName.ToLower() == "class"))
            {
                var obj         = exp.Object as ME3Class;
                var convert     = new ME3ObjectConverter(obj);
                var ast         = convert.ConvertClass();
                var CodeBuilder = new CodeBuilderVisitor();
                ast.AcceptVisitor(CodeBuilder);
                File.WriteAllLines(dumpPath + exp.ObjectName + ".txt", CodeBuilder.GetCodeLines());
            }

            /*foreach (var exp in pcc.Exports.Where(e => e.ClassName.ToLower() == "class"))
             * {
             *  var obj = exp.Object as ME3Class;
             *  var convert = new ME3ObjectConverter(obj);
             *  var ast = convert.ConvertClass();
             *  foreach (var func in ast.Functions)
             *  {
             *      Console.WriteLine("------------------------------" + func.Name + "------------------------------");
             *      var CodeBuilder = new CodeBuilderVisitor();
             *      func.AcceptVisitor(CodeBuilder);
             *      Console.Write(CodeBuilder.GetCodeString());
             *      Console.WriteLine("");
             *  }
             * }*/

            stream.Close();
        }
예제 #8
0
        public void BasicClassTest()
        {
            var source =
                "class Test Deprecated Transient; \n" +
                "var enum ETestnumeration {\n" +
                "     TEST_value1,\n" +
                "     TEST_value2,\n" +
                "     TEST_value3,\n" +
                "} inlineNumeration, testnum2;\n" +
                "var private deprecated int X; \n" +
                "VAR INT Y, Z; \n" +
                "var ETestnumeration testnum;\n" +
                "struct transient testStruct\n" +
                "{ var float a, b, c; };\n" +
                "var private struct transient twoStruct extends testStruct\n" +
                "{\n" +
                "   var etestnumeration num;\n" +
                "} structA, structB;\n" +
                "function float funcB( testStruct one, float two ) \n" +
                "{\n" +
                "   local float c;" +
                "   one.a = 1.3 * c;" +
                "   while (true)" +
                "   {" +
                "       c = c - c - c;" +
                "   }" +
                "   if (false) {" +
                "       switch(one.a) {" +
                "           case one.a:" +
                "               c = one.a;" +
                "               break;" +
                "           case 1.2:" +
                "           case 1.3:" +
                "               c = c + 0.5;" +
                "               break;" +
                "           default:" +
                "               c = 6.6;" +
                "       }" +
                "   }" +
                "   return one.a + 0.33 * (0.66 + 0.1) * 1.5;\n" +
                "}\n" +
                "private simulated function float MyFunc( out testStruct one, coerce optional float two ) \n" +
                "{\n" +
                "   return one.b + funcB(one, two);\n" +
                "}\n" +
                "auto state MyState\n" +
                "{\n" +
                "ignores MyFunc;\n" +
                "function StateFunc()\n" +
                "{\n" +
                "}\n" +
                "\n" +
                "Begin:\n" +
                "       moredragons\n" +
                "}\n" +
                "\n" +
                "final static operator(254) int >>>( coerce float left, coerce float right )\n" +
                "{\n" +
                "   all the dragons\n" +
                "}\n" +
                "\n" +
                "\n" +
                "\n";

            var parser  = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            var symbols = new SymbolTable();

            Class obj = new Class("Object", null, null, null, null, null, null, null, null, null, null);

            obj.OuterClass = obj;
            symbols.PushScope(obj.Name);
            symbols.AddSymbol(obj.Name, obj);

            VariableType integer = new VariableType("int", null, null);

            symbols.AddSymbol(integer.Name, integer);
            VariableType floatingpoint = new VariableType("float", null, null);

            symbols.AddSymbol(floatingpoint.Name, floatingpoint);

            InOpDeclaration plus_float = new InOpDeclaration("+", 20, false, null, floatingpoint, new FunctionParameter(floatingpoint, null, null, null, null),
                                                             new FunctionParameter(floatingpoint, null, null, null, null), null, null, null);

            symbols.AddOperator(plus_float);

            InOpDeclaration sub_float = new InOpDeclaration("-", 20, false, null, floatingpoint, new FunctionParameter(floatingpoint, null, null, null, null),
                                                            new FunctionParameter(floatingpoint, null, null, null, null), null, null, null);

            symbols.AddOperator(sub_float);

            InOpDeclaration mult_float = new InOpDeclaration("*", 16, false, null, floatingpoint, new FunctionParameter(floatingpoint, null, null, null, null),
                                                             new FunctionParameter(floatingpoint, null, null, null, null), null, null, null);

            symbols.AddOperator(mult_float);

            Class node           = (Class)parser.ParseDocument();
            var   ClassValidator = new ClassValidationVisitor(log, symbols);

            node.AcceptVisitor(ClassValidator);

            symbols.GoDirectlyToStack(node.GetInheritanceString());
            foreach (Function f in node.Functions)
            {
                symbols.PushScope(f.Name);
                var p = new CodeBodyParser(new TokenStream <String>(new StringLexer(source)), f.Body, symbols, f, log);
                var b = p.ParseBody();
                symbols.PopScope();
            }

            var CodeBuilder = new CodeBuilderVisitor();

            node.AcceptVisitor(CodeBuilder);
            Console.Write(CodeBuilder.GetCodeString());

            Assert.IsTrue(log.AllErrors.Count == 0);

            return;
        }
예제 #9
0
        public Statement DecompileForEach(bool isDynArray = false) // TODO: guess for loop, probably requires a large restructure
        {
            PopByte();
            var scopeStatements = new List <Statement>();

            var iteratorFunc = DecompileExpression();

            if (iteratorFunc == null)
            {
                return(null);
            }

            Expression dynArrVar   = null;
            Expression dynArrIndex = null;
            bool       unknByte    = false;

            if (isDynArray)
            {
                dynArrVar   = DecompileExpression();
                unknByte    = Convert.ToBoolean(ReadByte());
                dynArrIndex = DecompileExpression();
            }

            var scopeEnd = ReadUInt16(); // MemOff

            ForEachScopes.Push(scopeEnd);

            Scopes.Add(scopeStatements);
            CurrentScope.Push(Scopes.Count - 1);
            while (Position < Size)
            {
                if (CurrentIs(StandardByteCodes.IteratorNext) && PeekByte == (byte)StandardByteCodes.IteratorPop)
                {
                    PopByte(); // IteratorNext
                    PopByte(); // IteratorPop
                    break;
                }

                var current = DecompileStatement();
                if (current == null)
                {
                    return(null); // ERROR ?
                }
                scopeStatements.Add(current);
            }
            CurrentScope.Pop();
            ForEachScopes.Pop();

            if (isDynArray)
            {
                var builder = new CodeBuilderVisitor(); // what a wonderful hack, TODO.
                iteratorFunc.AcceptVisitor(builder);
                var arrayName  = new SymbolReference(null, null, null, builder.GetCodeString());
                var parameters = new List <Expression>()
                {
                    dynArrVar, dynArrIndex
                };
                iteratorFunc = new FunctionCall(arrayName, parameters, null, null);
            }

            var statement = new ForEachLoop(iteratorFunc, new CodeBody(scopeStatements, null, null), null, null);

            StatementLocations.Add(StartPositions.Pop(), statement);
            return(statement);
        }
예제 #10
0
        public static bool ResolveAllClassesInPackage(IMEPackage pcc, ref SymbolTable symbols)
        {
            string fileName = Path.GetFileNameWithoutExtension(pcc.FilePath);

#if DEBUGSCRIPT
            string dumpFolderPath = Path.Combine(ME3Directory.gamePath, "ScriptDump", fileName);
            Directory.CreateDirectory(dumpFolderPath);
#endif
            var log = new MessageLog();
            Debug.WriteLine($"{fileName}: Beginning Parse.");
            var classes = new List <(Class ast, string scriptText)>();
            foreach (ExportEntry export in pcc.Exports.Where(exp => exp.IsClass))
            {
                Class  cls        = ME3ObjectToASTConverter.ConvertClass(export.GetBinaryData <UClass>(), false);
                string scriptText = "";
                try
                {
#if DEBUGSCRIPT
                    var codeBuilder = new CodeBuilderVisitor();
                    cls.AcceptVisitor(codeBuilder);
                    scriptText = codeBuilder.GetCodeString();
                    File.WriteAllText(Path.Combine(dumpFolderPath, $"{cls.Name}.uc"), scriptText);
                    var parser = new ClassOutlineParser(new TokenStream <string>(new StringLexer(scriptText, log)), log);
                    cls = parser.TryParseClass();
                    if (cls == null || log.Content.Any())
                    {
                        DisplayError(scriptText, log.ToString());
                        return(false);
                    }
#endif

                    if (export.ObjectName == "Object")
                    {
                        symbols = SymbolTable.CreateIntrinsicTable(cls);
                    }
                    else
                    {
                        symbols.AddType(cls);
                    }

                    classes.Add(cls, scriptText);
                }
                catch (Exception e) when(!App.IsDebug)
                {
                    DisplayError(scriptText, log.ToString());
                    return(false);
                }
            }
            Debug.WriteLine($"{fileName}: Finished parse.");
            foreach (var validationPass in Enums.GetValues <ValidationPass>())
            {
                foreach ((Class ast, string scriptText) in classes)
                {
                    try
                    {
                        var validator = new ClassValidationVisitor(log, symbols, validationPass);
                        ast.AcceptVisitor(validator);
                        if (log.Content.Any())
                        {
                            DisplayError(scriptText, log.ToString());
                            return(false);
                        }
                    }
                    catch (Exception e) when(!App.IsDebug)
                    {
                        DisplayError(scriptText, log.ToString());
                        return(false);
                    }
                }
                Debug.WriteLine($"{fileName}: Finished validation pass {validationPass}.");
            }

            switch (fileName)
            {
            case "Core":
                symbols.InitializeOperators();
                break;

            case "Engine":
                symbols.ValidateIntrinsics();
                break;
            }

#if DEBUGSCRIPT
            //parse function bodies for testing purposes
            foreach ((Class ast, string scriptText) in classes)
            {
                symbols.RevertToObjectStack();
                if (!ast.Name.CaseInsensitiveEquals("Object"))
                {
                    symbols.GoDirectlyToStack(((Class)ast.Parent).GetInheritanceString());
                    symbols.PushScope(ast.Name);
                }

                foreach (Function function in ast.Functions.Where(func => !func.IsNative && func.IsDefined))
                {
                    CodeBodyParser.ParseFunction(function, scriptText, symbols, log);
                    if (log.Content.Any())
                    {
                        DisplayError(scriptText, log.ToString());
                    }
                }
            }
#endif


            symbols.RevertToObjectStack();

            return(true);
        }