private void _exportDatButton_Click(object sender, RoutedEventArgs e) { // Show save file dialog var saveFileDialog = new System.Windows.Forms.SaveFileDialog { Filter = "Genie database files (*.dat)|*.dat", Title = "Export DAT file..." }; if (saveFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return; } // Catch errors on export process try { // Reload internal genie file, apply changes and save GenieLibrary.GenieFile exportFile = new GenieLibrary.GenieFile(GenieLibrary.GenieFile.DecompressData(new IORAMHelper.RAMBuffer(_currentFileSelectionWindow.BaseGenieFilePath))); BalancingFile.WriteChangesToGenieFile(exportFile); IORAMHelper.RAMBuffer exportFileBuffer = new IORAMHelper.RAMBuffer(); exportFile.WriteData(exportFileBuffer); GenieLibrary.GenieFile.CompressData(exportFileBuffer).Save(saveFileDialog.FileName); } catch (IOException ex) { // Error MessageBox.Show($"Unable to export modified DAT file: {ex.Message}"); } }
/// <summary> /// Computes the hash of the given genie file. /// </summary> /// <param name="genieFile">The genie file to be hashed.</param> /// <returns></returns> public static byte[] ComputeHash(GenieFile genieFile) { // Calculate hash over string of all unit and research IDs/names, such that each one is contained at least once using (MemoryStream hashString = new MemoryStream()) { // Write unit IDs and names HashSet <int> unitIdsRead = new HashSet <int>(); foreach (GenieLibrary.DataElements.Civ c in genieFile.Civs) { foreach (var u in c.Units) { if (!unitIdsRead.Contains(u.Key)) { // Append name and ID byte[] uName = Encoding.ASCII.GetBytes(u.Value.Name1.TrimEnd('\0')); hashString.Write(uName, 0, uName.Length); hashString.Write(BitConverter.GetBytes((short)u.Key), 0, 2); // Unit was added unitIdsRead.Add(u.Key); } } } // Write research IDs and names for (short r = 0; r < genieFile.Researches.Count; ++r) { // Append name and ID byte[] rName = Encoding.ASCII.GetBytes(genieFile.Researches[r].Name.TrimEnd('\0')); hashString.Write(rName, 0, rName.Length); hashString.Write(BitConverter.GetBytes(r), 0, 2); } // Calculate hash and check hashString.Seek(0, SeekOrigin.Begin); using (MD5 md5 = MD5.Create()) return(md5.ComputeHash(hashString)); } }
private void _loadDatButton_Click(object sender, RoutedEventArgs e) { // Show window (create new first, as closed windows cannot be reopened) _currentFileSelectionWindow = new FileSelectionWindow(); if (!(_currentFileSelectionWindow.ShowDialog() ?? false)) { return; } // Check whether genie file exists if (!File.Exists(_currentFileSelectionWindow.BaseGenieFilePath)) { // Error MessageBox.Show($"The given genie file path is invalid: '{_currentFileSelectionWindow.BaseGenieFilePath}'"); return; } // Catch errors _languageFiles = new List <string>(); try { // Find language files if (File.Exists(_currentFileSelectionWindow.LanguageX1P1DllFilePath)) { _languageFiles.Add(_currentFileSelectionWindow.LanguageX1P1DllFilePath); } if (File.Exists(_currentFileSelectionWindow.LanguageX1DllFilePath)) { _languageFiles.Add(_currentFileSelectionWindow.LanguageX1DllFilePath); } if (File.Exists(_currentFileSelectionWindow.LanguageDllFilePath)) { _languageFiles.Add(_currentFileSelectionWindow.LanguageDllFilePath); } // Load genie file _genieFile = new GenieLibrary.GenieFile(GenieLibrary.GenieFile.DecompressData(new IORAMHelper.RAMBuffer(_currentFileSelectionWindow.BaseGenieFilePath))); } catch (IOException ex) { // Error MessageBox.Show($"Unable to load given genie file: {ex.Message}"); return; } // Check for mapping requirement _mappingFile = null; if (!string.IsNullOrWhiteSpace(_currentFileSelectionWindow.MappingFilePath) && File.Exists(_currentFileSelectionWindow.MappingFilePath)) { // Read mapping _mappingFile = new MappingFile(new IORAMHelper.RAMBuffer(_currentFileSelectionWindow.MappingFilePath)); if (!_mappingFile.CheckCompabilityToGenieFile(_genieFile)) { MessageBox.Show($"The given mapping file does not match the given DAT file."); } } else if (_genieFile.Researches.Exists(r => r.Name.StartsWith("#BDep"))) { MessageBox.Show($"This file was probably created using an editor that dynamically reassigns unit and research IDs.\nIt is strongly recommended to reload using a valid mapping file."); } // Create balancing data object BalancingFile = new BalancingFile(_genieFile, _languageFiles.ToArray(), _mappingFile); _balancingFilePath = ""; // Set filterable lists UnitEntryList = new GenericCollectionView <KeyValuePair <short, UnitEntry> >(CollectionViewSource.GetDefaultView(_balancingFile.UnitEntries)); OnPropertyChanged(nameof(UnitEntryList)); // Update child windows if (_projectileWindow != null) { _projectileWindow.GenieFile = _genieFile; } // Reset window title CurrentWindowTitle = WindowTitlePrefix; // Enable UI controls EnableEditorPanel = true; }
/// <summary> /// Checks whether this mapping file is valid for the given genie file, by computing and comparing its hash. /// </summary> /// <param name="genieFile">The genie file to be checked.</param> /// <returns></returns> public bool CheckCompabilityToGenieFile(GenieFile genieFile) { // Calculate hash and compare return(Hash.SequenceEqual(ComputeHash(genieFile))); }