private static void UnpackRegulationFile(Options options) { using (FileStream inputStream = new FileStream(options.InputPath, FileMode.Open, FileAccess.Read)) { EncFile encryptedFile = EncFile.ReadEncFile(inputStream, DecryptionKeys.RegulationFileKey); DcxFile compressedRegulationFile = DcxFile.Read(encryptedFile.Data); UnpackBndFile(new MemoryStream(compressedRegulationFile.Decompress()), options.OutputPath); } }
private static void UnpackBdf4File(Options options) { string bdfDirectoryPath = Path.GetDirectoryName(options.InputPath); string bhf4Extension = Path.GetExtension(options.InputPath).Replace("bdt", "bhd"); string bhf4FilePath = Path.Combine(bdfDirectoryPath, Path.GetFileNameWithoutExtension(options.InputPath) + bhf4Extension); if (!File.Exists(bhf4FilePath)) { // HACK: Adding 132 to a hash of a text that ends with XXX.bdt will give you the hash of XXX.bhd. string[] split = Path.GetFileNameWithoutExtension(options.InputPath).Split('_'); uint hash; if (uint.TryParse(split[0], out hash)) { hash += 132; split[0] = hash.ToString("D10"); bhf4FilePath = Path.Combine(bdfDirectoryPath, string.Join("_", split) + ".bhd"); } } using (Bdf4FileStream bdf4InputStream = Bdf4FileStream.OpenFile(options.InputPath, FileMode.Open, FileAccess.Read)) { Bhf4File bhf4File = Bhf4File.OpenBhf4File(bhf4FilePath); foreach (var entry in bhf4File.Entries) { MemoryStream data = bdf4InputStream.Read(entry.FileOffset, entry.FileSize); string fileName = entry.FileName; string fileExtension = Path.GetExtension(fileName); if (fileExtension == ".dcx") { DcxFile dcxFile = DcxFile.Read(data); data = new MemoryStream(dcxFile.Decompress()); fileName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName)); } string outputFilePath = Path.Combine(options.OutputPath, fileName); Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath)); File.WriteAllBytes(outputFilePath, data.ToArray()); } } }
private static void UnpackDcxFile(Options options) { string unpackedFileName = Path.GetFileNameWithoutExtension(options.InputPath); string outputFilePath = options.OutputPath; bool hasExtension = Path.GetExtension(unpackedFileName) != ""; using (FileStream inputStream = new FileStream(options.InputPath, FileMode.Open, FileAccess.Read)) { DcxFile dcxFile = DcxFile.Read(inputStream); byte[] decompressedData = dcxFile.Decompress(); if (!hasExtension) { string extension = GetDataExtension(new MemoryStream(decompressedData)); if (extension != ".dcx") { outputFilePath += extension; } } File.WriteAllBytes(outputFilePath, decompressedData); } }
private static void UnpackBdtFile(Options options) { FileNameDictionary dictionary = FileNameDictionary.OpenFromFile(options.InputGameVersion); string fileNameWithoutExtension = Path.GetFileName(options.InputPath).Replace("Ebl.bdt", "").Replace(".bdt", ""); string archiveName = fileNameWithoutExtension.ToLower(); using (Bdt5FileStream bdtStream = Bdt5FileStream.OpenFile(options.InputPath, FileMode.Open, FileAccess.Read)) { Bhd5File bhdFile = Bhd5File.Read( inputStream: DecryptBhdFile( filePath: Path.ChangeExtension(options.InputPath, "bhd"), version: options.InputGameVersion), version: options.InputGameVersion ); foreach (var bucket in bhdFile.GetBuckets()) { foreach (var entry in bucket.GetEntries()) { MemoryStream data; if (entry.FileSize == 0) { long fileSize; if (!TryReadFileSize(entry, bdtStream, out fileSize)) { Console.WriteLine($"Unable to determine the length of file '{entry.FileNameHash:D10}'"); continue; } entry.FileSize = fileSize; } if (entry.IsEncrypted) { data = bdtStream.Read(entry.FileOffset, entry.PaddedFileSize); CryptographyUtility.DecryptAesEcb(data, entry.AesKey.Key, entry.AesKey.Ranges); data.Position = 0; data.SetLength(entry.FileSize); } else { data = bdtStream.Read(entry.FileOffset, entry.FileSize); } string fileName; string dataExtension = GetDataExtension(data); bool fileNameFound = dictionary.TryGetFileName(entry.FileNameHash, archiveName, out fileName); if (!fileNameFound) { fileNameFound = dictionary.TryGetFileName(entry.FileNameHash, archiveName, dataExtension, out fileName); } string extension; if (fileNameFound) { extension = Path.GetExtension(fileName); if (dataExtension == ".dcx" && extension != ".dcx") { extension = ".dcx"; fileName += ".dcx"; } } else { extension = dataExtension; fileName = $"{entry.FileNameHash:D10}_{fileNameWithoutExtension}{extension}"; } if (extension == ".enc") { byte[] decryptionKey; if (DecryptionKeys.TryGetAesFileKey(Path.GetFileName(fileName), out decryptionKey)) { EncFile encFile = EncFile.ReadEncFile(data, decryptionKey); data = encFile.Data; fileName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName)); extension = Path.GetExtension(fileName); } else { Debug.WriteLine($"No decryption key for file \'{fileName}\' found."); } } if (extension == ".dcx") { DcxFile dcxFile = DcxFile.Read(data); data = new MemoryStream(dcxFile.Decompress()); fileName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName)); if (fileNameFound) { extension = Path.GetExtension(fileName); } else { extension = GetDataExtension(data); fileName += extension; } } if (extension == ".bnd") { UnpackBnd3File(data, options.OutputPath); continue; // don't actually unpack bnds } Debug.WriteLine( "{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}", fileNameWithoutExtension, fileName, extension, entry.FileNameHash, entry.FileOffset, entry.FileSize, entry.PaddedFileSize, entry.IsEncrypted, fileNameFound); string newFileNamePath = Path.Combine(options.OutputPath, fileName); Directory.CreateDirectory(Path.GetDirectoryName(newFileNamePath)); File.WriteAllBytes(newFileNamePath, data.ToArray()); } } } }