private void StartFunctionScan(byte[] data) { DecompiledScriptBlocks.ClearEx(); TokenList.ClearEx(); ScriptHeaderBlocks.ClearEx(); ScriptFooterBlocks.ClearEx(); if (CurrentLoadedExport.FileRef.Game == MEGame.ME3) { var func = new ME3Explorer.Unreal.Classes.Function(data, CurrentLoadedExport, CurrentLoadedExport.ClassName == "State" ? Convert.ToInt32(StartOffset_Changer.Text) : 32); func.ParseFunction(); DecompiledScriptBlocks.Add(func.GetSignature()); DecompiledScriptBlocks.AddRange(func.ScriptBlocks); TokenList.AddRange(func.SingularTokenList); int pos = 12; var functionSuperclass = BitConverter.ToInt32(CurrentLoadedExport.Data, pos); ScriptHeaderBlocks.Add(new ScriptHeaderItem("Function superclass", functionSuperclass, pos, functionSuperclass != 0 ? CurrentLoadedExport.FileRef.getEntry(functionSuperclass) : null)); pos += 4; var nextItemCompilingChain = BitConverter.ToInt32(CurrentLoadedExport.Data, pos); ScriptHeaderBlocks.Add(new ScriptHeaderItem("Next item in loading chain", nextItemCompilingChain, pos, nextItemCompilingChain > 0 ? CurrentLoadedExport : null)); pos += 4; nextItemCompilingChain = BitConverter.ToInt32(CurrentLoadedExport.Data, pos); ScriptHeaderBlocks.Add(new ScriptHeaderItem("Children Probe Start", nextItemCompilingChain, pos, nextItemCompilingChain > 0 ? CurrentLoadedExport : null)); pos += 4; ScriptHeaderBlocks.Add(new ScriptHeaderItem("Unknown 2 (Memory size?)", BitConverter.ToInt32(CurrentLoadedExport.Data, pos), pos)); pos += 4; ScriptHeaderBlocks.Add(new ScriptHeaderItem("Size", BitConverter.ToInt32(CurrentLoadedExport.Data, pos), pos)); pos = CurrentLoadedExport.Data.Length - 6; string flagStr = func.GetFlags(); ScriptFooterBlocks.Add(new ScriptHeaderItem("Native Index", BitConverter.ToInt16(CurrentLoadedExport.Data, pos), pos)); pos += 2; ScriptFooterBlocks.Add(new ScriptHeaderItem("Flags", $"0x{BitConverter.ToInt32(CurrentLoadedExport.Data, pos).ToString("X8")} {func.GetFlags().Substring(6)}", pos)); } else if (CurrentLoadedExport.FileRef.Game == MEGame.ME1) { //Header int pos = 16; var nextItemCompilingChain = BitConverter.ToInt32(CurrentLoadedExport.Data, pos); ScriptHeaderBlocks.Add(new ScriptHeaderItem("Next item in loading chain", nextItemCompilingChain, pos, nextItemCompilingChain > 0 ? CurrentLoadedExport : null)); pos += 8; nextItemCompilingChain = BitConverter.ToInt32(CurrentLoadedExport.Data, pos); ScriptHeaderBlocks.Add(new ScriptHeaderItem("Children Probe Start", nextItemCompilingChain, pos, nextItemCompilingChain > 0 ? CurrentLoadedExport : null)); pos += 4; ScriptHeaderBlocks.Add(new ScriptHeaderItem("Unknown 1 (??)", BitConverter.ToInt32(CurrentLoadedExport.Data, pos), pos)); pos += 4; ScriptHeaderBlocks.Add(new ScriptHeaderItem("Unknown 2 (Line??)", BitConverter.ToInt32(CurrentLoadedExport.Data, pos), pos)); pos += 4; ScriptHeaderBlocks.Add(new ScriptHeaderItem("Unknown 3 (TextPos??)", BitConverter.ToInt32(CurrentLoadedExport.Data, pos), pos)); pos += 4; ScriptHeaderBlocks.Add(new ScriptHeaderItem("Script Size", BitConverter.ToInt32(CurrentLoadedExport.Data, pos), pos)); pos += 4; BytecodeStart = pos; var func = UE3FunctionReader.ReadFunction(CurrentLoadedExport); func.Decompile(new TextBuilder(), false); //parse bytecode bool defined = func.HasFlag("Defined"); if (defined) { DecompiledScriptBlocks.Add(func.FunctionSignature + " {"); } else { DecompiledScriptBlocks.Add(func.FunctionSignature); } for (int i = 0; i < func.Statements.statements.Count; i++) { Statement s = func.Statements.statements[i]; DecompiledScriptBlocks.Add(s); if (s.Reader != null && i == 0) { //Add tokens read from statement. All of them point to the same reader, so just do only the first one. TokenList.AddRange(s.Reader.ReadTokens.Select(x => x.ToBytecodeSingularToken(pos)).OrderBy(x => x.StartPos)); } } if (defined) { DecompiledScriptBlocks.Add("}"); } //Footer pos = CurrentLoadedExport.Data.Length - (func.HasFlag("Net") ? 17 : 15); string flagStr = func.GetFlags(); ScriptFooterBlocks.Add(new ScriptHeaderItem("Native Index", BitConverter.ToInt16(CurrentLoadedExport.Data, pos), pos)); pos += 2; ScriptFooterBlocks.Add(new ScriptHeaderItem("Operator Precedence", CurrentLoadedExport.Data[pos], pos)); pos++; int functionFlags = BitConverter.ToInt32(CurrentLoadedExport.Data, pos); ScriptFooterBlocks.Add(new ScriptHeaderItem("Flags", $"0x{functionFlags.ToString("X8")} {flagStr}", pos)); pos += 4; //if ((functionFlags & func._flagSet.GetMask("Net")) != 0) //{ //ScriptFooterBlocks.Add(new ScriptHeaderItem("Unknown 1 (RepOffset?)", BitConverter.ToInt16(CurrentLoadedExport.Data, pos), pos)); //pos += 2; //} int friendlyNameIndex = BitConverter.ToInt32(CurrentLoadedExport.Data, pos); ScriptFooterBlocks.Add(new ScriptHeaderItem("Friendly Name Table Index", $"0x{friendlyNameIndex.ToString("X8")} {CurrentLoadedExport.FileRef.getNameEntry(friendlyNameIndex)}", pos)); pos += 4; ScriptFooterBlocks.Add(new ScriptHeaderItem("Unknown 2", $"0x{BitConverter.ToInt16(CurrentLoadedExport.Data, pos).ToString("X4")}", pos)); pos += 4; //ME1Explorer.Unreal.Classes.Function func = new ME1Explorer.Unreal.Classes.Function(data, CurrentLoadedExport.FileRef as ME1Package); //try //{ // Function_TextBox.Text = func.ToRawText(); //} //catch (Exception e) //{ // Function_TextBox.Text = "Error parsing function: " + e.Message; //} } else { //Function_TextBox.Text = "Parsing UnrealScript Functions for this game is not supported."; } }