void worker_DoWork(object sender, DoWorkEventArgs e) { GeneratorWorkerArgs args = (GeneratorWorkerArgs)e.Argument; Dictionary<string, MetaMap> globalMaps = new Dictionary<string, MetaMap>(); DateTime startTime = DateTime.Now; List<string> mapFiles = Directory.EnumerateFiles(args.InputFolder, "*.map").ToList(); for (int i = mapFiles.Count - 1; i >= 0; i--) { if (mapFiles[i].EndsWith("shared.map") || mapFiles[i].EndsWith("campaign.map")) mapFiles.RemoveAt(i); } for (int i = 0; i < mapFiles.Count; i++) { Dictionary<ITag, MetaMap> tagMaps = new Dictionary<ITag, MetaMap>(); IReader reader; ICacheFile cacheFile = LoadMap(mapFiles[i], out reader); MetaAnalyzer analyzer = new MetaAnalyzer(cacheFile); Queue<MetaMap> mapsToProcess = new Queue<MetaMap>(); foreach (ITag tag in cacheFile.Tags) { if (tag.MetaLocation.AsAddress() > 0) { MetaMap map = new MetaMap(); tagMaps[tag] = map; mapsToProcess.Enqueue(map); reader.SeekTo(tag.MetaLocation.AsOffset()); analyzer.AnalyzeArea(reader, tag.MetaLocation.AsAddress(), map); } } GenerateSubMaps(mapsToProcess, analyzer, reader, cacheFile); Dictionary<string, MetaMap> classMaps = new Dictionary<string, MetaMap>(); foreach (ITag tag in cacheFile.Tags) { if (tag.MetaLocation.AsAddress() > 0) { MetaMap map = tagMaps[tag]; EstimateMapSize(map, tag.MetaLocation.AsAddress(), analyzer.GeneratedMemoryMap, 1); string magicStr = CharConstant.ToString(tag.Class.Magic); MetaMap oldClassMap; if (classMaps.TryGetValue(magicStr, out oldClassMap)) oldClassMap.MergeWith(map); else classMaps[magicStr] = map; } } foreach (KeyValuePair<string, MetaMap> map in classMaps) { MetaMap globalMap; if (globalMaps.TryGetValue(map.Key, out globalMap)) globalMap.MergeWith(map.Value); else globalMaps[map.Key] = map.Value; } reader.Close(); args.Worker.ReportProgress(100 * i / (mapFiles.Count - 1)); } string badChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); foreach (KeyValuePair<string, MetaMap> map in globalMaps) { string filename = map.Key; foreach (char badChar in badChars) filename = filename.Replace(badChar, '_'); filename += ".xml"; string path = Path.Combine(args.OutputFolder, filename); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t"; XmlWriter writer = XmlWriter.Create(path, settings); AssemblyPluginWriter pluginWriter = new AssemblyPluginWriter(writer, "Halo4"); int size = map.Value.GetBestSizeEstimate(); FoldSubMaps(map.Value); pluginWriter.EnterPlugin(size); pluginWriter.EnterRevisions(); pluginWriter.VisitRevision(new PluginRevision("Assembly", 1, "Generated plugin from scratch.")); pluginWriter.LeaveRevisions(); WritePlugin(map.Value, size, pluginWriter); pluginWriter.LeavePlugin(); writer.Dispose(); } DateTime endTime = DateTime.Now; e.Result = endTime.Subtract(startTime); }
private void GenerateSubMaps(Queue<MetaMap> maps, MetaAnalyzer analyzer, IReader reader, ICacheFile cacheFile) { Dictionary<uint, MetaMap> generatedMaps = new Dictionary<uint, MetaMap>(); while (maps.Count > 0) { MetaMap map = maps.Dequeue(); foreach (MetaValueGuess guess in map.Guesses) { if (guess.Type == MetaValueType.Reflexive) { MetaMap subMap; if (!generatedMaps.TryGetValue(guess.Pointer, out subMap)) { subMap = new MetaMap(); reader.SeekTo(cacheFile.MetaPointerConverter.AddressToOffset(guess.Pointer)); analyzer.AnalyzeArea(reader, guess.Pointer, subMap); maps.Enqueue(subMap); generatedMaps[guess.Pointer] = subMap; } map.AssociateSubMap(guess.Offset, subMap); } } } }