public static void UnpackTCDFile(string directoryPath, string inputPrefix, Action <string, double> progressCallback) { var fullPath = new DirectoryInfo(Path.GetFullPath(directoryPath)); var patternFile = Path.Combine(fullPath.Parent.FullName, $"{inputPrefix}{TCDEncodeDecode.PatternSuffix}"); var resourceFile = Path.Combine(fullPath.Parent.FullName, $"{inputPrefix}{TCDEncodeDecode.ResourceSuffix}"); Directory.CreateDirectory(directoryPath); var unpackThread = new Thread(() => { try { using (var rsr = new BinaryReader(File.OpenRead(resourceFile), Encoding.GetEncoding("Shift_JIS"))) { using (var psr = new StreamReader(File.OpenRead(patternFile), Encoding.GetEncoding("Shift_JIS"))) { var files = psr.ReadToEnd().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); var fileCount = files.Length; var fileNumber = 0; foreach (var file in files) { var pattern = TCDEncodeDecode.DecryptString(file, TCDEncodeDecode.DefaultPassword); var parts = pattern.Split('_'); var fileName = string.Join("_", parts.Take(parts.Length - 1)); var newFile = Path.Combine(directoryPath, fileName); var size = int.Parse(parts.Last()); progressCallback(fileName, (double)fileNumber / fileCount); var rawBuffer = rsr.ReadBytes(size); var buffer = rawBuffer.Select((b, i) => i > 1024 ? (byte)b : (byte)(~b & 0xff)).ToArray(); using (var bw = new BinaryWriter(new FileStream(newFile, FileMode.Create))) { bw.Write(buffer); } fileNumber += 1; } } } } finally { progressCallback(null, 0); } }); unpackThread.Start(); }
public void Load() { string resourceFile, patternFile, fileBase; resourceFile = patternFile = fileBase = string.Empty; if (!File.Exists(this.selectedFile)) { throw new InvalidOperationException($"Missing file \"{this.selectedFile}\"."); } else if (this.selectedFile.EndsWith(TCDLoadStrategy.ResourceSuffix, StringComparison.InvariantCultureIgnoreCase)) { fileBase = Path.GetFileName(this.selectedFile.Substring(0, this.selectedFile.Length - TCDLoadStrategy.ResourceSuffix.Length)); resourceFile = this.selectedFile; patternFile = Path.Combine(Path.GetDirectoryName(this.selectedFile), fileBase + TCDLoadStrategy.PatternSuffix); if (!File.Exists(patternFile)) { throw new InvalidOperationException($"Missing associated pattern file \"{patternFile}\"."); } } else if (this.selectedFile.EndsWith(TCDLoadStrategy.PatternSuffix, StringComparison.InvariantCultureIgnoreCase)) { fileBase = Path.GetFileName(this.selectedFile.Substring(0, this.selectedFile.Length - TCDLoadStrategy.PatternSuffix.Length)); resourceFile = Path.Combine(Path.GetDirectoryName(this.selectedFile), fileBase + TCDLoadStrategy.ResourceSuffix); patternFile = this.selectedFile; if (!File.Exists(resourceFile)) { throw new InvalidOperationException($"Missing associated resource file \"{resourceFile}\"."); } } else { throw new InvalidOperationException($"Invalid file \"{this.selectedFile}\".{Environment.NewLine}Expected a \"<name>Resource\" or \"<name>Pattern\" .tcd file."); } var unpackThread = new Thread(() => { try { using (var rsr = new BinaryReader(File.OpenRead(resourceFile), Encoding.GetEncoding("Shift_JIS"))) { using (var psr = new StreamReader(File.OpenRead(patternFile), Encoding.GetEncoding("Shift_JIS"))) { var files = psr.ReadToEnd().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); var fileCount = files.Length; var fileNumber = 0; foreach (var file in files) { var pattern = TCDEncodeDecode.DecryptString(file, this.password); var parts = pattern.Split('_'); var fileName = string.Join("_", parts.Take(parts.Length - 1)); var size = int.Parse(parts.Last()); var rawBuffer = rsr.ReadBytes(size); var buffer = rawBuffer.Select((b, i) => i > 1024 ? (byte)b : (byte)(~b & 0xff)).ToArray(); this.fileBytes[fileName] = buffer; fileNumber += 1; this.UpdateProgress(fileName, (double)fileNumber / fileCount); } } } } catch (CryptographicException) { MessageBox.Show("Resource file decryption error. Check the password in the Settings.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } finally { this.UpdateProgressComplete(); } }); unpackThread.Start(); }