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 WritePlugin(MetaMap map, int size, AssemblyPluginWriter writer) { for (int offset = 0; offset < size; offset += 4) { MetaValueGuess guess = map.GetGuess(offset); if (guess != null) { switch (guess.Type) { case MetaValueType.DataReference: if (offset <= size - 0x14) { writer.VisitDataReference("Unknown", (uint)offset, false, 0); offset += 0x10; continue; } break; case MetaValueType.TagReference: if (offset <= size - 0x10) { writer.VisitTagReference("Unknown", (uint)offset, false, true, true, 0); offset += 0xC; continue; } break; case MetaValueType.Reflexive: if (offset <= size - 0xC) { MetaMap subMap = map.GetSubMap(offset); if (subMap != null) { int subMapSize = subMap.GetBestSizeEstimate(); writer.EnterReflexive("Unknown", (uint)offset, false, (uint)subMapSize, 0); WritePlugin(subMap, subMapSize, writer); writer.LeaveReflexive(); offset += 0x8; continue; } } break; } } // Just write an unknown value depending upon how much space we have left if (offset <= size - 4) writer.VisitUndefined("Unknown", (uint)offset, false, 0); else if (offset <= size - 2) writer.VisitInt16("Unknown", (uint)offset, false, 0); else writer.VisitInt8("Unknown", (uint)offset, false, 0); } }
private void doConvert(BackgroundWorker worker, IEnumerable<string> files, string outputDir, string gameName) { int progress = 0; foreach (string file in files) { string name = Path.GetFileName(file); worker.ReportProgress(progress, "Converting " + name + "..."); progress++; if (file.EndsWith(".asc") || file.EndsWith(".alt") || file.EndsWith(".ent") || file.EndsWith(".xml")) { XmlReader reader = null; XmlWriter writer = null; try { string extension = ".xml"; if (ascensionFmt.Checked) extension = ".asc"; else if (alterationFmt.Checked) extension = ".alt"; XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t"; string outPath = Path.Combine(outputDir, Path.ChangeExtension(name, extension)); writer = XmlWriter.Create(outPath, settings); reader = XmlReader.Create(file); IPluginVisitor visitor; if (assemblyFmt.Checked) visitor = new AssemblyPluginWriter(writer, gameName); else if (ascensionFmt.Checked) visitor = new AscensionPluginWriter(writer, Path.GetFileNameWithoutExtension(file)); else throw new InvalidOperationException("Unsupported output format."); UniversalPluginLoader.LoadPlugin(reader, visitor); } finally { if (reader != null) reader.Close(); if (writer != null) writer.Close(); } } } worker.ReportProgress(progress, "Done!"); }