/// <summary> /// Prepares a packed file for viewing/editing. can be used as stand-alone to get files without creating any task. /// </summary> /// <param name="bnk">BNK file</param> /// <param name="packedFilePath">Path of packed file to prepare</param> /// <returns>Full path of extracted file</returns> public string PrepareFile(BNK bnk, string packedFilePath) { string returnPath = null; if (bnk == null || string.IsNullOrEmpty(packedFilePath)) { return(returnPath); } // Working folder string workFolder = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); if (workFolder == null) { throw new Exception(ERROR_CODE_TEMP_FOLDER); } // Extracting packed file into working folder string packedFileName = bnk.GetPackedFileName(packedFilePath); returnPath = string.Format(@"{0}\{1}", workFolder, packedFileName); bnk.ExtractPackedFile(packedFilePath, returnPath, false); // Removing attributes on file File.SetAttributes(returnPath, FileAttributes.Normal); return(returnPath); }
/// <summary> /// Defines Picture tab contents /// </summary> private void _UpdatePictureTab() { // Searching for picture in deploy folder string deployFolder = Program.ApplicationSettings.PatchEditorLastDeployLocation; if (!string.IsNullOrEmpty(deployFolder) && Directory.Exists(deployFolder)) { string pictureFile = deployFolder + LibraryConstants.FILE_MNP_BACKGROUND_PICTURE; notGeneratedLabel.Visible = false; if (File.Exists(pictureFile)) { string tempFolder = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); string workingFile = tempFolder + LibraryConstants.FILE_MNP_BACKGROUND_PICTURE; File.Copy(pictureFile, workingFile, true); picPanel.BackgroundImage = Image.FromFile(workingFile); } else { picPanel.BackgroundImage = Resources.nopic; } } else { picPanel.BackgroundImage = null; notGeneratedLabel.Visible = true; } }
/// <summary> /// Reads file data. This method should not be called from subclasses ! /// </summary> protected override void _ReadData() { try { // File decryption string tempFolder = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); _WorkingFileName = string.Concat(tempFolder, FILE_AICONFIG_XML); XTEAEncryption.Decrypt(_FileName, _WorkingFileName); // Extracting xml and dirty data byte[] xmlData; using (BinaryReader reader = new BinaryReader(new FileStream(_WorkingFileName, FileMode.Open, FileAccess.Read))) { // Finding 0x00 0x00 sequence byte readByte = 0xAA; while (readByte != 0x00) { readByte = reader.ReadByte(); } long xmlPartLength = reader.BaseStream.Position; reader.BaseStream.Seek(0, SeekOrigin.Begin); xmlData = reader.ReadBytes((int)(xmlPartLength - 1)); _DirtyData = reader.ReadBytes((int)(reader.BaseStream.Length - xmlData.Length)); } // Loading xml... _Doc = new XmlDocument(); File2.WriteBytesToFile(_WorkingFileName, xmlData); _Doc.Load(_WorkingFileName); // Locating zones const string xRequest = "/AICONFIG/VEHICLE_REPARTITION/ZONE"; _ZoneNodes = _Doc.SelectNodes(xRequest); if (_ZoneNodes == null || _ZoneNodes.Count == 0) { throw new Exception("Invalid zoning data in AIConfig.xml: see " + xRequest); } } catch (Exception ex) { throw new Exception("Unable to read file: " + _FileName, ex); } }
/// <summary> /// Réalise la conversion multiple /// </summary> private void _MultipleConvert() { // Vérifications if (string.IsNullOrEmpty(sourceBNKTextBox.Text) || string.IsNullOrEmpty(targetFolderTextBox.Text)) { return; } Cursor = Cursors.WaitCursor; // Parcours des fichiers et extraction des 2DB BNK bnkFile = TduFile.GetFile(sourceBNKTextBox.Text) as BNK; if (bnkFile == null) { throw new Exception(_ERROR_INVALID_BNK_FILE); } Collection <string> textureFiles = bnkFile.GetPackedFilesPathsByExtension(LibraryConstants.EXTENSION_2DB_FILE); string tempFolder = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); foreach (string anotherFilePath in textureFiles) { // 1.Extraction depuis le BNK vers le dossier temporaire bnkFile.ExtractPackedFile(anotherFilePath, tempFolder, true); // 2.Conversion des fichiers 2DB>DDS string fileName = tempFolder + @"\" + bnkFile.GetPackedFileName(anotherFilePath); FileInfo fi = new FileInfo(fileName); string newFileName = targetFolderTextBox.Text + @"\" + File2.ChangeExtensionOfFilename(fi.Name, LibraryConstants.EXTENSION_DDS_FILE); // If file already exists, it is renamed Tools.RenameIfNecessary(newFileName, LibraryConstants.SUFFIX_OLD_FILE); GraphicsConverters._2DBToDDS(fileName, newFileName); } // EVO 32 string message = string.Format(_STATUS_SUCCESS_MULTIPLE, textureFiles.Count); StatusBarLogManager.ShowEvent(this, message); // On efface le champ source sourceBNKTextBox.Text = ""; // Mise à jour de l'emplacement des 2DB _2DBLocationLink.Text = tempFolder; Cursor = Cursors.Default; }
/// <summary> /// Handles database loading /// </summary> private void _LoadDatabase() { DB.Culture currentCulture = Program.ApplicationSettings.GetCurrentCulture(); string resourceBNKFileName = DB.GetBNKFileName(currentCulture); BNK resourceBNK = TduFile.GetFile(Tools.TduPath + LibraryConstants.FOLDER_DB + resourceBNKFileName) as BNK; if (resourceBNK != null) { // Extracting Houses resource string packedFileName = DB.GetFileName(currentCulture, DB.Topic.Houses); string packedFilePath = resourceBNK.GetPackedFilesPaths(packedFileName)[0]; string tempLocation = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); resourceBNK.ExtractPackedFile(packedFilePath, tempLocation, true); // Loading resource _HousesResource = TduFile.GetFile(tempLocation + @"\" + packedFileName) as DBResource; if (_HousesResource == null) { throw new Exception("Error while loading database resources (Houses) !"); } } }
/// <summary> /// What the instruction should do /// </summary> protected override void _Process() { // Checking parameters string databaseIdentifier = _GetParameter(PatchInstructionParameter.ParameterName.databaseId); string rimName = _GetParameter(PatchInstructionParameter.ParameterName.rimName); string tempFolder = ""; try { // 1. Extracting brands BNK databaseBNK; string rimsDBFileName; string rimsDBFilePath; try { string bnkFilePath = string.Concat(LibraryConstants.GetSpecialFolder(LibraryConstants.TduSpecialFolder.Database), DB.GetBNKFileName(PatchHelper.CurrentCulture)); rimsDBFileName = DB.GetFileName(PatchHelper.CurrentCulture, DB.Topic.Rims); databaseBNK = TduFile.GetFile(bnkFilePath) as BNK; if (databaseBNK == null) { throw new Exception("Database BNK file is invalid."); } // Files are extracted to a temporary location rimsDBFilePath = databaseBNK.GetPackedFilesPaths(rimsDBFileName)[0]; tempFolder = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); databaseBNK.ExtractPackedFile(rimsDBFilePath, tempFolder, true); } catch (Exception ex) { throw new Exception("Unable to extract DB file.", ex); } // 2. Getting TduFile DBResource rimsDBResource; try { rimsDBResource = TduFile.GetFile(tempFolder + @"\" + rimsDBFileName) as DBResource; if (rimsDBResource == null || !rimsDBResource.Exists) { throw new Exception("Extracted rim db file not found!"); } } catch (Exception ex) { throw new Exception("Unable to gain access to DB contents.", ex); } // 3. Setting value in DB file DBResource.Entry rimsEntry = rimsDBResource.GetEntryFromId(databaseIdentifier); try { if (rimsEntry.isValid) { rimsEntry.value = rimName; rimsDBResource.UpdateEntry(rimsEntry); } else { throw new Exception("Unable to retrieve a DB entry for identifier: " + databaseIdentifier); } } catch (Exception ex) { throw new Exception("Unable to locate DB entry to update.", ex); } // 4. Saving try { rimsDBResource.Save(); } catch (Exception ex) { throw new Exception("Unable to save DB files.", ex); } // 5. File replacing try { // Rims databaseBNK.ReplacePackedFile(rimsDBFilePath, tempFolder + @"\" + rimsDBFileName); } catch (Exception ex) { throw new Exception("Unable to replace database files in BNK.", ex); } } finally { // Cleaning up try { File2.RemoveTemporaryFolder(null, tempFolder); } catch (Exception ex) { // Silent Exception2.PrintStackTrace(ex); } } }
/// <summary> /// Saves the current file to disk. To implement if necessary. /// </summary> public override void Save() { // Preparing destination string tempFolder = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); FileInfo fi = new FileInfo(_FileName); string tempFile = tempFolder + @"\" + fi.Name + ".OK"; // Saving data using (TextWriter writer = new StreamWriter(new FileStream(tempFile, FileMode.Create, FileAccess.Write))) { // Header comments writer.Write(_HeaderComments); // Column list StringBuilder sbFileRef = new StringBuilder(); sbFileRef.Append(_CHAR_START_TEXT); sbFileRef.Append("TDU_"); sbFileRef.Append(_CurrentTopic.ToString()); sbFileRef.Append(_CHAR_END_TEXT); sbFileRef.Append(' '); sbFileRef.Append(_FileReference); writer.WriteLine(sbFileRef.ToString()); foreach (Cell anotherColumn in _Structure) { StringBuilder sbColumn = new StringBuilder(); sbColumn.Append(_CHAR_START_TEXT); sbColumn.Append(anotherColumn.name); sbColumn.Append(_CHAR_END_TEXT); sbColumn.Append(' '); sbColumn.Append(_GetSymbolByValueType(anotherColumn.valueType)); if (anotherColumn.valueType == ValueType.Reference || anotherColumn.valueType == ValueType.ReferenceL) { sbColumn.Append(' '); sbColumn.Append(anotherColumn.optionalRef); } writer.WriteLine(sbColumn.ToString()); } // Count comment string countComment = string.Format(_FORMAT_COMMENT_COUNT, _Entries.Count); writer.WriteLine(countComment); // Entries foreach (Entry anotherEntry in _Entries) { StringBuilder sbEntry = new StringBuilder(); foreach (Cell anotherCell in anotherEntry.cells) { sbEntry.Append(anotherCell.value); sbEntry.Append(_CHAR_VALUE_SEPARATOR); } writer.WriteLine(sbEntry.ToString()); } } // Encrypting needed XTEAEncryption.Encrypt(tempFile, _FileName); }
/// <summary> /// Lit les données du fichier. A implémenter si nécessaire /// </summary> protected override sealed void _ReadData() { // Decrypting needed string tempFolder = File2.SetTemporaryFolder(null, LibraryConstants.FOLDER_TEMP, true); FileInfo fi = new FileInfo(_FileName); string tempFile = tempFolder + @"\" + fi.Name + ".OK"; XTEAEncryption.Decrypt(_FileName, tempFile); // Parsing clear file using (TextReader reader = new StreamReader(new FileStream(tempFile, FileMode.Open, FileAccess.Read))) { // Clearing all data _Entries.Clear(); _EntriesByPrimaryKey.Clear(); // First lines = header comments StringBuilder sbHeader = new StringBuilder(); string currentLine = reader.ReadLine(); while (currentLine != null && currentLine.StartsWith(_CHAR_COMMENTS)) { sbHeader.AppendLine(currentLine); currentLine = reader.ReadLine(); } _HeaderComments = sbHeader.ToString(); // Column list _Structure = new List <Cell>(); int count = 0; int unicityCounter = 1; while (currentLine != null && currentLine[0] == _CHAR_START_TEXT) { // Parsing column description int nameEndPosition = currentLine.IndexOf(_CHAR_END_TEXT); string name = currentLine.Substring(1, nameEndPosition - 1); if (count++ == 0) { // First column is just file reference _CurrentTopic = _GetTopicByName(name); _FileReference = currentLine.Substring(nameEndPosition + 2); } else { Cell currentCell = new Cell(); // Regular column description string type = currentLine.Substring(nameEndPosition + 2, 1); currentCell.name = name; currentCell.valueType = _GetValueTypeBySymbol(type); currentCell.index = count - 2; if (currentCell.valueType == ValueType.Reference || currentCell.valueType == ValueType.ReferenceL) { string reference = currentLine.Substring(nameEndPosition + 4); currentCell.optionalRef = reference; } _Structure.Add(currentCell); // Index update // BUGFIX: on TDU_PNJ, 6 columns have the same name // Column name is suffixed by a counter if (_ColumnIndexByName.ContainsKey(currentCell.name)) { currentCell.name = currentCell.name + "_" + unicityCounter; unicityCounter++; } _ColumnIndexByName.Add(currentCell.name, currentCell.index); } currentLine = reader.ReadLine(); } // Comment for line count string countComment = currentLine; currentLine = reader.ReadLine(); // Values int entryCount = 0; int maxEntryCount = _GetMaxEntryCount(countComment); string separator = new string(_CHAR_VALUE_SEPARATOR, 1); // BUGFIX: does not take entries when count is higher than expected while (currentLine != null && currentLine.Contains(separator)) { if (entryCount > maxEntryCount) { break; } // Getting all values by splitting between ; string[] allValues = currentLine.Split(_CHAR_VALUE_SEPARATOR); // BUG_65: ensure current line is valid. If last separator is missing, entry is also considered as OK. if (allValues.Length < _Structure.Count || allValues.Length > _Structure.Count + 1) { Log.Info("Current DB entry is invalid (" + _FileName + "):\r\n" + currentLine); break; } Entry currentEntry = new Entry(); string primaryKey = null; currentEntry.index = entryCount; currentEntry.cells = new List <Cell>(); for (int i = 0; i < allValues.Length - 1; i++) { Cell currentCell = _Structure[i]; currentCell.value = allValues[i]; currentCell.index = i; currentCell.entryIndex = entryCount; currentEntry.cells.Add(currentCell); if (currentCell.valueType == ValueType.PrimaryKey) { primaryKey = currentCell.value; } } // If no REF column found, primary key is automatically built with contents of first 2 columns if (primaryKey == null && currentEntry.cells.Count >= 2) { primaryKey = string.Format(DatabaseHelper.FORMAT_COMPLEX_PK, currentEntry.cells[0].value, currentEntry.cells[1].value); } currentEntry.primaryKey = primaryKey; _Entries.Add(currentEntry); // Debug only - very slow ! //Log.Info("primary key = " + primaryKey); // TODO potential problem with Elise duplicated rims 1297992029 // Duplicate risk with TDU_Achievements if (primaryKey != null && !_EntriesByPrimaryKey.ContainsKey(primaryKey)) { _EntriesByPrimaryKey.Add(primaryKey, currentEntry); } currentLine = reader.ReadLine(); entryCount++; } } // Adding current reference to global association if (_FileReference != null && !_DBFilesByReference.ContainsKey(_FileReference)) { _DBFilesByReference.Add(_FileReference, _CurrentTopic.ToString()); } // EVO_65: Properties Property.ComputeValueDelegate encryptedDelegate = (() => "Yes"); Properties.Add(new Property("Encrypted ?", "Database", encryptedDelegate)); }