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); }
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() + ")"); }
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); }
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; }
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(); }
// TODO: guess for loop, probably requires a large restructure public Statement DecompileForEach(bool isDynArray = false) { 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; }
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; }
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); } } } }