private void previewToolStripMenuItem_Click(object sender, EventArgs e) { var menuItem = sender as ToolStripMenuItem; var source = (menuItem.Owner as ContextMenuStrip).SourceControl as TreeView; DatFile df = source?.SelectedNode?.Tag as DatFile; tbInfo.Text = null; tbRaw.Text = null; tbAscii.Text = null; pbPreview.Image = null; pbPreview.Tag = null; // Select the clicked node if (df != null) { StringBuilder sbInfo = new StringBuilder(); StringBuilder sbRaw = new StringBuilder(); StringBuilder sbAscii = new StringBuilder(); string extraInfo = null; string contentDescription = null; byte[] actualContent = null; byte[] header1 = null; byte[] header2 = null; if (df.CompressionLevel == CompressionType.Default || df.CompressionLevel == CompressionType.Maximum) { // for compressed files, the header is only an unknown dword header1 = _database.GetData(df.FileOffset + 8, 4); var compressed = _database.GetData(df.FileOffset + 12, (int)df.Size1); try { actualContent = Ionic.Zlib.ZlibStream.UncompressBuffer(compressed); // inside the compressed content is the file id (dword), and an unknown dword // of a very low (<256, typically) value. header2 = actualContent.Take(8).ToArray(); actualContent = actualContent.Skip(8).ToArray(); var compressionRatio = 100 * (decimal)compressed.Length / (decimal)actualContent.Length; contentDescription = $"Content was compressed by {compressionRatio:#} percent. Viewing decompressed content."; } catch (Exception ex) { byte[] fakeHeader = new byte[2]; contentDescription = "Unable to decompress content. Showing raw content instead."; header1 = new byte[0]; actualContent = compressed; } } else { // for uncompressed files, the header is the file id (dword) and the file size (dword) header1 = _database.GetData(df.FileOffset + 8, 8); actualContent = _database.GetData(df.FileOffset + 16, (int)BitConverter.ToUInt32(header1, 4)); } sbInfo.AppendLine("File ID: " + df.FileId.ToString("X8")); sbInfo.AppendLine("Offset: 0x" + df.FileOffset.ToString("X")); sbInfo.AppendLine("File Date: " + df.FileDate); sbInfo.AppendLine("Version: " + df.Version); sbInfo.AppendLine("Compression: " + df.CompressionLevel.ToString()); sbInfo.AppendLine("File Size: " + df.Size1); sbInfo.AppendLine("Dat Space Consumed: " + df.Size2); sbInfo.AppendLine("Type: 0x" + df.FileType.ToString("X8")); sbInfo.AppendLine("Unknown 1: 0x" + df.Unknown1.ToString("X8")); sbInfo.AppendLine("Unknown 2: 0x" + df.Unknown2.ToString("X8")); var fileType = DatFile.GetActualFileType(actualContent); // raw data tab if (!string.IsNullOrWhiteSpace(contentDescription)) { sbRaw.AppendLine(contentDescription); } sbRaw.AppendLine().AppendLine($"File Header ({header1.Length} bytes)"); sbRaw.AppendLine(header1.PrintBytes()); if (header2 != null) { sbRaw.AppendLine().AppendLine($"Compressed Header ({header2.Length} bytes)"); sbRaw.AppendLine(header2.PrintBytes()); } sbRaw.AppendLine().AppendLine($"Content ({actualContent.Length} bytes)"); sbRaw.AppendLine(actualContent.PrintBytes()); // ascii tab sbAscii.AppendLine($"File Header ({header1.Length} bytes)"); sbAscii.AppendLine(header1.PrintAsciiBytes()); if (header2 != null) { sbAscii.AppendLine().AppendLine($"Compressed Header ({header2.Length} bytes)"); sbAscii.AppendLine(header2.PrintAsciiBytes()); } sbAscii.AppendLine().AppendLine($"Content ({actualContent.Length} bytes)"); sbAscii.Append(actualContent.PrintAsciiBytes()); switch (fileType) { case KnownFileType.DXT1: case KnownFileType.DXT3: case KnownFileType.DXT5: { uint height = BitConverter.ToUInt32(actualContent, 0); uint width = BitConverter.ToUInt32(actualContent, 4); try { var dds = DdsFile.ConvertFromDxt(fileType, actualContent.Skip(16).ToArray(), width, height); pbPreview.Image = DdsFile.DdsToBmp((int)width, (int)height, dds); pbPreview.Tag = df; sbInfo.AppendLine("Image Content available for preview (use Mouse Wheel to zoom)."); } catch (Exception ex) { sbInfo.AppendLine("Image Content Detected but no preview is available."); } break; } break; } tbInfo.Text = sbInfo.ToString(); tbRaw.Text = sbRaw.ToString(); tbAscii.Text = sbAscii.ToString(); } }
private void previewToolStripMenuItem_Click(object sender, EventArgs e) { var menuItem = sender as ToolStripMenuItem; var source = (menuItem.Owner as ContextMenuStrip).SourceControl as TreeView; DatFile df = source?.SelectedNode?.Tag as DatFile; // Select the clicked node if (df != null) { uint len = Math.Max(df.Size1, df.Size2); var buffer = _database.GetData(df.FileOffset + 8, (int)len); // in the file, the first dword is the file id uint fileId = BitConverter.ToUInt32(buffer, 0); if (fileId != df.FileId) { MessageBox.Show("Unable to verify file.", "Dat Explorer", MessageBoxButtons.OK); return; } uint actualSize = BitConverter.ToUInt32(buffer, 4); StringBuilder sb = new StringBuilder(); sb.AppendLine("File ID: " + df.FileId.ToString("X8")); sb.AppendLine("Offset: 0x" + df.FileOffset.ToString("X")); sb.AppendLine("File Date: " + df.FileDate); sb.AppendLine("Version: " + df.Version); sb.AppendLine("Size 1: " + df.Size1); sb.AppendLine("Size 2: " + df.Size2); sb.AppendLine("Type: 0x" + df.FileType.ToString("X8")); sb.AppendLine("Unknown 1: 0x" + df.Unknown1.ToString("X8")); sb.AppendLine("Unknown 2: 0x" + df.Unknown2.ToString("X8")); sb.AppendLine(); StringBuilder sbAlt = new StringBuilder(); sbAlt.AppendLine().AppendLine().AppendLine().AppendLine().AppendLine().AppendLine().AppendLine().AppendLine().AppendLine(); sbAlt.AppendLine(); for (int i = 0; i < actualSize; i++) { byte thisByte = buffer[i + 8]; sb.Append(thisByte.ToString("X2")); char thisChar = '.'; if (thisByte > 31) { thisChar = Encoding.ASCII.GetString(buffer, i + 8, 1)[0]; } sbAlt.Append(thisChar); if ((i + 1) % 4 == 0) { sb.Append(" "); sbAlt.Append(" "); } if ((i + 1) % 16 == 0) { sb.AppendLine(); sbAlt.AppendLine(); } } tbPreview.Text = sb.ToString(); tbPreviewDecoded.Text = sbAlt.ToString(); } }