public DecompileCache(ProjectFile pf) { Types = new AssetResolverTypes(pf); GlobalFunctionNames = new Dictionary <GMFunctionEntry, string>(); if (pf.DataHandle.VersionInfo.IsNumberAtLeast(2, 3)) { // Find all function names in global scripts GMChunkCODE code = pf.DataHandle.GetChunk <GMChunkCODE>(); Parallel.ForEach(pf.DataHandle.GetChunk <GMChunkGLOB>().List, scr => { GMCode entry = code.List[scr]; // Find fragments List <Fragment> fragments = Fragments.FindAndProcess(entry, false); // Find blocks in the main fragment that come after another fagment foreach (Block b in fragments[^ 1].Blocks.List) { if (b.AfterFragment && b.Instructions.Count > 2 && b.Instructions[0].Kind == GMCode.Bytecode.Instruction.Opcode.Push && b.Instructions[0].Type1 == GMCode.Bytecode.Instruction.DataType.Int32 && b.Instructions[0].Value == null) { string name = ASTBuilder.GetNameAfterFragment(b); if (name != null) { GMFunctionEntry func = b.Instructions[0].Function.Target; lock (GlobalFunctionNames) GlobalFunctionNames[func] = name; } } } });
public override void Unserialize(GMDataReader reader) { base.Unserialize(reader); FunctionEntries = new GMList <GMFunctionEntry>(); Locals = new GMList <GMLocalsEntry>(); if (reader.VersionInfo.FormatID <= 14) { int startOff = reader.Offset; while (reader.Offset + 12 <= startOff + Length) { GMFunctionEntry entry = new GMFunctionEntry(); entry.Unserialize(reader); FunctionEntries.Add(entry); } } else { FunctionEntries.Unserialize(reader); Locals.Unserialize(reader); } }