private static void DumpSharedResources(string mapPath, EngineDatabase db) { ICacheFile cacheFile; ResourceTable resources; using (var reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian)) { cacheFile = CacheFileLoader.LoadCacheFile(reader, db); resources = cacheFile.Resources.LoadResourceTable(reader); } using (var output = new StreamWriter(Path.ChangeExtension(mapPath, ".txt"))) { output.WriteLine("Shared resources referenced by {0}:", Path.GetFileName(mapPath)); output.WriteLine(); output.WriteLine("Rsrc Datum Map File Class Tag"); output.WriteLine("---------- -------- ----- ---"); foreach (Resource resource in resources.Resources.Where(r => r.Location != null && r.ParentTag != null)) { // If either page has a null file path, then it's shared ResourcePointer loc = resource.Location; string primaryFile = (loc.PrimaryPage != null) ? loc.PrimaryPage.FilePath : null; string secondaryFile = (loc.SecondaryPage != null) ? loc.SecondaryPage.FilePath : null; if (primaryFile != null || secondaryFile != null) { string className = CharConstant.ToString(resource.ParentTag.Class.Magic); string name = cacheFile.FileNames.GetTagName(resource.ParentTag) ?? resource.ParentTag.Index.ToString(); string fileName = primaryFile ?? secondaryFile; fileName = fileName.Substring(fileName.IndexOf('\\') + 1); output.WriteLine("{0} {1, -12} {2} {3}", resource.Index, fileName, className, name); } } } }
public static Dictionary <string, IEnumerable <UnitSeatMapping> > LoadAllSeatMappings(string path, EngineDatabase db, out EngineDescription engineInfo) { Dictionary <string, IEnumerable <UnitSeatMapping> > result = new Dictionary <string, IEnumerable <UnitSeatMapping> >(); string fileName = Path.GetFileNameWithoutExtension(path); using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { var reader = new EndianReader(stream, Endian.BigEndian); var cache = CacheFileLoader.LoadCacheFile(reader, fileName, db, out engineInfo); if (cache.Type != CacheFileType.Shared && cache.Type != CacheFileType.SinglePlayerShared && cache.ScriptFiles.Length > 0) { foreach (var file in cache.ScriptFiles) { if (file is ScnrScriptFile scnr) { var mappings = SeatMappingNameExtractor.ExtractScnrSeatMappings(scnr, reader, engineInfo.ScriptInfo); if (mappings.Any()) { result[file.Name] = mappings; } } } } } return(result); }
private KeyValuePair <ICacheFile, EngineDescription> LoadMap(string path, out IReader reader) { reader = new EndianReader(File.OpenRead(path), Endian.BigEndian); var cacheFile = CacheFileLoader.LoadCacheFile(reader, path, App.AssemblyStorage.AssemblySettings.DefaultDatabase, out EngineDescription buildInfo); return (new KeyValuePair <ICacheFile, EngineDescription>(cacheFile, buildInfo)); }
public static async Task Create(Dictionary <string, string> arguments, Dictionary <string, string> options) { await Task.Delay(1); var cacheFilePath = arguments["cache"]; var projectDirectory = arguments["project"]; // Check file exists if (cacheFilePath == null || !File.Exists(cacheFilePath)) { throw new ComposerException("Cache doesn't exist"); } // Create project directory // TODO: think about logic if directory already exists if (!Directory.Exists(projectDirectory)) { Directory.CreateDirectory(projectDirectory); } // Create Project var project = new Models.Project { Title = "Example Halo Project", Version = "1.0.0", Description = "Simple project for testing the tool", Properties = new ProjectProperties { TagsFolder = "tags", GitEnabled = true } }; using (var stream = File.OpenRead(cacheFilePath)) using (var reader = new EndianReader(stream, Endian.BigEndian)) { EngineDescription engineDescription = null; EngineDatabase engineDatabase = XMLEngineDatabaseLoader.LoadDatabase("data/formats/engines.xml"); var cacheFile = CacheFileLoader.LoadCacheFile(reader, engineDatabase, out engineDescription); var stringIdTrie = new Trie(); if (cacheFile.StringIDs != null) { stringIdTrie.AddRange(cacheFile.StringIDs); } if (cacheFile.TagClasses.Any()) { LoadTags(project, cacheFile, projectDirectory, stringIdTrie); } } File.WriteAllText(Path.Combine(projectDirectory, "project.json"), JsonConvert.SerializeObject(project, Formatting.Indented)); }
public static IEnumerable <ICacheFile> LoadAllMaps(string[] paths, EngineDatabase db) { List <ICacheFile> result = new List <ICacheFile>(); foreach (string path in paths) { using var stream = new FileStream(path, FileMode.Open, FileAccess.Read); var reader = new EndianReader(stream, Endian.BigEndian); var cache = CacheFileLoader.LoadCacheFile(reader, Path.GetFileNameWithoutExtension(path), db); result.Add(cache); } return(result); }
private static ScriptTable LoadScripts(string path, EngineDatabase db, out EngineDescription desc) { using (var stream = File.OpenRead(path)) { EngineDescription engine; var reader = new EndianReader(stream, Endian.BigEndian); var cache = CacheFileLoader.LoadCacheFile(reader, Path.GetFileName(path), db, out engine); desc = engine; var scripts = cache.ScriptFiles[0].LoadScripts(reader); return(scripts); } }
public static bool applyPatch(ZipArchiveEntry zippedPatchFile, string patchFileName, string unmoddedMapPath, string outputPath) { createTmpDir(); try { zippedPatchFile.ExtractToFile(Config.modpack_dir + @"\tmp\" + patchFileName); } catch (IOException) { rmTmpDir(); createTmpDir(); zippedPatchFile.ExtractToFile(Config.modpack_dir + @"\tmp\" + patchFileName); } Patch currentPatch = LoadPatch(Config.modpack_dir + @"\tmp\" + patchFileName); // Copy the original map to the destination path IO.CopyFile(unmoddedMapPath, outputPath, true); //if modpack has written to unmoddedmap, take from backups // Open the destination map using (var stream = new EndianStream(File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian)) { EngineDatabase engineDb = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml"); ICacheFile cacheFile; try { cacheFile = CacheFileLoader.LoadCacheFile(stream, engineDb); } catch (NotSupportedException nse) { form1.showMsg("Error patching '" + patchFileName + "':" + nse.Message, "Error"); return(false); } if (!string.IsNullOrEmpty(currentPatch.BuildString) && cacheFile.BuildString != currentPatch.BuildString) { form1.showMsg("Unable to patch. That patch is for a map with a build version of " + currentPatch.BuildString + ", and the unmodified map file doesn't match that.", "Error"); return(false); } if (currentPatch.MapInternalName == null) { // Because Ascension doesn't include this, and ApplyPatch() will complain otherwise currentPatch.MapInternalName = cacheFile.InternalName; } // Apply the patch! try { PatchApplier.ApplyPatch(currentPatch, cacheFile, stream); } catch (ArgumentException ae) { form1.showMsg("There was an issue applying the patch file '" + patchFileName + "': " + ae.Message, "Info"); return(false); } } rmTmpDir(); return(true); }
public static Dictionary <string, ScriptTable> LoadAllScriptFiles(string path, EngineDatabase db, out EngineDescription engineInfo) { Dictionary <string, ScriptTable> result = new Dictionary <string, ScriptTable>(); using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { var reader = new EndianReader(stream, Endian.BigEndian); var cache = CacheFileLoader.LoadCacheFile(reader, path, db, out engineInfo); if (cache.Type != CacheFileType.Shared && cache.Type != CacheFileType.SinglePlayerShared && cache.ScriptFiles.Length > 0) { foreach (var file in cache.ScriptFiles) { result.Add(file.Name, file.LoadScripts(reader)); } } } return(result); }
// Patch Applying private void btnApplyPatch_Click(object sender, RoutedEventArgs e) { try { // Check the user isn't completly retarded if (!CheckAllApplyMandatoryFields() || currentPatch == null) { return; } // Check the output name if (cacheOutputName != "") { if (Path.GetFileNameWithoutExtension(txtApplyPatchOutputMap.Text) != cacheOutputName) { if (MetroMessageBox.Show("Warning", "This patch suggests to use the filename \"" + cacheOutputName + ".map\" to save this map. This filename may be required in order for the map to work correctly.\r\n\r\nAre you sure you want to save this map as \"" + Path.GetFileName(txtApplyPatchOutputMap.Text) + "\"?", MetroMessageBox.MessageBoxButtons.OkCancel) != MetroMessageBox.MessageBoxResult.OK) { Close(); return; } } } // Paths string unmoddedMapPath = txtApplyPatchUnmodifiedMap.Text; string outputPath = txtApplyPatchOutputMap.Text; // Copy the original map to the destination path File.Copy(unmoddedMapPath, outputPath, true); // Open the destination map using (var stream = new EndianStream(File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian)) { EngineDatabase engineDb = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml"); ICacheFile cacheFile = CacheFileLoader.LoadCacheFile(stream, outputPath, engineDb); if (currentPatch.MapInternalName != null && cacheFile.InternalName != currentPatch.MapInternalName) { MetroMessageBox.Show("Unable to apply patch", "Hold on there! That patch is for " + currentPatch.MapInternalName + ".map, and the unmodified map file you selected doesn't seem to match that. Find the correct file and try again."); return; } if (!string.IsNullOrEmpty(currentPatch.BuildString) && cacheFile.BuildString != currentPatch.BuildString) { MetroMessageBox.Show("Unable to apply patch", "Hold on there! That patch is for a map with a build version of" + currentPatch.BuildString + ", and the unmodified map file you selected doesn't seem to match that. Find the correct file and try again."); return; } // Apply the patch! if (currentPatch.MapInternalName == null) { currentPatch.MapInternalName = cacheFile.InternalName; } // Because Ascension doesn't include this, and ApplyPatch() will complain otherwise PatchApplier.ApplyPatch(currentPatch, cacheFile, stream); // Check for blf snaps if (cbApplyPatchBlfExtraction.IsChecked != null && (PatchApplicationPatchExtra.Visibility == Visibility.Visible && (bool)cbApplyPatchBlfExtraction.IsChecked)) { string extractDir = Path.GetDirectoryName(outputPath); string blfDirectory = Path.Combine(extractDir, "images"); string infDirectory = Path.Combine(extractDir, "info"); if (!Directory.Exists(blfDirectory)) { Directory.CreateDirectory(blfDirectory); } if (!Directory.Exists(infDirectory)) { Directory.CreateDirectory(infDirectory); } string infPath = Path.Combine(infDirectory, Path.GetFileName(currentPatch.CustomBlfContent.MapInfoFileName)); File.WriteAllBytes(infPath, currentPatch.CustomBlfContent.MapInfo); foreach (BlfContainerEntry blfContainerEntry in currentPatch.CustomBlfContent.BlfContainerEntries) { string blfPath = Path.Combine(blfDirectory, Path.GetFileName(blfContainerEntry.FileName)); File.WriteAllBytes(blfPath, blfContainerEntry.BlfContainer); } } } MetroMessageBox.Show("Patch Applied!", "Your patch has been applied successfully. Have fun!"); } catch (Exception ex) { MetroException.Show(ex); } }
// Patch Creation private void btnCreatePatch_Click(object sender, RoutedEventArgs e) { try { // Check the user isn't completly retarded if (!CheckAllCreateMandatoryFields()) { return; } // Check the user isn't a skid if (!CheckAllCreateMetaFilesExists()) { return; } // Paths string cleanMapPath = txtCreatePatchUnModifiedMap.Text; string moddedMapPath = txtCreatePatchModifiedMap.Text; string outputPath = txtCreatePatchOutputPatch.Text; string previewImage = txtCreatePatchPreviewImage.Text; // Details string author = txtCreatePatchContentAuthor.Text; string desc = txtCreatePatchContentDescription.Text; string name = txtCreatePatchContentName.Text; string outputName = txtCreatePatchOutputName.Text; // Make dat patch var patch = new Patch { Author = author, Description = desc, Name = name, OutputName = outputName, Screenshot = String.IsNullOrEmpty(previewImage) ? null : File.ReadAllBytes(previewImage), BuildString = _buildInfo.Version, PC = String.IsNullOrEmpty(_buildInfo.GameExecutable) ? false : true }; EndianReader originalReader = null; EndianReader newReader = null; try { originalReader = new EndianReader(File.OpenRead(cleanMapPath), Endian.BigEndian); newReader = new EndianReader(File.OpenRead(moddedMapPath), Endian.BigEndian); ICacheFile originalFile = CacheFileLoader.LoadCacheFile(originalReader, cleanMapPath, App.AssemblyStorage.AssemblySettings.DefaultDatabase); ICacheFile newFile = CacheFileLoader.LoadCacheFile(newReader, moddedMapPath, App.AssemblyStorage.AssemblySettings.DefaultDatabase); if (cbCreatePatchHasCustomMeta.IsChecked != null && (bool)cbCreatePatchHasCustomMeta.IsChecked && cboxCreatePatchTargetGame.SelectedIndex < 4) { var targetGame = (TargetGame)cboxCreatePatchTargetGame.SelectedIndex; byte[] mapInfo = File.ReadAllBytes(txtCreatePatchMapInfo.Text); var mapInfoFileInfo = new FileInfo(txtCreatePatchMapInfo.Text); FileInfo blfFileInfo; patch.CustomBlfContent = new BlfContent(mapInfoFileInfo.FullName, mapInfo, targetGame); #region Blf Data if (PatchCreationBlfOption0.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf0.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } if (PatchCreationBlfOption1.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf1.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } if (PatchCreationBlfOption2.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf2.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } if (PatchCreationBlfOption3.Visibility == Visibility.Visible) { blfFileInfo = new FileInfo(txtCreatePatchblf3.Text); patch.CustomBlfContent.BlfContainerEntries.Add(new BlfContainerEntry(blfFileInfo.Name, File.ReadAllBytes(blfFileInfo.FullName))); } #endregion } PatchBuilder.BuildPatch(originalFile, originalReader, newFile, newReader, patch); } finally { if (originalReader != null) { originalReader.Dispose(); } if (newReader != null) { newReader.Dispose(); } } IWriter output = new EndianWriter(File.Open(outputPath, FileMode.Create, FileAccess.Write), Endian.BigEndian); AssemblyPatchWriter.WritePatch(patch, output); output.Dispose(); MetroMessageBox.Show("Patch Created!", "Your patch has been created in the designated location. Happy sailing, modder!"); } catch (Exception ex) { MetroException.Show(ex); } }
static void Main(string[] args) { if (args.Length != 3) { Console.WriteLine("Usage: BlockAlignmentScanner <map dir> <in plugin dir> <out plugin dir>"); return; } var mapDir = args[0]; var inDir = args[1]; var outDir = args[2]; Console.WriteLine("Loading plugins..."); var pluginsByClass = new Dictionary <string, XDocument>(); foreach (var pluginPath in Directory.EnumerateFiles(inDir, "*.xml")) { Console.WriteLine("- {0}", pluginPath); var document = XDocument.Load(pluginPath); var className = Path.GetFileNameWithoutExtension(pluginPath); pluginsByClass[className] = document; } Console.WriteLine("Loading engine database..."); var exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var dbPath = Path.Combine(exeDir, "Formats", "Engines.xml"); var db = XMLEngineDatabaseLoader.LoadDatabase(dbPath); Console.WriteLine("Processing maps..."); var alignsByElem = new Dictionary <XElement, int>(); foreach (var mapPath in Directory.EnumerateFiles(mapDir, "*.map")) { Console.WriteLine("- {0}", Path.GetFileName(mapPath)); using (var reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian)) { var map = CacheFileLoader.LoadCacheFile(reader, db); var visitedTagBlocks = new HashSet <uint>(); foreach (var tag in map.Tags) { if (tag == null || tag.Class == null || tag.MetaLocation == null) { continue; } // Get the plugin for the tag var className = CharConstant.ToString(tag.Class.Magic); XDocument plugin; if (!pluginsByClass.TryGetValue(className, out plugin)) { continue; } // Process it var baseOffset = tag.MetaLocation.AsOffset(); var baseElement = plugin.Element("plugin"); DetectAlignment(map, reader, baseOffset, baseElement, alignsByElem, visitedTagBlocks); } } } Console.WriteLine("Adjusting plugins..."); foreach (var align in alignsByElem) { if (align.Value != 4) { Console.WriteLine("- \"{0}\" -> align 0x{1:X}", align.Key.Attribute("name").Value, align.Value); align.Key.SetAttributeValue(XName.Get("align"), "0x" + align.Value.ToString("X")); } } if (!Directory.Exists(outDir)) { Directory.CreateDirectory(outDir); } Console.WriteLine("Saving plugins..."); foreach (var plugin in pluginsByClass) { var outPath = Path.Combine(outDir, plugin.Key + ".xml"); Console.WriteLine("- {0}", outPath); var settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t"; using (var writer = XmlWriter.Create(outPath, settings)) plugin.Value.Save(writer); } }
private static void Main(string[] args) { var ofd = new OpenFileDialog(); ofd.Title = "Open Cache File"; ofd.Filter = "Blam Cache Files|*.map"; if (ofd.ShowDialog() != DialogResult.OK) { return; } var sfd = new SaveFileDialog(); sfd.Title = "Save String Dump"; sfd.Filter = "Text Files|*.txt"; if (sfd.ShowDialog() != DialogResult.OK) { return; } string mapPath = ofd.FileName; string dumpPath = sfd.FileName; EngineDatabase engineDb = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml"); ICacheFile cacheFile; LanguagePack locales; using (IReader reader = new EndianReader(File.OpenRead(mapPath), Endian.BigEndian)) { Console.WriteLine("Loading cache file..."); cacheFile = CacheFileLoader.LoadCacheFile(reader, mapPath, engineDb); Console.WriteLine("Loading locales..."); locales = cacheFile.Languages.LoadLanguage(GameLanguage.English, reader); } var output = new StreamWriter(dumpPath); output.WriteLine("Input file: {0}.map", cacheFile.InternalName); output.WriteLine(); // Sort locales by stringID var localesById = new List <LocalizedString>(); localesById.AddRange(locales.StringLists.SelectMany(l => l.Strings).Where(s => s != null && s.Value != null)); localesById.Sort((x, y) => x.Key.Value.CompareTo(y.Key.Value)); // Dump locales Console.WriteLine("Dumping locales..."); output.WriteLine("---------------"); output.WriteLine("English Locales"); output.WriteLine("---------------"); foreach (LocalizedString str in localesById) { if (str != null) { output.WriteLine("{0} = \"{1}\"", str.Key, str.Value); } } output.WriteLine(); // Dump stringIDs Console.WriteLine("Dumping stringIDs..."); output.WriteLine("---------"); output.WriteLine("StringIDs"); output.WriteLine("---------"); int index = 0; foreach (string str in cacheFile.StringIDs) { if (str != null) { output.WriteLine("0x{0:X} = \"{1}\"", index, str); } else { output.WriteLine("0x{0:X} = (null)", index); } index++; } output.Close(); Console.WriteLine("Done!"); }