diff --git a/Controls/SearchBox.cs b/Controls/SearchBox.cs
new file mode 100644
index 0000000..652ea76
--- /dev/null
+++ b/Controls/SearchBox.cs
@@ -0,0 +1,221 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace Controls
+{
+ public partial class SearchBox : UserControl
+ {
+ [Browsable(true)]
+ public DataGridView DataGridView { get; set; }
+ int CurrentRowIndex = -1;
+ int CurrentColumnIndex = -1;
+
+ public SearchBox()
+ {
+ InitializeComponent();
+ Hide();
+ }
+ public SearchBox(DataGridView dataGrid)
+ {
+ DataGridView = dataGrid;
+ InitializeComponent();
+ Hide();
+ }
+
+ private void SearchHide_Click(object sender, System.EventArgs e)
+ {
+ Hide();
+ }
+
+ private bool IsMatch(string value)
+ {
+ string searchText = InputSearch.Text;
+
+ if (string.IsNullOrWhiteSpace(searchText))
+ return false;
+
+ return value.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) > -1;
+ }
+
+ private void FindNext_Click(object sender, EventArgs e)
+ {
+ bool found = false;
+
+ for (int rowIndex = CurrentRowIndex; rowIndex < DataGridView.Rows.Count; rowIndex++)
+ {
+ for (int colIndex = CurrentColumnIndex + 1; colIndex < DataGridView.Columns.Count; colIndex++)
+ {
+ if (rowIndex >= 0 && rowIndex < DataGridView.Rows.Count && colIndex >= 0 && colIndex < DataGridView.Columns.Count)
+ {
+ DataGridViewCell cell = DataGridView.Rows[rowIndex].Cells[colIndex];
+ if (cell.Value != null && IsMatch(cell.Value.ToString()))
+ {
+ SelectCell(rowIndex, colIndex);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found)
+ break;
+
+
+ CurrentColumnIndex = -1;
+ }
+
+ if (!found)
+ {
+
+ for (int rowIndex = 0; rowIndex < DataGridView.Rows.Count; rowIndex++)
+ {
+ for (int colIndex = 0; colIndex < DataGridView.Columns.Count; colIndex++)
+ {
+ if (rowIndex >= 0 && rowIndex < DataGridView.Rows.Count && colIndex >= 0 && colIndex < DataGridView.Columns.Count)
+ {
+ DataGridViewCell cell = DataGridView.Rows[rowIndex].Cells[colIndex];
+ if (cell.Value != null && IsMatch(cell.Value.ToString()))
+ {
+ SelectCell(rowIndex, colIndex);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found)
+ break;
+ }
+ }
+ if (!found)
+ {
+ Failedmessage();
+ }
+ }
+
+
+ private void FindPrevious_Click(object sender, EventArgs e)
+ {
+ bool found = false;
+
+ for (int rowIndex = CurrentRowIndex; rowIndex >= 0; rowIndex--)
+ {
+ for (int colIndex = CurrentColumnIndex - 1; colIndex >= 0; colIndex--)
+ {
+ if (rowIndex >= 0 && rowIndex < DataGridView.Rows.Count && colIndex >= 0 && colIndex < DataGridView.Columns.Count)
+ {
+ DataGridViewCell cell = DataGridView.Rows[rowIndex].Cells[colIndex];
+ if (cell.Value != null && IsMatch(cell.Value.ToString()))
+ {
+ SelectCell(rowIndex, colIndex);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found)
+ break;
+
+
+ CurrentColumnIndex = DataGridView.Columns.Count;
+ }
+
+ if (!found)
+ {
+ for (int rowIndex = DataGridView.Rows.Count - 1; rowIndex >= 0; rowIndex--)
+ {
+ for (int colIndex = DataGridView.Columns.Count - 1; colIndex >= 0; colIndex--)
+ {
+ if (rowIndex >= 0 && rowIndex < DataGridView.Rows.Count && colIndex >= 0 && colIndex < DataGridView.Columns.Count)
+ {
+ DataGridViewCell cell = DataGridView.Rows[rowIndex].Cells[colIndex];
+ if (cell.Value != null && IsMatch(cell.Value.ToString()))
+ {
+ SelectCell(rowIndex, colIndex);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found)
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ Failedmessage();
+ }
+ }
+
+
+ private void Failedmessage()
+ {
+ MessageBox.Show(
+ text: $"The searched value '{InputSearch.Text}' not found.",
+ caption: "Search Result",
+ buttons: MessageBoxButtons.OK,
+ icon: MessageBoxIcon.Warning
+ );
+ }
+
+ private void SelectCell(int rowIndex, int colIndex)
+ {
+ DataGridView.ClearSelection();
+ DataGridView.FirstDisplayedScrollingRowIndex = rowIndex;
+ DataGridView.Rows[rowIndex].Cells[colIndex].Selected = true;
+
+ CurrentRowIndex = rowIndex;
+ CurrentColumnIndex = colIndex;
+ }
+
+ private void InputSearch_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (!InputSearch.Focused)
+ {
+ InputSearch.Focus();
+ }
+
+ if (e.KeyCode == Keys.Enter)
+ {
+ FindNext_Click(sender, e);
+ }
+ }
+
+ public new void Show()
+ {
+ if (DataGridView.CurrentCell!=null)
+ {
+ InputSearch.Text = DataGridView.CurrentCell.Value.ToString();
+ }
+ InputSearch.Focus();
+ base.Show();
+ }
+
+ public int CountTotalMatches()
+ {
+ int totalMatches = 0;
+
+ for (int rowIndex = 0; rowIndex < DataGridView.Rows.Count; rowIndex++)
+ {
+ for (int colIndex = 0; colIndex < DataGridView.Columns.Count; colIndex++)
+ {
+ if (rowIndex >= 0 && rowIndex < DataGridView.Rows.Count && colIndex >= 0 && colIndex < DataGridView.Columns.Count)
+ {
+ DataGridViewCell cell = DataGridView.Rows[rowIndex].Cells[colIndex];
+ if (cell.Value != null && IsMatch(cell.Value.ToString()))
+ {
+ totalMatches++;
+ }
+ }
+ }
+ }
+
+ return totalMatches;
+ }
+
+ }
+}
diff --git a/Controls/SearchBox.designer.cs b/Controls/SearchBox.designer.cs
new file mode 100644
index 0000000..2cb1146
--- /dev/null
+++ b/Controls/SearchBox.designer.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Windows.Forms;
+
+namespace Controls
+{
+ partial class SearchBox
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.searchcount = new System.Windows.Forms.Label();
+ this.SearchHide = new System.Windows.Forms.Label();
+ this.FindPrevious = new System.Windows.Forms.Button();
+ this.FindNext = new System.Windows.Forms.Button();
+ this.InputSearch = new TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // searchcount
+ //
+ this.searchcount.Location = new System.Drawing.Point(423, 7);
+ this.searchcount.Name = "searchcount";
+ this.searchcount.Size = new System.Drawing.Size(211, 18);
+ this.searchcount.TabIndex = 6;
+ //
+ // SearchHide
+ //
+ this.SearchHide.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.SearchHide.AutoSize = true;
+ this.SearchHide.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.SearchHide.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold);
+ this.SearchHide.Location = new System.Drawing.Point(665, 7);
+ this.SearchHide.Name = "SearchHide";
+ this.SearchHide.Size = new System.Drawing.Size(18, 17);
+ this.SearchHide.TabIndex = 5;
+ this.SearchHide.Text = "X";
+ this.SearchHide.Click += new System.EventHandler(this.SearchHide_Click);
+ //
+ // FindPrevious
+ //
+ this.FindPrevious.Location = new System.Drawing.Point(331, 4);
+ this.FindPrevious.Name = "FindPrevious";
+ this.FindPrevious.Size = new System.Drawing.Size(86, 23);
+ this.FindPrevious.TabIndex = 4;
+ this.FindPrevious.Text = "Find Previous";
+ this.FindPrevious.UseVisualStyleBackColor = true;
+ this.FindPrevious.Click += new System.EventHandler(this.FindPrevious_Click);
+ //
+ // FindNext
+ //
+ this.FindNext.Location = new System.Drawing.Point(250, 4);
+ this.FindNext.Name = "FindNext";
+ this.FindNext.Size = new System.Drawing.Size(75, 23);
+ this.FindNext.TabIndex = 3;
+ this.FindNext.Text = "Find Next";
+ this.FindNext.UseVisualStyleBackColor = true;
+ this.FindNext.Click += new System.EventHandler(this.FindNext_Click);
+ //
+ // InputSearch
+ //
+ this.InputSearch.Location = new System.Drawing.Point(79, 5);
+ this.InputSearch.Name = "InputSearch";
+ this.InputSearch.Size = new System.Drawing.Size(162, 20);
+ this.InputSearch.TabIndex = 0;
+ this.InputSearch.KeyDown += new System.Windows.Forms.KeyEventHandler(this.InputSearch_KeyDown);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(7, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(56, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "Find what:";
+ //
+ // SearchBox
+ //
+ this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.Controls.Add(this.searchcount);
+ this.Controls.Add(this.SearchHide);
+ this.Controls.Add(this.FindPrevious);
+ this.Controls.Add(this.FindNext);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.InputSearch);
+ this.Location = new System.Drawing.Point(155, 23);
+ this.Name = "SearchBox";
+ this.Size = new System.Drawing.Size(689, 30);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label searchcount;
+ private System.Windows.Forms.Label SearchHide;
+ private System.Windows.Forms.Button FindPrevious;
+ private System.Windows.Forms.Button FindNext;
+
+ private System.Windows.Forms.Label label1;
+ public TextBox InputSearch;
+ }
+}
diff --git a/Controls/SearchBox.resx b/Controls/SearchBox.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Controls/SearchBox.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Core/StringTable/StringTable.cs b/Core/StringTable/StringTable.cs
index 840dda1..ffdbb67 100644
--- a/Core/StringTable/StringTable.cs
+++ b/Core/StringTable/StringTable.cs
@@ -7,10 +7,45 @@ namespace alan_wake_2_rmdtoc_Tool.Core.StringTable
public class SrtingTableEntry
{
- public string Name;
- public string Value;
+ private string _Name;
+ private string _Value;
+ public string Name
+ {
+ get
+ {
+ return ReplaceBreaklines(_Name);
+ }
+ set
+ {
+ _Name = ReplaceBreaklines(value, true);
+ }
+ }
+ public string Value
+ {
+ get { return ReplaceBreaklines(_Value); }
+ set { _Value = ReplaceBreaklines(value, true); }
+ }
+
+ private static string ReplaceBreaklines(string StringValue, bool Back = false)
+ {
+ if (!Back)
+ {
+ StringValue = StringValue.Replace("\r\n", "");
+ StringValue = StringValue.Replace("\r", "");
+ StringValue = StringValue.Replace("\n", "");
+ }
+ else
+ {
+ StringValue = StringValue.Replace("", "\r\n");
+ StringValue = StringValue.Replace("", "\r");
+ StringValue = StringValue.Replace("", "\n");
+ }
+
+ return StringValue;
+ }
}
+
public class StringTable : List, IStringTable
{
public IStream Stream;
@@ -27,7 +62,7 @@ void ReadStringTable()
{
var Entry = new SrtingTableEntry();
- Entry.Name = Stream.GetStringValue(Stream.GetIntValue());
+ Entry.Name = Stream.GetStringValue(Stream.GetIntValue(), Encoding.UTF8);
Entry.Value = Stream.GetStringValue(Stream.GetIntValue() * 2, Encoding.Unicode);
Add(Entry);
}
@@ -42,7 +77,7 @@ public void BuildStringTable()
for (int i = 0; i < Count; i++)
{
var Entry = this[i];
- var Bytes = Encoding.ASCII.GetBytes(Entry.Name);
+ var Bytes = Encoding.UTF8.GetBytes(Entry.Name);
Stream.SetIntValue(Bytes.Length);
Stream.SetBytes(Bytes);
Bytes = Encoding.Unicode.GetBytes(Entry.Value);
diff --git a/Core/rmdtoc.cs b/Core/rmdtoc.cs
index f03aa9b..fa66c27 100644
--- a/Core/rmdtoc.cs
+++ b/Core/rmdtoc.cs
@@ -23,8 +23,8 @@ public class rmdtocHeader
public int CompressionInfoTableOffset;
public int CompressionInfoTableSize;
- public int Unko2;//=0
- public int Unko3;//=1
+ public int RMDBLOB_Path_Offset;
+ public int RMDBLOB_Path_Count;
public int Table_1_Offset;//Table size is Table_1_Count* 0x1C
public int Table_1_Count;
@@ -48,16 +48,78 @@ public class rmdtocHeader
public int Table_5_Size;
}
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
+
+ public class RMDBLOBPath
+ {
+ public const int Size = 0x10;
+ public int NameOffset;
+ public int NameLength;
+ public ulong Hash;
+ public string Path;
+
+ public void Read(IStream stream)
+ {
+ NameOffset = stream.Get();
+ NameLength = stream.Get();
+ Hash = stream.Get();
+ }
+
+ public void Write(IStream stream)
+ {
+ stream.SetIntValue(NameOffset);
+ stream.SetIntValue(NameLength);
+ stream.SetUInt64Value(Hash);
+ }
+ }
+
public class CompressInfo
{
- public byte unko;
+ public const int Size = 0x10;
+ public byte isCompressed;
public byte FileIndex;
public byte unko2;
- public int BufferOffset;
+ public uint _bufferoffset;
public byte unko3;
public int BufferUSize;
public int BufferSize;
+
+ public long BufferOffset
+ {
+ get
+ {
+ long value = _bufferoffset;
+ return value + (unko3 * 0x100000000);
+ }
+ set
+ {
+ long newUnko3 = value / 0x100000000;
+ unko3 = (byte)newUnko3;
+ _bufferoffset = (uint)(value - (newUnko3 * 0x100000000));
+ }
+ }
+
+ public void Read(IStream stream)
+ {
+ isCompressed = stream.Get();
+ FileIndex = stream.Get();
+ unko2 = stream.Get();
+ _bufferoffset = stream.Get();
+ unko3 = stream.Get();
+ BufferUSize = stream.Get();
+ BufferSize = stream.Get();
+ }
+
+ public void Write(IStream stream)
+ {
+ stream.SetByteValue(isCompressed);
+ stream.SetByteValue(FileIndex);
+ stream.SetByteValue(unko2);
+ stream.SetUIntValue(_bufferoffset);
+ stream.SetByteValue(unko3);
+ stream.SetIntValue(BufferUSize);
+ stream.SetIntValue(BufferSize);
+ }
+
}
@@ -65,9 +127,9 @@ public class FolderInfo
{
const int Size = 0x1c;
+ public int TreeLevel;
public int FolderIndex;
- public int unko;
- public int unko2;
+ public int FolderCount;
public int FilesIndex;
public int FilesCount;
public int NameOffset;
@@ -80,9 +142,9 @@ public class FolderInfo
public void Read(IStream stream)
{
+ TreeLevel = stream.Get();
FolderIndex = stream.Get();
- unko = stream.Get();
- unko2 = stream.Get();
+ FolderCount = stream.Get();
FilesIndex = stream.Get();
FilesCount = stream.Get();
NameOffset = stream.Get();
@@ -91,9 +153,9 @@ public void Read(IStream stream)
public void Write(IStream stream)
{
+ stream.SetIntValue(TreeLevel);
stream.SetIntValue(FolderIndex);
- stream.SetIntValue(unko);
- stream.SetIntValue(unko2);
+ stream.SetIntValue(FolderCount);
stream.SetIntValue(FilesIndex);
stream.SetIntValue(FilesCount);
stream.SetIntValue(NameOffset);
@@ -117,17 +179,13 @@ public class FileInfo
public rmdtoc Rmdtoc;
- public CompressInfo[] CompressInfos;
+ public List CompressInfos;
public string Name;
-
public bool IsEdited = false;
-
public byte[] NewFileBytes;
-
-
public void Read(IStream stream)
{
CompressionInfoTableOffset = stream.Get();
@@ -153,12 +211,15 @@ public void Write(IStream stream)
public string GetOffset()
{
- int offset = 0;
+
+ long offset = 0;
foreach (var item in CompressInfos)
{
offset += item.BufferOffset;
break;
}
+
+ Console.WriteLine(offset);
return "0x" + offset.ToString("X");
}
@@ -181,18 +242,16 @@ public byte[] GetFile()
foreach (var info in CompressInfos)
{
- string path = Path.ChangeExtension(Rmdtoc.rmdtocStream.Name, null) + "-" + info.FileIndex.ToString("D3") + ".rmdblob";
- Console.WriteLine(path);
- var stream = new FStream(path, FileMode.Open, FileAccess.Read);
-
- if (info.BufferSize == 0)
+ var stream = new FStream(GetRMDBLOBPath(info), FileMode.Open, FileAccess.Read);
+ stream.Position = info.BufferOffset;
+ if (info.BufferSize == 0 || info.isCompressed == 0)
{
- DecompressBuffer.SetBytes(stream.GetBytes(info.BufferUSize, false, info.BufferOffset));
+ DecompressBuffer.SetBytes(stream.GetBytes(info.BufferUSize));
}
else
{
- DecompressBuffer.SetBytes(LZ4Codec.Decode(stream.GetBytes(info.BufferSize, false, info.BufferOffset), 0, info.BufferSize, info.BufferUSize));
+ DecompressBuffer.SetBytes(LZ4Codec.Decode(stream.GetBytes(info.BufferSize), 0, info.BufferSize, info.BufferUSize));
}
stream.Close();
}
@@ -201,26 +260,75 @@ public byte[] GetFile()
return DecompressBuffer.ToArray();
}
- public string GetId()
+
+ public string GetRMDBLOBPath(CompressInfo info)
+ {
+ return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Rmdtoc.rmdtocStream.Name), Rmdtoc.RMDBLOBPaths[info.FileIndex].Path));
+ }
+
+ public string GetRMDBLOBPath()
{
- if (CompressInfos.Length == 0)
+ if(CompressInfos.Count==0)
{
return "";
}
+ return Path.GetFullPath( Path.Combine(Path.GetDirectoryName(Rmdtoc.rmdtocStream.Name), Rmdtoc.RMDBLOBPaths[CompressInfos[0].FileIndex].Path));
+ }
+ public byte[] GetRow()
+ {
- string path = Path.ChangeExtension(Rmdtoc.rmdtocStream.Name, null) + "-" + CompressInfos[0].FileIndex.ToString("D3") + ".rmdblob";
- Console.WriteLine(path);
- var stream = new FStream(path, FileMode.Open, FileAccess.Read);
+ var DecompressBuffer = new MStream();
+ foreach (var info in CompressInfos)
+ {
+
+ var stream = new FStream(GetRMDBLOBPath(info), FileMode.Open, FileAccess.Read);
+
+ stream.Position = info.BufferOffset;
+ DecompressBuffer.SetStringValue("Offset: " + stream.Position);
+ DecompressBuffer.SetStringValue("Size: " + info.BufferSize);
+ DecompressBuffer.SetStringValue("USize: " + info.BufferUSize);
+ DecompressBuffer.SetStringValue("IsCompressed: " + info.isCompressed);
+ DecompressBuffer.SetStringValue("Start");
+
+ if (info.BufferSize == 0 || info.isCompressed == 0)
+ {
+ DecompressBuffer.SetBytes(stream.GetBytes(info.BufferUSize));
+ }
+ else
+ {
+ DecompressBuffer.SetBytes(stream.GetBytes(info.BufferSize));
+ }
+ DecompressBuffer.SetStringValue("End of File");
+
+ stream.Close();
+ }
+
+
+ return DecompressBuffer.ToArray();
+
+
+
+ }
+ public string GetId()
+ {
+ if (CompressInfos.Count == 0)
+ {
+ return "";
+ }
+
+ var stream = new FStream(GetRMDBLOBPath(CompressInfos[0]), FileMode.Open, FileAccess.Read);
string id;
if (CompressInfos[0].BufferSize == 0)
{
- id = stream.GetStringValue(4, false, CompressInfos[0].BufferOffset);
+ stream.Position = CompressInfos[0].BufferOffset;
+ id = stream.GetStringValue(4);
}
else
{
- id = stream.GetStringValue(4, false, CompressInfos[0].BufferOffset + 1);
+ stream.Position = CompressInfos[0].BufferOffset + 1;
+ id = stream.GetStringValue(4);
}
@@ -233,22 +341,34 @@ public string GetId()
public void SetFile()
{
var info = CompressInfos[0];
- string path = Path.ChangeExtension(Rmdtoc.rmdtocStream.Name, null) + "-" + info.FileIndex.ToString("D3") + ".rmdblob";
- Console.WriteLine(path);
- var stream = new FStream(path, FileMode.Open, FileAccess.ReadWrite);
+ var stream = new FStream(GetRMDBLOBPath(info), FileMode.Open, FileAccess.ReadWrite);
- info.BufferUSize = NewFileBytes.Length;
- var CompressedBytes = LZ4Codec.Encode(NewFileBytes, 0, info.BufferUSize);
- info.BufferSize = CompressedBytes.Length;
+ byte[] CompressedBytes;
+ if (info.isCompressed != 0)
+ {
+ info.BufferUSize = NewFileBytes.Length;
+ CompressedBytes = LZ4Codec.Encode(NewFileBytes, 0, info.BufferUSize);
+ info.BufferSize = CompressedBytes.Length;
+ }
+ else
+ {
+ info.BufferUSize = NewFileBytes.Length;
+ CompressedBytes = NewFileBytes;
+ info.BufferSize = 0;
+ }
+
+ /////
stream.Seek(0, SeekOrigin.End);
info.BufferOffset = (int)stream.Position;
stream.SetBytes(CompressedBytes);
+ ////////
- CompressInfos = new CompressInfo[1];
- CompressInfos[0] = info;
- CompressionInfoTableSize = Marshal.SizeOf();
- DecompressSize = NewFileBytes.Length;
+ CompressInfos.Clear();
+ CompressInfos.Add(info);
+ ///
+ CompressionInfoTableSize = CompressInfo.Size * CompressInfos.Count;
+ DecompressSize = info.BufferUSize;
stream.Close();
IsEdited = false;
@@ -263,22 +383,17 @@ public void SetFile()
public class rmdtoc : IDisposable
{
-
public IStream rmdtocStream;
public rmdtocHeader header;
-
-
-
public rmdtoc(string rmdtocPath)
{
rmdtocStream = new FStream(rmdtocPath, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite);
-
-
Load();
}
public IStream BufferStream;
+ public IStream RMDBLOBPathBlock;
public IStream Table1;
public IStream Table2;
public IStream Table3;
@@ -287,24 +402,31 @@ public rmdtoc(string rmdtocPath)
public IStream NameTable;
public List Files;
public List Folders;
+ public List RMDBLOBPaths;
public TreeNode Root;
void Load()
{
header = rmdtocStream.Get();
-
BufferStream = new MStream(GetBuffer(rmdtocStream, header.CompressionInfoTableOffset, header.CompressionInfoTableSize));
+ RMDBLOBPathBlock = new MStream(BufferStream.GetBytes(header.RMDBLOB_Path_Count * RMDBLOBPath.Size, SeekToOffset: header.RMDBLOB_Path_Offset));
Table1 = new MStream(BufferStream.GetBytes(header.Table_1_Count * 0x1C, SeekToOffset: header.Table_1_Offset));
Table2 = new MStream(BufferStream.GetBytes(header.Table_2_Count * 0x20, SeekToOffset: header.Table_2_Offset));
Table3 = new MStream(BufferStream.GetBytes(header.Table_3_Count * 0x8, SeekToOffset: header.Table_3_Offset));
Table4 = new MStream(BufferStream.GetBytes(header.Table_4_Size, SeekToOffset: header.Table_4_Offset));
Table5 = new MStream(BufferStream.GetBytes(header.Table_5_Size, SeekToOffset: header.Table_5_Offset));
-
-
-
NameTable = new MStream(BufferStream.GetBytes(header.Names_Size, SeekToOffset: header.Names_Offset));
+ RMDBLOBPaths=new List();
+ for (int i = 0; i < header.RMDBLOB_Path_Count; i++)
+ {
+ var path = new RMDBLOBPath();
+ path.Read(RMDBLOBPathBlock);
+ path.Path = GetName(path.NameOffset, path.NameLength);
+ RMDBLOBPaths.Add(path);
+ }
+
Files = new List();
for (int i = 0; i < header.Table_2_Count; i++)
{
@@ -312,7 +434,16 @@ void Load()
file.Read(Table2);
file.Rmdtoc = this;
file.DMKPBlock = Table4.GetBytes(file.DMKPTableSize, false, file.DMKPTableOffset);
- file.CompressInfos = Table5.GetArray(file.CompressionInfoTableSize / Marshal.SizeOf(), false, file.CompressionInfoTableOffset);
+ file.CompressInfos = new List();
+
+ Table5.Seek(file.CompressionInfoTableOffset);
+ for (int j = 0; j < file.CompressionInfoTableSize / CompressInfo.Size; j++)
+ {
+ var info = new CompressInfo();
+ info.Read(Table5);
+ file.CompressInfos.Add(info);
+ }
+
file.Name = GetName(file.NameOffset, file.NameLength);
Files.Add(file);
}
@@ -344,7 +475,7 @@ void Load()
private void MakeNode(List folders, TreeNode node, FolderInfo Folder)
{
- for (int i = Folder.unko; i < Folder.unko + Folder.unko2; i++)
+ for (int i = Folder.FolderIndex; i < Folder.FolderIndex + Folder.FolderCount; i++)
{
Root = new TreeNode(folders[i].Name);
Root.Tag = folders[i];
@@ -362,11 +493,16 @@ public byte[] GetBuffer(IStream stream, long offset, int BlockSize)
var StoreOffset = stream.Position;
stream.Position = offset;
- for (int i = 0; i < BlockSize / Marshal.SizeOf(); i++)
+ for (int i = 0; i < BlockSize / CompressInfo.Size; i++)
{
- var info = stream.Get();
+ var info = new CompressInfo();
+ info.Read(stream);
- DecompressBuffer.SetBytes(LZ4Codec.Decode(stream.GetBytes(info.BufferSize, false, info.BufferOffset), 0, info.BufferSize, info.BufferUSize));
+ var pos = stream.Position;
+ stream.Seek(info.BufferOffset);
+ DecompressBuffer.SetBytes(LZ4Codec.Decode(stream.GetBytes(info.BufferSize), 0, info.BufferSize, info.BufferUSize));
+
+ stream.Position = pos;
}
stream.Position = StoreOffset;
@@ -385,7 +521,7 @@ private CompressInfo[] CompressFile(byte[] bytes, out byte[] CompressedBytes)
{
var info = new List();
var compressinfo = new CompressInfo();
- compressinfo.unko = 0x10;
+ compressinfo.isCompressed = 0x10;
compressinfo.BufferUSize = bytes.Length;
CompressedBytes = LZ4Codec.Encode(bytes, 0, compressinfo.BufferUSize);
compressinfo.BufferSize = CompressedBytes.Length;
@@ -407,7 +543,7 @@ public void Save()
file.CompressionInfoTableOffset = (int)Table5.Position;
foreach (var info in file.CompressInfos)
{
- Table5.SetStructureValus(info);
+ info.Write(Table5);
}
}
@@ -417,8 +553,12 @@ public void Save()
file.Write(Table2);
}
- BufferStream.SetSize(header.Table_1_Offset);
- BufferStream.SetPosition(header.Table_1_Offset);
+ BufferStream = new MStream();
+
+ header.RMDBLOB_Path_Offset = (int)BufferStream.Position;
+ BufferStream.SetBytes(RMDBLOBPathBlock.ToArray());
+
+ header.Table_1_Offset=(int)BufferStream.Position;
BufferStream.SetBytes(Table1.ToArray());
header.Table_2_Offset = (int)BufferStream.Position;
@@ -431,9 +571,11 @@ public void Save()
BufferStream.SetBytes(Table3.ToArray());
header.Table_4_Offset = (int)BufferStream.Position;
+ header.Table_4_Size = (int)Table4.GetSize();
BufferStream.SetBytes(Table4.ToArray());
header.Table_5_Offset = (int)BufferStream.Position;
+ header.Table_5_Size = (int)Table5.GetSize();
BufferStream.SetBytes(Table5.ToArray());
@@ -448,7 +590,7 @@ public void Save()
rmdtocStream.Seek(0);
rmdtocStream.SetBytes(new byte[4096], false);
- header.CompressionInfoTableSize = infoTable.Length * Marshal.SizeOf();
+ header.CompressionInfoTableSize = infoTable.Length * CompressInfo.Size;
rmdtocStream.SetStructureValus(header);
@@ -456,7 +598,7 @@ public void Save()
for (int i = 0; i < infoTable.Length; i++)
{
infoTable[i].BufferOffset = offset;
- rmdtocStream.SetStructureValus(infoTable[i]);
+ infoTable[i].Write(rmdtocStream);
offset += infoTable[i].BufferSize;
}
diff --git a/Forms/FrmMain.Designer.cs b/Forms/FrmMain.Designer.cs
index 464625c..6b9f3ab 100644
--- a/Forms/FrmMain.Designer.cs
+++ b/Forms/FrmMain.Designer.cs
@@ -49,11 +49,14 @@ private void InitializeComponent()
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.stringTableEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.exportRowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.treeView1 = new Controls.NTreeView();
this.listView1 = new Controls.NListView();
this.FileName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.Offset = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.Size = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.RMDBLOBPath = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.imageViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuStrip1.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.menuStrip1.SuspendLayout();
@@ -73,9 +76,10 @@ private void InitializeComponent()
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.eportSelectedToolStripMenuItem,
- this.replaceSelectedFileToolStripMenuItem});
+ this.replaceSelectedFileToolStripMenuItem,
+ this.exportRowToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1";
- this.contextMenuStrip1.Size = new System.Drawing.Size(181, 48);
+ this.contextMenuStrip1.Size = new System.Drawing.Size(230, 70);
//
// eportSelectedToolStripMenuItem
//
@@ -181,7 +185,8 @@ private void InitializeComponent()
// toolsToolStripMenuItem
//
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.stringTableEditorToolStripMenuItem});
+ this.stringTableEditorToolStripMenuItem,
+ this.imageViewerToolStripMenuItem});
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(46, 24);
this.toolsToolStripMenuItem.Text = "Tools";
@@ -210,6 +215,17 @@ private void InitializeComponent()
this.splitContainer1.SplitterDistance = 264;
this.splitContainer1.TabIndex = 2;
//
+ // exportRowToolStripMenuItem
+ //
+ this.exportRowToolStripMenuItem.Name = "exportRowToolStripMenuItem";
+ this.exportRowToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt)
+ | System.Windows.Forms.Keys.Shift)
+ | System.Windows.Forms.Keys.T)));
+ this.exportRowToolStripMenuItem.Size = new System.Drawing.Size(229, 22);
+ this.exportRowToolStripMenuItem.Text = "Export Row";
+ this.exportRowToolStripMenuItem.Visible = false;
+ this.exportRowToolStripMenuItem.Click += new System.EventHandler(this.exportRowToolStripMenuItem_Click);
+ //
// treeView1
//
this.treeView1.BackColor = System.Drawing.SystemColors.Window;
@@ -238,7 +254,8 @@ private void InitializeComponent()
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.FileName,
this.Offset,
- this.Size});
+ this.Size,
+ this.RMDBLOBPath});
this.listView1.ContextMenuStrip = this.contextMenuStrip1;
this.listView1.Font = new System.Drawing.Font("Tahoma", 10F);
this.listView1.HideSelection = false;
@@ -268,6 +285,17 @@ private void InitializeComponent()
this.Size.Text = "Size";
this.Size.Width = 193;
//
+ // RMDBLOBPath
+ //
+ this.RMDBLOBPath.Text = "RMDBLOB Archive Path";
+ //
+ // imageViewerToolStripMenuItem
+ //
+ this.imageViewerToolStripMenuItem.Name = "imageViewerToolStripMenuItem";
+ this.imageViewerToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.imageViewerToolStripMenuItem.Text = "Image Viewer";
+ this.imageViewerToolStripMenuItem.Click += new System.EventHandler(this.imageViewerToolStripMenuItem_Click);
+ //
// FrmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -321,6 +349,9 @@ private void TreeView1_BeforeClear(object sender, System.EventArgs e)
private System.Windows.Forms.ToolStripMenuItem replaceSelectedFileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
+ private System.Windows.Forms.ToolStripMenuItem exportRowToolStripMenuItem;
+ private System.Windows.Forms.ColumnHeader RMDBLOBPath;
+ private System.Windows.Forms.ToolStripMenuItem imageViewerToolStripMenuItem;
}
}
diff --git a/Forms/FrmMain.cs b/Forms/FrmMain.cs
index 0865df6..b34198c 100644
--- a/Forms/FrmMain.cs
+++ b/Forms/FrmMain.cs
@@ -166,16 +166,62 @@ private void listView1_DoubleClick(object sender, EventArgs e)
if (fileInfo.Name == "string_table.bin" || fileInfo.GetId() == "RMDL")
{
- var MStream = new MStream(fileInfo.GetFile());
+ var MStream = new MStream(fileInfo.Name, fileInfo.GetFile());
var frm = new FrmStringTable(MStream);
if (frm.ShowDialog() == DialogResult.OK)
{
- fileInfo.IsEdited = true;
- fileInfo.NewFileBytes = MStream.ToArray();
- Modifiedtrmdtoc.Add(fileInfo.Rmdtoc);
- MessageBox.Show("Done!");
+ try
+ {
+ fileInfo.IsEdited = true;
+ fileInfo.NewFileBytes = MStream.ToArray();
+ Modifiedtrmdtoc.Add(fileInfo.Rmdtoc);
+ MessageBox.Show("Done!");
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ }
}
}
+ else if (fileInfo.Name.EndsWith(".png", StringComparison.InvariantCulture) ||
+ fileInfo.Name.EndsWith(".jpg", StringComparison.InvariantCulture) ||
+ fileInfo.Name.EndsWith(".bmp", StringComparison.InvariantCulture) ||
+ fileInfo.Name.EndsWith(".tga", StringComparison.InvariantCulture) ||
+ fileInfo.Name.EndsWith(".dds", StringComparison.InvariantCulture) ||
+ fileInfo.Name.EndsWith(".tex", StringComparison.InvariantCulture))
+ {
+ try
+ {
+ var MStream = new MStream(fileInfo.Name, fileInfo.GetFile());
+ var frm = new frmImageViewer(MStream);
+ frm.ShowDialog();
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ }
+ }
+
+
+ }
+
+ private void exportRowToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ FolderDialog folderDialog = new FolderDialog();
+ if (folderDialog.ShowDialog() != DialogResult.OK)
+ return;
+ foreach (ListViewItem item in listView1.SelectedItems)
+ {
+ var fileInfo = item.Tag as FileInfo;
+ File.WriteAllBytes(Path.Combine(folderDialog.FileName, fileInfo.Name), fileInfo.GetRow());
+ }
+
+ MessageBox.Show("Done!");
+ }
+
+ private void imageViewerToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ new frmImageViewer().Show();
}
}
}
diff --git a/Forms/FrmMain.resx b/Forms/FrmMain.resx
index 9bbd0a4..f0b684c 100644
--- a/Forms/FrmMain.resx
+++ b/Forms/FrmMain.resx
@@ -125,7 +125,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAC4
- BwAAAk1TRnQBSQFMAwEBAAFwAQEBcAEBARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
+ BwAAAk1TRnQBSQFMAwEBAAFAAQIBQAECARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
AUADAAEQAwABAQEAAQgGAAEEGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA
AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA
AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm
@@ -172,7 +172,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAC0
- BwAAAk1TRnQBSQFMAwEBAAFsAQEBbAEBARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
+ BwAAAk1TRnQBSQFMAwEBAAE8AQIBPAECARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA
AUADAAEQAwABAQEAAQgGAAEEGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA
AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA
AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm
diff --git a/Forms/FrmStringTable.Designer.cs b/Forms/FrmStringTable.Designer.cs
index e1d3914..1474a82 100644
--- a/Forms/FrmStringTable.Designer.cs
+++ b/Forms/FrmStringTable.Designer.cs
@@ -34,10 +34,19 @@ private void InitializeComponent()
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.namesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.valuesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.bothToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.importAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.namesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.valuesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.bothToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.TableName = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.TableValue = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.searchBox1 = new Controls.SearchBox();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.findToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
@@ -66,7 +75,7 @@ private void InitializeComponent()
//
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
- this.openToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.openToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.openToolStripMenuItem.Text = "Open";
this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
//
@@ -75,7 +84,7 @@ private void InitializeComponent()
this.saveToolStripMenuItem.Enabled = false;
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
this.saveToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));
- this.saveToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.saveToolStripMenuItem.Size = new System.Drawing.Size(146, 22);
this.saveToolStripMenuItem.Text = "Save";
this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click);
//
@@ -83,7 +92,9 @@ private void InitializeComponent()
//
this.toolToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.exportAllToolStripMenuItem,
- this.importAllToolStripMenuItem});
+ this.importAllToolStripMenuItem,
+ this.toolStripSeparator1,
+ this.findToolStripMenuItem});
this.toolToolStripMenuItem.Enabled = false;
this.toolToolStripMenuItem.Name = "toolToolStripMenuItem";
this.toolToolStripMenuItem.Size = new System.Drawing.Size(41, 20);
@@ -91,18 +102,68 @@ private void InitializeComponent()
//
// exportAllToolStripMenuItem
//
+ this.exportAllToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.namesToolStripMenuItem,
+ this.valuesToolStripMenuItem,
+ this.bothToolStripMenuItem1});
this.exportAllToolStripMenuItem.Name = "exportAllToolStripMenuItem";
- this.exportAllToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.exportAllToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
this.exportAllToolStripMenuItem.Text = "Export All";
this.exportAllToolStripMenuItem.Click += new System.EventHandler(this.exportAllToolStripMenuItem_Click);
//
+ // namesToolStripMenuItem
+ //
+ this.namesToolStripMenuItem.Name = "namesToolStripMenuItem";
+ this.namesToolStripMenuItem.Size = new System.Drawing.Size(111, 22);
+ this.namesToolStripMenuItem.Text = "Names";
+ this.namesToolStripMenuItem.Click += new System.EventHandler(this.namesToolStripMenuItem_Click);
+ //
+ // valuesToolStripMenuItem
+ //
+ this.valuesToolStripMenuItem.Name = "valuesToolStripMenuItem";
+ this.valuesToolStripMenuItem.Size = new System.Drawing.Size(111, 22);
+ this.valuesToolStripMenuItem.Text = "Values";
+ this.valuesToolStripMenuItem.Click += new System.EventHandler(this.valuesToolStripMenuItem_Click);
+ //
+ // bothToolStripMenuItem1
+ //
+ this.bothToolStripMenuItem1.Name = "bothToolStripMenuItem1";
+ this.bothToolStripMenuItem1.Size = new System.Drawing.Size(111, 22);
+ this.bothToolStripMenuItem1.Text = "Both";
+ this.bothToolStripMenuItem1.Click += new System.EventHandler(this.bothToolStripMenuItem1_Click);
+ //
// importAllToolStripMenuItem
//
+ this.importAllToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.namesToolStripMenuItem1,
+ this.valuesToolStripMenuItem1,
+ this.bothToolStripMenuItem});
this.importAllToolStripMenuItem.Name = "importAllToolStripMenuItem";
- this.importAllToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.importAllToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
this.importAllToolStripMenuItem.Text = "Import All";
this.importAllToolStripMenuItem.Click += new System.EventHandler(this.importAllToolStripMenuItem_Click);
//
+ // namesToolStripMenuItem1
+ //
+ this.namesToolStripMenuItem1.Name = "namesToolStripMenuItem1";
+ this.namesToolStripMenuItem1.Size = new System.Drawing.Size(111, 22);
+ this.namesToolStripMenuItem1.Text = "Names";
+ this.namesToolStripMenuItem1.Click += new System.EventHandler(this.namesToolStripMenuItem1_Click);
+ //
+ // valuesToolStripMenuItem1
+ //
+ this.valuesToolStripMenuItem1.Name = "valuesToolStripMenuItem1";
+ this.valuesToolStripMenuItem1.Size = new System.Drawing.Size(111, 22);
+ this.valuesToolStripMenuItem1.Text = "Values";
+ this.valuesToolStripMenuItem1.Click += new System.EventHandler(this.valuesToolStripMenuItem1_Click);
+ //
+ // bothToolStripMenuItem
+ //
+ this.bothToolStripMenuItem.Name = "bothToolStripMenuItem";
+ this.bothToolStripMenuItem.Size = new System.Drawing.Size(111, 22);
+ this.bothToolStripMenuItem.Text = "Both";
+ this.bothToolStripMenuItem.Click += new System.EventHandler(this.bothToolStripMenuItem_Click);
+ //
// dataGridView1
//
this.dataGridView1.AllowUserToAddRows = false;
@@ -114,9 +175,10 @@ private void InitializeComponent()
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView1.Location = new System.Drawing.Point(0, 24);
this.dataGridView1.Name = "dataGridView1";
- this.dataGridView1.Size = new System.Drawing.Size(801, 524);
+ this.dataGridView1.Size = new System.Drawing.Size(801, 494);
this.dataGridView1.TabIndex = 1;
this.dataGridView1.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellValueChanged);
+ this.dataGridView1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.dataGridView1_KeyDown);
//
// TableName
//
@@ -129,6 +191,28 @@ private void InitializeComponent()
this.TableValue.HeaderText = "Text Value";
this.TableValue.Name = "TableValue";
//
+ // searchBox1
+ //
+ this.searchBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.searchBox1.DataGridView = this.dataGridView1;
+ this.searchBox1.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.searchBox1.Location = new System.Drawing.Point(0, 518);
+ this.searchBox1.Name = "searchBox1";
+ this.searchBox1.Size = new System.Drawing.Size(801, 30);
+ this.searchBox1.TabIndex = 2;
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6);
+ //
+ // findToolStripMenuItem
+ //
+ this.findToolStripMenuItem.Name = "findToolStripMenuItem";
+ this.findToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.findToolStripMenuItem.Text = "Find";
+ this.findToolStripMenuItem.Click += new System.EventHandler(this.findToolStripMenuItem_Click);
+ //
// FrmStringTable
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -136,10 +220,12 @@ private void InitializeComponent()
this.ClientSize = new System.Drawing.Size(801, 548);
this.Controls.Add(this.dataGridView1);
this.Controls.Add(this.menuStrip1);
+ this.Controls.Add(this.searchBox1);
this.MainMenuStrip = this.menuStrip1;
this.Name = "FrmStringTable";
this.ShowIcon = false;
this.Text = "String Table Editor";
+ this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FrmStringTable_KeyDown);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
@@ -160,5 +246,14 @@ private void InitializeComponent()
private System.Windows.Forms.ToolStripMenuItem toolToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportAllToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem importAllToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem namesToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem valuesToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem namesToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem valuesToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem bothToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem bothToolStripMenuItem1;
+ private Controls.SearchBox searchBox1;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.ToolStripMenuItem findToolStripMenuItem;
}
}
\ No newline at end of file
diff --git a/Forms/FrmStringTable.cs b/Forms/FrmStringTable.cs
index ca8297f..7f19eb4 100644
--- a/Forms/FrmStringTable.cs
+++ b/Forms/FrmStringTable.cs
@@ -113,6 +113,15 @@ private void saveToolStripMenuItem_Click(object sender, EventArgs e)
}
private void exportAllToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+
+ }
+
+ private void importAllToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ }
+
+ private void namesToolStripMenuItem_Click(object sender, EventArgs e)
{
var sdf = new SaveFileDialog();
sdf.Filter = "Text Files|*.txt";
@@ -124,7 +133,7 @@ private void exportAllToolStripMenuItem_Click(object sender, EventArgs e)
var sb = new System.Text.StringBuilder();
foreach (var Table in stringtable as List)
{
- sb.AppendLine(Table.Name + "=" + Table.Value);
+ sb.AppendLine(Table.Name);
}
File.WriteAllText(sdf.FileName, sb.ToString());
@@ -132,7 +141,71 @@ private void exportAllToolStripMenuItem_Click(object sender, EventArgs e)
MessageBox.Show("Done!");
}
- private void importAllToolStripMenuItem_Click(object sender, EventArgs e)
+ private void valuesToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var sdf = new SaveFileDialog();
+ sdf.Filter = "Text Files|*.txt";
+ sdf.Title = "Save Text File";
+ sdf.FileName = Path.GetFileName(Stream.Name) + ".txt";
+ if (sdf.ShowDialog() != DialogResult.OK)
+ return;
+
+ var sb = new System.Text.StringBuilder();
+ foreach (var Table in stringtable as List)
+ {
+ sb.AppendLine(Table.Value);
+ }
+
+ File.WriteAllText(sdf.FileName, sb.ToString());
+
+ MessageBox.Show("Done!");
+ }
+
+ private void namesToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ var ofd = new OpenFileDialog();
+ ofd.Filter = "Text Files|*.txt";
+ ofd.Title = "Select Text File";
+ ofd.FileName = Path.GetFileName(Stream.Name) + ".txt";
+ if (ofd.ShowDialog() != DialogResult.OK)
+ return;
+
+ var lines = File.ReadAllLines(ofd.FileName);
+ int i = 0;
+ foreach (var line in lines)
+ {
+ if (i >= dataGridView1.Rows.Count) break;
+ var Table = dataGridView1.Rows[i++];
+ Table.Cells["TableName"].Value = line;
+ }
+
+ MessageBox.Show("Done!");
+ }
+
+ private void valuesToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ var ofd = new OpenFileDialog();
+ ofd.Filter = "Text Files|*.txt";
+ ofd.Title = "Select Text File";
+ ofd.FileName = Path.GetFileName(Stream.Name) + ".txt";
+ if (ofd.ShowDialog() != DialogResult.OK)
+ return;
+
+ var lines = File.ReadAllLines(ofd.FileName);
+ int i = 0;
+ foreach (var line in lines)
+ {
+ if (i >= dataGridView1.Rows.Count) break;
+
+ var Table = dataGridView1.Rows[i++];
+ Table.Cells["TableValue"].Value = line;
+
+ }
+
+ MessageBox.Show("Done!");
+ }
+
+ private void bothToolStripMenuItem_Click(object sender, EventArgs e)
{
var ofd = new OpenFileDialog();
ofd.Filter = "Text Files|*.txt";
@@ -145,7 +218,8 @@ private void importAllToolStripMenuItem_Click(object sender, EventArgs e)
int i = 0;
foreach (var line in lines)
{
- var split = line.Split(new[] { '=' },2);
+ if (i >= dataGridView1.Rows.Count) break;
+ var split = line.Split(new[] { '=' }, 2);
if (split.Length != 2)
continue;
@@ -157,11 +231,41 @@ private void importAllToolStripMenuItem_Click(object sender, EventArgs e)
Table.Cells["TableValue"].Value = value;
}
-
MessageBox.Show("Done!");
+ }
+ private void bothToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ var sdf = new SaveFileDialog();
+ sdf.Filter = "Text Files|*.txt";
+ sdf.Title = "Save Text File";
+ sdf.FileName = Path.GetFileName(Stream.Name) + ".txt";
+ if (sdf.ShowDialog() != DialogResult.OK)
+ return;
+ var sb = new System.Text.StringBuilder();
+ foreach (var Table in stringtable as List)
+ {
+ sb.AppendLine(Table.Name+"="+ Table.Value);
+ }
+ }
+ private void FrmStringTable_KeyDown(object sender, KeyEventArgs e)
+ {
+
+ }
+
+ private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Control && e.KeyCode == Keys.F)
+ {
+ searchBox1.Visible = true;
+ }
+ }
+
+ private void findToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ searchBox1.Visible = true;
}
}
}
diff --git a/Forms/FrmStringTable.resx b/Forms/FrmStringTable.resx
index 87c5092..0210eaa 100644
--- a/Forms/FrmStringTable.resx
+++ b/Forms/FrmStringTable.resx
@@ -126,4 +126,10 @@
True
+
+ True
+
+
+ True
+
\ No newline at end of file
diff --git a/Forms/frmImageViewer.Designer.cs b/Forms/frmImageViewer.Designer.cs
new file mode 100644
index 0000000..06c82cd
--- /dev/null
+++ b/Forms/frmImageViewer.Designer.cs
@@ -0,0 +1,102 @@
+namespace alan_wake_2_rmdtoc_Tool.Forms
+{
+ partial class frmImageViewer
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ this.menuStrip1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.fileToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Padding = new System.Windows.Forms.Padding(0);
+ this.menuStrip1.Size = new System.Drawing.Size(800, 24);
+ this.menuStrip1.TabIndex = 0;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // fileToolStripMenuItem
+ //
+ this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.openToolStripMenuItem});
+ this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+ this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
+ this.fileToolStripMenuItem.Text = "File";
+ //
+ // openToolStripMenuItem
+ //
+ this.openToolStripMenuItem.Name = "openToolStripMenuItem";
+ this.openToolStripMenuItem.Size = new System.Drawing.Size(103, 22);
+ this.openToolStripMenuItem.Text = "Open";
+ this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.pictureBox1.Location = new System.Drawing.Point(0, 24);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(800, 426);
+ this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+ this.pictureBox1.TabIndex = 1;
+ this.pictureBox1.TabStop = false;
+ //
+ // frmImageViewer
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.SystemColors.ButtonShadow;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.Controls.Add(this.pictureBox1);
+ this.Controls.Add(this.menuStrip1);
+ this.MainMenuStrip = this.menuStrip1;
+ this.Name = "frmImageViewer";
+ this.ShowIcon = false;
+ this.Text = "Image Viwer";
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
+ private System.Windows.Forms.PictureBox pictureBox1;
+ }
+}
\ No newline at end of file
diff --git a/Forms/frmImageViewer.cs b/Forms/frmImageViewer.cs
new file mode 100644
index 0000000..ae43b39
--- /dev/null
+++ b/Forms/frmImageViewer.cs
@@ -0,0 +1,58 @@
+using Helper;
+using System;
+using System.IO;
+using System.Windows.Forms;
+
+namespace alan_wake_2_rmdtoc_Tool.Forms
+{
+ public partial class frmImageViewer : Form
+ {
+ bool IsStreamFile = false;
+ public IStream Stream;
+ public frmImageViewer()
+ {
+ InitializeComponent();
+ }
+
+ public frmImageViewer(IStream stream)
+ {
+
+ InitializeComponent();
+ Stream = stream;
+ IsStreamFile = false;
+ openToolStripMenuItem.Visible = false;
+ PrintImage();
+ }
+
+ private void openToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var ofd = new OpenFileDialog();
+ ofd.Filter = "All Images|*.tex;*.dds;*.png;*.jpg;*.bmp;*.tga";
+ ofd.Title = "Select Image";
+ if (ofd.ShowDialog() != DialogResult.OK)
+ return;
+
+ Stream = FStream.Open(ofd.FileName, FileMode.Open, FileAccess.Read);
+ PrintImage();
+ }
+
+ private void PrintImage()
+ {
+ if (Stream.GetIntValue(false) == 0x20534444)
+ {
+ pictureBox1.Image = DDSToBitmap.Convert(Stream);
+ }
+ else if (Stream.Name.EndsWith(".png", StringComparison.InvariantCulture) ||
+ Stream.Name.EndsWith(".jpg", StringComparison.InvariantCulture) ||
+ Stream.Name.EndsWith(".bmp", StringComparison.InvariantCulture) ||
+ Stream.Name.EndsWith(".tga", StringComparison.InvariantCulture))
+ {
+ pictureBox1.Image = System.Drawing.Image.FromStream((Stream)Stream);
+ }
+ else
+ {
+ MessageBox.Show("Not supported file!");
+ }
+ }
+ }
+}
diff --git a/Forms/frmImageViewer.resx b/Forms/frmImageViewer.resx
new file mode 100644
index 0000000..d5494e3
--- /dev/null
+++ b/Forms/frmImageViewer.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/Helper/DDSCooker.cs b/Helper/DDSCooker.cs
new file mode 100644
index 0000000..0ce10a7
--- /dev/null
+++ b/Helper/DDSCooker.cs
@@ -0,0 +1,1038 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using System.Text;
+
+
+namespace Helper
+{
+
+ public enum DDSFormat : uint
+ {
+ unknown = 0,
+ r32g32b32a32_typeless,
+ r32g32b32a32_float,
+ r32g32b32a32_uint,
+ r32g32b32a32_sint,
+ r32g32b32_typeless,
+ r32g32b32_float,
+ r32g32b32_uint,
+ r32g32b32_sint,
+ r16g16b16a16_typeless,
+ r16g16b16a16_float,
+ r16g16b16a16_unorm,
+ r16g16b16a16_uint,
+ r16g16b16a16_snorm,
+ r16g16b16a16_sint,
+ r32g32_typeless,
+ r32g32_float,
+ r32g32_uint,
+ r32g32_sint,
+ r32g8x24_typeless,
+ d32_float_s8x24_uint,
+ r32_float_x8x24_typeless,
+ x32_typeless_g8x24_uint,
+ r10g10b10a2_typeless,
+ r10g10b10a2_unorm,
+ r10g10b10a2_uint,
+ r11g11b10_float,
+ r8g8b8a8_typeless,
+ r8g8b8a8_unorm,
+ r8g8b8a8_unorm_srgb,
+ r8g8b8a8_uint,
+ r8g8b8a8_snorm,
+ r8g8b8a8_sint,
+ r16g16_typeless,
+ r16g16_float,
+ r16g16_unorm,
+ r16g16_uint,
+ r16g16_snorm,
+ r16g16_sint,
+ r32_typeless,
+ d32_float,
+ r32_float,
+ r32_uint,
+ r32_sint,
+ r24g8_typeless,
+ d24_unorm_s8_uint,
+ r24_unorm_x8_typeless,
+ x24_typeless_g8_uint,
+ r8g8_typeless,
+ [Description("A8L8")]
+ r8g8_unorm,
+ r8g8_uint,
+ [Description("V8U8")]
+ r8g8_snorm,
+ r8g8_sint,
+ r16_typeless,
+ r16_float,
+ d16_unorm,
+ r16_unorm,
+ r16_uint,
+ r16_snorm,
+ r16_sint,
+ r8_typeless,
+ [Description("L8")]
+ r8_unorm,
+ r8_uint,
+ r8_snorm,
+ r8_sint,
+ [Description("A8")]
+ a8_unorm,
+ r1_unorm,
+ r9g9b9e5_sharedexp,
+ [Description("RGBG or GBGR")]
+ r8g8_b8g8_unorm,
+ g8r8_g8b8_unorm,
+ bc1_typeless,
+ [Description("DXT1")]
+ bc1_unorm,
+ [Description("DXT1")]
+ bc1_unorm_srgb,
+ bc2_typeless,
+ [Description("DXT2")]
+ bc2_unorm,
+ [Description("DXT2")]
+ bc2_unorm_srgb,
+ bc3_typeless,
+ [Description("DXT5")]
+ bc3_unorm,
+ [Description("DXT5")]
+ bc3_unorm_srgb,
+ bc4_typeless,
+ [Description("BC4U")]
+ bc4_unorm,
+ [Description("BC4S")]
+ bc4_snorm,
+ bc5_typeless,
+ [Description("ATI2 or BC5U")]
+ bc5_unorm,
+ [Description("BC5S")]
+ bc5_snorm,
+ b5g6r5_unorm,
+ [Description("B5G5R5A1 A1R5G5B5")]
+ b5g5r5a1_unorm,
+ [Description("A8R8G8B8")]
+ b8g8r8a8_unorm,
+ [Description("X8R8G8B8")]
+ b8g8r8x8_unorm,
+ r10g10b10_xr_bias_a2_unorm,
+ b8g8r8a8_typeless,
+ [Description("A8B8G8R8")]
+ b8g8r8a8_unorm_srgb,
+ b8g8r8x8_typeless,
+ [Description("X8B8G8R8")]
+ b8g8r8x8_unorm_srgb,
+ bc6h_typeless,
+ bc6h_uf16,
+ bc6h_sf16,
+ bc7_typeless,
+ bc7_unorm,
+ bc7_unorm_srgb,
+ ayuv,
+ y410,
+ y416,
+ nv12,
+ p010,
+ p016,
+ opaque,
+ [Description("YUY2")]
+ yuy2,
+ y210,
+ y216,
+ nv11,
+ ai44,
+ ia44,
+ p8,
+ a8p8,
+ [Description("A4R4G4B4")]
+ b4g4r4a4_unorm,
+ p208,
+ v208,
+ v408
+ }
+ public static class DDSCooker //Todo
+ {
+
+
+
+ public static uint BitsPerPixel(DDSFormat fmt)
+ {
+ switch (fmt)
+ {
+ case DDSFormat.r32g32b32a32_typeless:
+ case DDSFormat.r32g32b32a32_float:
+ case DDSFormat.r32g32b32a32_uint:
+ case DDSFormat.r32g32b32a32_sint:
+ return 128;
+
+ case DDSFormat.r32g32b32_typeless:
+ case DDSFormat.r32g32b32_float:
+ case DDSFormat.r32g32b32_uint:
+ case DDSFormat.r32g32b32_sint:
+ return 96;
+
+ case DDSFormat.r16g16b16a16_typeless:
+ case DDSFormat.r16g16b16a16_float:
+ case DDSFormat.r16g16b16a16_unorm:
+ case DDSFormat.r16g16b16a16_uint:
+ case DDSFormat.r16g16b16a16_snorm:
+ case DDSFormat.r16g16b16a16_sint:
+ case DDSFormat.r32g32_typeless:
+ case DDSFormat.r32g32_float:
+ case DDSFormat.r32g32_uint:
+ case DDSFormat.r32g32_sint:
+ case DDSFormat.r32g8x24_typeless:
+ case DDSFormat.d32_float_s8x24_uint:
+ case DDSFormat.r32_float_x8x24_typeless:
+ case DDSFormat.x32_typeless_g8x24_uint:
+ return 64;
+
+ case DDSFormat.r10g10b10a2_typeless:
+ case DDSFormat.r10g10b10a2_unorm:
+ case DDSFormat.r10g10b10a2_uint:
+ case DDSFormat.r11g11b10_float:
+ case DDSFormat.r8g8b8a8_typeless:
+ case DDSFormat.r8g8b8a8_unorm:
+ case DDSFormat.r8g8b8a8_unorm_srgb:
+ case DDSFormat.r8g8b8a8_uint:
+ case DDSFormat.r8g8b8a8_snorm:
+ case DDSFormat.r8g8b8a8_sint:
+ case DDSFormat.r16g16_typeless:
+ case DDSFormat.r16g16_float:
+ case DDSFormat.r16g16_unorm:
+ case DDSFormat.r16g16_uint:
+ case DDSFormat.r16g16_snorm:
+ case DDSFormat.r16g16_sint:
+ case DDSFormat.r32_typeless:
+ case DDSFormat.d32_float:
+ case DDSFormat.r32_float:
+ case DDSFormat.r32_uint:
+ case DDSFormat.r32_sint:
+ case DDSFormat.r24g8_typeless:
+ case DDSFormat.d24_unorm_s8_uint:
+ case DDSFormat.r24_unorm_x8_typeless:
+ case DDSFormat.x24_typeless_g8_uint:
+ case DDSFormat.r9g9b9e5_sharedexp:
+ case DDSFormat.r8g8_b8g8_unorm:
+ case DDSFormat.g8r8_g8b8_unorm:
+ case DDSFormat.b8g8r8a8_unorm:
+ case DDSFormat.b8g8r8x8_unorm:
+ case DDSFormat.r10g10b10_xr_bias_a2_unorm:
+ case DDSFormat.b8g8r8a8_typeless:
+ case DDSFormat.b8g8r8a8_unorm_srgb:
+ case DDSFormat.b8g8r8x8_typeless:
+ case DDSFormat.b8g8r8x8_unorm_srgb:
+ return 32;
+
+ case DDSFormat.r8g8_typeless:
+ case DDSFormat.r8g8_unorm:
+ case DDSFormat.r8g8_uint:
+ case DDSFormat.r8g8_snorm:
+ case DDSFormat.r8g8_sint:
+ case DDSFormat.r16_typeless:
+ case DDSFormat.r16_float:
+ case DDSFormat.d16_unorm:
+ case DDSFormat.r16_unorm:
+ case DDSFormat.r16_uint:
+ case DDSFormat.r16_snorm:
+ case DDSFormat.r16_sint:
+ case DDSFormat.b5g6r5_unorm:
+ case DDSFormat.b5g5r5a1_unorm:
+ case DDSFormat.b4g4r4a4_unorm:
+ return 16;
+
+ case DDSFormat.r8_typeless:
+ case DDSFormat.r8_unorm:
+ case DDSFormat.r8_uint:
+ case DDSFormat.r8_snorm:
+ case DDSFormat.r8_sint:
+ case DDSFormat.a8_unorm:
+ return 8;
+
+ case DDSFormat.r1_unorm:
+ return 1;
+
+ case DDSFormat.bc1_typeless:
+ case DDSFormat.bc1_unorm:
+ case DDSFormat.bc1_unorm_srgb:
+ case DDSFormat.bc4_typeless:
+ case DDSFormat.bc4_unorm:
+ case DDSFormat.bc4_snorm:
+ return 4;
+
+ case DDSFormat.bc2_typeless:
+ case DDSFormat.bc2_unorm:
+ case DDSFormat.bc2_unorm_srgb:
+ case DDSFormat.bc3_typeless:
+ case DDSFormat.bc3_unorm:
+ case DDSFormat.bc3_unorm_srgb:
+ case DDSFormat.bc5_typeless:
+ case DDSFormat.bc5_unorm:
+ case DDSFormat.bc5_snorm:
+ case DDSFormat.bc6h_typeless:
+ case DDSFormat.bc6h_uf16:
+ case DDSFormat.bc6h_sf16:
+ case DDSFormat.bc7_typeless:
+ case DDSFormat.bc7_unorm:
+ case DDSFormat.bc7_unorm_srgb:
+ return 8;
+
+ default:
+ return 0;
+ }
+ }
+
+
+ public static (uint, uint, uint, uint) GetMask(DDSFormat format)
+ {
+ switch (format)
+ {
+ //RGBBitCount=32
+ case DDSFormat.r8g8b8a8_unorm:
+ return (0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+
+ case DDSFormat.r10g10b10a2_unorm:
+ return (0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000);
+
+ case DDSFormat.r16g16_unorm:
+ return (0x0000ffff, 0xffff0000, 0x00000000, 0x00000000);
+
+ case DDSFormat.r32_float:
+ return (0xffffffff, 0x00000000, 0x00000000, 0x00000000);
+
+ case DDSFormat.b8g8r8a8_unorm:
+ return (0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
+
+ case DDSFormat.b8g8r8x8_unorm:
+ return (0x00ff0000, 0x0000ff00, 0x000000ff, 0);
+
+ case DDSFormat.b8g8r8x8_unorm_srgb:
+ return (0x000000ff, 0x0000ff00, 0x00ff0000, 0);
+
+
+
+
+ //RGBBitCount=16
+ case DDSFormat.b5g5r5a1_unorm:
+ return (0x7C00, 0x3E0, 0x1F, 0x8000);
+ case DDSFormat.b5g6r5_unorm:
+ return (0xf8000000, 0x07e00000, 0x001f0000, 0x00000000);
+ case DDSFormat.b4g4r4a4_unorm:
+ return (0x0f000000, 0x00f00000, 0x000f0000, 0xf0000000);
+ case DDSFormat.r16_unorm:
+ return (0x0000ffff, 0x00000000, 0x00000000, 0x00000000);
+ case DDSFormat.r8g8_unorm:
+ return (0xff, 0x00000000, 0x00000000, 0xFF00);
+
+
+ //RGBBitCount=8
+
+ case DDSFormat.r8_unorm:
+ return (0xff, 0x0, 0x0, 0x0);
+
+ case DDSFormat.a8_unorm:
+ return (0x0, 0x0, 0x0, 0xff);
+
+ default:
+ return (0x00000000, 0x00000000, 0x00000000, 0x00000000);
+
+
+ }
+ }
+
+
+
+
+ [Flags]
+ public enum DDSPixelFormatFlags
+ {
+ D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
+ DDSCAPS_COMPLEX = 0x8,
+ DDSCAPS_MIPMAP = 0x400000,
+ DDSCAPS_TEXTURE = 0x1000
+ }
+
+ [Flags]
+ enum D3D10_RESOURCE_DIMENSION
+ {
+ D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
+ D3D10_RESOURCE_DIMENSION_BUFFER = 1,
+ D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
+ D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
+ D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4
+ }
+
+
+ [Flags]
+ public enum HeaderFlags
+ {
+ ///
+ /// Required in every .dds file.
+ ///
+ DDSD_CAPS = 0x1,
+ ///
+ /// Required in every .dds file.
+ ///
+ DDSD_HEIGHT = 0x2,
+ ///
+ /// Required in every .dds file.
+ ///
+ DDSD_WIDTH = 0x4,
+ ///
+ /// Required when pitch is provided for an uncompressed texture.
+ ///
+ DDSD_PITCH = 0x8,
+ ///
+ /// Required in every .dds file.
+ ///
+ DDSD_PIXELFORMAT = 0x1000,
+ ///
+ /// Required in a mipmapped texture.
+ ///
+ DDSD_MIPMAPCOUNT = 0x20000,
+ ///
+ /// Required when pitch is provided for a compressed texture.
+ ///
+ DDSD_LINEARSIZE = 0x80000,
+ ///
+ /// Required in a depth texture.
+ ///
+ DDSD_DEPTH = 0x800000
+ }
+
+ [Flags]
+ public enum DDSCAPS
+ {
+ ///
+ /// Optional; must be used on any file that contains more than one surface (a mipmap, a cubic environment map, or mipmapped volume texture).
+ ///
+ DDSCAPS_COMPLEX = 0x8,
+ ///
+ /// Required
+ ///
+ DDSCAPS_TEXTURE = 0x1000,
+ ///
+ /// Optional; should be used for a mipmap.
+ ///
+ DDSCAPS_MIPMAP = 0x400000
+ }
+
+ [Flags]
+ public enum DDSCAPS2
+ {
+ ///
+ /// Required for a cube map.
+ ///
+ DDSCAPS2_CUBEMAP = 0x200,
+ ///
+ /// Required when these surfaces are stored in a cube map.
+ ///
+ DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
+ ///
+ /// Required when these surfaces are stored in a cube map.
+ ///
+ DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
+ ///
+ /// Required when these surfaces are stored in a cube map.
+ ///
+ DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
+ ///
+ /// Required when these surfaces are stored in a cube map.
+ ///
+ DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
+ ///
+ /// Required when these surfaces are stored in a cube map.
+ ///
+ DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
+ ///
+ /// Required when these surfaces are stored in a cube map.
+ ///
+ DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
+ ///
+ /// Required for a volume texture.
+ ///
+ DDSCAPS2_VOLUME = 0x200000
+ }
+
+
+ public enum DDPF
+ {
+ ///
+ /// Texture contains alpha data; dwRGBAlphaBitMask contains valid data.
+ ///
+ DDPF_ALPHAPIXELS = 0x1,
+ ///
+ /// Used in some older DDS files for alpha channel only uncompressed data (dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data)
+ ///
+ DDPF_ALPHA = 0x2,
+ ///
+ /// Texture contains compressed RGB data; dwFourCC contains valid data.
+ ///
+ DDPF_FOURCC = 0x4,
+ ///
+ /// Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks(dwRBitMask, dwGBitMask, dwBBitMask) contain valid data.
+ ///
+ DDPF_RGB = 0x40,
+ ///
+ /// Used in some older DDS files for YUV uncompressed data(dwRGBBitCount contains the YUV bit count; dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask)
+ ///
+ DDPF_YUV = 0x200,
+ ///
+ /// Used in some older DDS files for single channel color uncompressed data(dwRGBBitCount contains the luminance channel bit count; dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file.
+ ///
+ DDPF_LUMINANCEA = 0x20001, //DDPF_LUMINANCE| DDPF_ALPHAPIXELS
+ DDPF_LUMINANCE = 0x20000,
+
+
+ DDPF_RGBA = 0x41, //DDPF_RGB | DDPF_ALPHAPIXELS
+ DDPF_PAL8 = 0x20,
+ DDPF_PAL8A = 0x21, //DDPF_PAL8 | DDPF_ALPHAPIXELS
+ DDPF_BUMPDUDV = 0x80000
+ }
+
+ enum DDS_DIMENSION
+ {
+ ///
+ /// (D3D10_RESOURCE_DIMENSION_TEXTURE1D) Resource is a 1D texture.The dwWidth member of DDS_HEADER specifies the size of the texture.Typically, you set the dwHeight member of DDS_HEADER to 1; you also must set the DDSD_HEIGHT flag in the dwFlags member of DDS_HEADER.
+ ///
+ DDS_DIMENSION_TEXTURE1D = 2,
+ ///
+ /// (D3D10_RESOURCE_DIMENSION_TEXTURE2D) Resource is a 2D texture with an area specified by the dwWidth and dwHeight members of DDS_HEADER.You can also use this type to identify a cube-map texture.For more information about how to identify a cube-map texture, see miscFlag and arraySize members.
+ ///
+ DDS_DIMENSION_TEXTURE2D = 3,
+ ///
+ /// (D3D10_RESOURCE_DIMENSION_TEXTURE3D) Resource is a 3D texture with a volume specified by the dwWidth, dwHeight, and dwDepth members of DDS_HEADER.You also must set the DDSD_DEPTH flag in the dwFlags member of DDS_HEADER.
+ ///
+ DDS_DIMENSION_TEXTURE3D = 4
+ }
+
+
+ ///
+ /// Indicates a 2D texture is a cube-map texture.
+ ///
+ static uint DDS_RESOURCE_MISC_TEXTURECUBE = 0x4;
+
+
+
+ enum DDS_ALPHA_MODE
+ {
+ ///
+ /// Alpha channel content is unknown. This is the value for legacy files, which typically is assumed to be 'straight' alpha.
+ ///
+ DDS_ALPHA_MODE_UNKNOWN = 0x0,
+ ///
+ /// Any alpha channel content is presumed to use straight alpha.
+ ///
+ DDS_ALPHA_MODE_STRAIGHT = 0x1,
+ ///
+ /// Any alpha channel content is using premultiplied alpha.The only legacy file formats that indicate this information are 'DX2' and 'DX4'.
+ ///
+ DDS_ALPHA_MODE_PREMULTIPLIED = 0x2,
+ ///
+ /// Any alpha channel content is all set to fully opaque.
+ ///
+ DDS_ALPHA_MODE_OPAQUE = 0x3,
+ ///
+ /// Any alpha channel content is being used as a 4th channel and is not intended to represent transparency (straight or premultiplied).
+ ///
+ DDS_ALPHA_MODE_CUSTOM = 0x4,
+ }
+
+
+
+
+
+
+ public static byte[] TexToDds(byte[] bytes, DDSFormat format, int height, int width, int mipmap = 0, int depth = 0, bool UseDX10 = false)
+ {
+ MStream Tex = new MStream(bytes);
+ Tex.SetStringValue("DDS ");
+ Tex.SetIntValue(124);//block size
+ HeaderFlags flags = HeaderFlags.DDSD_CAPS | HeaderFlags.DDSD_HEIGHT | HeaderFlags.DDSD_WIDTH | HeaderFlags.DDSD_PIXELFORMAT;
+
+
+ if (depth != 0)
+ {
+ flags |= HeaderFlags.DDSD_DEPTH;
+ }
+
+ if (mipmap > 1)
+ {
+ flags |= HeaderFlags.DDSD_MIPMAPCOUNT;
+ }
+
+ //if (format == Format.bc1_unorm || format == Format.bc2_unorm || format == Format.bc3_unorm)
+ //{
+ // flags |= HeaderFlags.DDSD_LINEARSIZE;
+ //}
+
+ Tex.SetUIntValue((uint)flags);
+ Tex.SetIntValue(height);
+ Tex.SetIntValue(width);
+ Tex.SetIntValue(0); //pitchOrLinearSize
+ Tex.SetIntValue(depth);
+ Tex.SetIntValue(mipmap);
+
+ Tex.Skip(44); //reserved1
+
+ Tex.SetIntValue(32); //block size
+ DDPF dwFlags = 0;
+ if (format == DDSFormat.bc1_unorm || format == DDSFormat.bc2_unorm || format == DDSFormat.bc3_unorm || UseDX10)
+ {
+ dwFlags = DDPF.DDPF_FOURCC;
+ }
+ else if (format == DDSFormat.r8_unorm || format == DDSFormat.r16_unorm || format == DDSFormat.r8g8_unorm)
+ {
+ dwFlags = DDPF.DDPF_LUMINANCE;
+ }
+ else if (format == DDSFormat.a8_unorm)
+ {
+ dwFlags = DDPF.DDPF_ALPHA;
+ }
+ else
+ {
+ dwFlags = DDPF.DDPF_ALPHAPIXELS | DDPF.DDPF_RGB;
+ }
+
+ // dwFlags//
+ Tex.SetUIntValue((uint)dwFlags); //block size
+
+ bool ISDX10 = false;
+ if (format == DDSFormat.bc1_unorm)
+ {
+ Tex.SetStringValue("DXT1");
+ }
+ else if (format == DDSFormat.bc2_unorm)
+ {
+ Tex.SetStringValue("DXT3");
+ }
+ else if (format == DDSFormat.bc3_unorm)
+ {
+ Tex.SetStringValue("DXT5");
+ }
+ else if (format == DDSFormat.bc4_unorm)
+ {
+ Tex.SetStringValue("ATI1");
+ }
+ else if (format == DDSFormat.bc5_unorm)
+ {
+ Tex.SetStringValue("ATI2");
+ }
+ else
+ {
+ if (!UseDX10)
+ {
+ Tex.SetIntValue(0);
+ }
+ else
+ {
+ Tex.SetStringValue("DX10");
+ ISDX10 = true;
+ }
+ }
+
+ uint RGBBitCount = 0;
+ uint RBitMask = 0;
+ uint GBitMask = 0;
+ uint BBitMask = 0;
+ uint ABitMask = 0;
+
+ if (!ISDX10)
+ {
+ RGBBitCount = BitsPerPixel(format);
+ (RBitMask, GBitMask, BBitMask, ABitMask) = GetMask(format);
+ }
+
+ Tex.SetUIntValue(RGBBitCount); //RGBBitCount
+ Tex.SetUIntValue(RBitMask); //RBitMask
+ Tex.SetUIntValue(GBitMask); //GBitMask
+ Tex.SetUIntValue(BBitMask); //BBitMask
+ Tex.SetUIntValue(ABitMask); //ABitMask
+
+ DDSCAPS Caps = DDSCAPS.DDSCAPS_TEXTURE;
+
+ if (mipmap > 1)
+ {
+ Caps |= DDSCAPS.DDSCAPS_MIPMAP;
+ }
+
+ if (mipmap > 1 || depth > 1)
+ {
+ Caps |= DDSCAPS.DDSCAPS_COMPLEX;
+ }
+
+ Tex.SetUIntValue((uint)Caps);
+
+ DDSCAPS2 Caps2 = 0;
+ Tex.SetUIntValue((uint)Caps2);
+ Tex.SetUIntValue(0);//Caps3
+ Tex.SetUIntValue(0);//Caps4
+ Tex.SetUIntValue(0);//reserved2
+
+ if (ISDX10)
+ {
+ Tex.SetUIntValue((uint)format);//DXGI_FORMAT
+ Tex.SetUIntValue((uint)DDS_DIMENSION.DDS_DIMENSION_TEXTURE2D);//D3D10_RESOURCE_DIMENSION
+ Tex.SetUIntValue(0);//miscFlag
+ Tex.SetUIntValue(1);//arraySize //For a 3D texture, you must set this number to 1.
+ Tex.SetUIntValue((uint)DDS_ALPHA_MODE.DDS_ALPHA_MODE_UNKNOWN);//miscFlags2
+ }
+
+ Tex.SetBytes(bytes);
+
+ return Tex.ToArray();
+ }
+
+
+
+
+ public struct DDS_HEADER
+ {
+ public uint Magic;
+ public uint size;
+ [MarshalAs(UnmanagedType.U4)]
+ public HeaderFlags flags;
+ public int height;
+ public int width;
+ public int pitchOrLinearSize;
+ public int depth;
+ public int mipMapCount;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
+ public uint[] reserved1;
+ public DDS_PIXELFORMAT ddspf;
+ [MarshalAs(UnmanagedType.U4)]
+ public DDSCAPS caps;
+ [MarshalAs(UnmanagedType.U4)]
+ public DDSCAPS2 caps2;
+ public uint caps3;
+ public uint caps4;
+ public uint reserved2;
+
+ }
+
+
+ public struct DDS_PIXELFORMAT
+ {
+ public int size;
+ [MarshalAs(UnmanagedType.U4)]
+ public DDPF flags;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+ public byte[] fourCC;
+ public uint RGBBitCount;
+ public uint RBitMask;
+ public uint GBitMask;
+ public uint BBitMask;
+ public uint ABitMask;
+ }
+
+
+ public struct dxt10_header
+ {
+ [MarshalAs(UnmanagedType.U4)]
+ public DDSFormat dxgiFormat;
+ public uint resourceDimension;
+ public uint miscFlag;
+ public uint arraySize;
+ public uint miscFlags2;
+ }
+
+ public struct DDS_Info
+ {
+ public DDSFormat Format { get; set; }
+ public DDS_HEADER DDS_HEADER { get; set; }
+ public dxt10_header dxt10_Header { get; set; }
+ public byte[] Data { get; set; }
+ }
+
+
+
+ public static DDS_Info DdsToTex(byte[] bytes)
+ {
+
+ MStream memoryList = new MStream(bytes);
+
+ if (memoryList.GetIntValue(false) != 0x20534444)
+ {
+ throw new Exception("Invalid dds file");
+ }
+
+ DDS_Info dds_info = new DDS_Info();
+ dds_info.DDS_HEADER = memoryList.GetStructureValues();
+ if (BitConverter.ToInt32(dds_info.DDS_HEADER.ddspf.fourCC, 0) == 0x30315844)
+ {
+ dds_info.dxt10_Header = memoryList.GetStructureValues();
+ dds_info.Format = dds_info.dxt10_Header.dxgiFormat;
+ }
+ dds_info.Data = memoryList.GetBytes((int)(memoryList.GetSize() - memoryList.GetPosition()));
+
+
+ if (dds_info.Format == default)
+ {
+
+ dds_info.Format = GetFormat(dds_info.DDS_HEADER.ddspf);
+ }
+#if false
+ Console.WriteLine("dxgiFormat: " + dds_info.Format.ToString());
+ Console.WriteLine("RGBBitCount: " + dds_info.DDS_HEADER.ddspf.RGBBitCount);
+ Console.WriteLine("Has Flag: " + dds_info.DDS_HEADER.ddspf.flags.Equals(DDPF.DDPF_RGBA));
+ Console.WriteLine("Has RBitMask: " + dds_info.DDS_HEADER.ddspf.RBitMask);
+ Console.WriteLine("Has GBitMask: " + dds_info.DDS_HEADER.ddspf.GBitMask);
+ Console.WriteLine("Has BBitMask: " + dds_info.DDS_HEADER.ddspf.BBitMask);
+ Console.WriteLine("Has ABitMask: " + dds_info.DDS_HEADER.ddspf.ABitMask);
+ Console.WriteLine("width: " + dds_info.DDS_HEADER.width);
+ Console.WriteLine("height: " + dds_info.DDS_HEADER.height);
+ Console.WriteLine("flags: " + dds_info.DDS_HEADER.ddspf.flags.ToString());
+ Console.WriteLine("caps: " + dds_info.DDS_HEADER.caps.ToString());
+ Console.WriteLine("caps2: " + dds_info.DDS_HEADER.caps2.ToString());
+#endif
+ return dds_info;
+ }
+
+
+ ///
+ /// this function is for stream and return DDS_Info.Data
+ ///
+ ///
+ ///
+ ///
+ public static DDS_Info DdsToTex(IStream stream)
+ {
+
+ if (stream.GetIntValue(false) != 0x20534444)
+ {
+ throw new Exception("Invalid dds file");
+ }
+
+ DDS_Info dds_info = new DDS_Info();
+ dds_info.DDS_HEADER = stream.GetStructureValues();
+ if (BitConverter.ToInt32(dds_info.DDS_HEADER.ddspf.fourCC, 0) == 0x30315844)
+ {
+ dds_info.dxt10_Header = stream.GetStructureValues();
+ dds_info.Format = dds_info.dxt10_Header.dxgiFormat;
+ }
+
+ if (dds_info.Format == default)
+ {
+
+ dds_info.Format = GetFormat(dds_info.DDS_HEADER.ddspf);
+ }
+#if false
+ Console.WriteLine("dxgiFormat: " + dds_info.Format.ToString());
+ Console.WriteLine("RGBBitCount: " + dds_info.DDS_HEADER.ddspf.RGBBitCount);
+ Console.WriteLine("Has Flag: " + dds_info.DDS_HEADER.ddspf.flags.Equals(DDPF.DDPF_RGBA));
+ Console.WriteLine("Has RBitMask: " + dds_info.DDS_HEADER.ddspf.RBitMask);
+ Console.WriteLine("Has GBitMask: " + dds_info.DDS_HEADER.ddspf.GBitMask);
+ Console.WriteLine("Has BBitMask: " + dds_info.DDS_HEADER.ddspf.BBitMask);
+ Console.WriteLine("Has ABitMask: " + dds_info.DDS_HEADER.ddspf.ABitMask);
+ Console.WriteLine("width: " + dds_info.DDS_HEADER.width);
+ Console.WriteLine("height: " + dds_info.DDS_HEADER.height);
+ Console.WriteLine("flags: " + dds_info.DDS_HEADER.ddspf.flags.ToString());
+ Console.WriteLine("caps: " + dds_info.DDS_HEADER.caps.ToString());
+ Console.WriteLine("caps2: " + dds_info.DDS_HEADER.caps2.ToString());
+#endif
+ return dds_info;
+ }
+
+
+
+ static bool ISSameMask(DDS_PIXELFORMAT ddspf, uint RBitMask, uint GBitMask, uint BBitMask, uint ABitMask)
+ {
+ return ddspf.RBitMask == RBitMask &&
+ ddspf.GBitMask == GBitMask &&
+ ddspf.BBitMask == BBitMask &&
+ ddspf.ABitMask == ABitMask;
+ }
+
+
+ private static DDSFormat GetFormat(DDS_PIXELFORMAT ddspf)
+ {
+
+
+
+ if (ddspf.flags > 0 && (ddspf.flags.Equals(DDPF.DDPF_RGB) || ddspf.flags.Equals(DDPF.DDPF_RGBA)))
+ {
+
+ switch (ddspf.RGBBitCount)
+ {
+
+ case 32:
+ {
+ if (ISSameMask(ddspf, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))
+ {
+ return DDSFormat.r8g8b8a8_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000))
+ {
+ return DDSFormat.r10g10b10a2_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000))
+ {
+ return DDSFormat.r16g16_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0xffffffff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ return DDSFormat.r32_float;
+ }
+
+ if (ISSameMask(ddspf, 0x00ff0000, 0x0000ff00, 0x000000ff, 0))
+ {
+ return DDSFormat.b8g8r8x8_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0x000000ff, 0x0000ff00, 0x00ff0000, 0))
+ {
+ return DDSFormat.b8g8r8x8_unorm_srgb;
+ }
+
+ if (ISSameMask(ddspf, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000))
+ {
+
+ return DDSFormat.b8g8r8a8_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000))
+ {
+ return DDSFormat.b8g8r8a8_unorm_srgb;
+ }
+ break;
+ }
+
+ case 24:
+
+ if (ISSameMask(ddspf, 0xff0000, 0x00ff00, 0x0000ff, 0))
+ {
+ return DDSFormat.unknown; //R8G8B8
+ }
+ break;
+ case 16:
+ {
+
+
+ if (ISSameMask(ddspf, 0x7C00, 0x3E0, 0x1F, 0x8000))
+ {
+ return DDSFormat.b5g5r5a1_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0xf8000000, 0x07e00000, 0x001f0000, 0x00000000))
+ {
+ return DDSFormat.b5g6r5_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0x0f000000, 0x00f00000, 0x000f0000, 0xf0000000))
+ {
+ return DDSFormat.b4g4r4a4_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0x00ff, 0, 0, 0xff00))
+ {
+ return DDSFormat.r8g8_uint;
+ }
+ break;
+ }
+ }
+ }
+ else if (ddspf.flags > 0 && (ddspf.flags.Equals(DDPF.DDPF_LUMINANCE) || ddspf.flags.Equals(DDPF.DDPF_LUMINANCEA)))
+ {
+ switch (ddspf.RGBBitCount)
+ {
+ case 8:
+ {
+ if (ISSameMask(ddspf, 0x000000ff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ return DDSFormat.r8_unorm;
+ }
+ if (ISSameMask(ddspf, 0xff, 0, 0, 0))
+ {
+ return DDSFormat.r8_uint;
+ }
+ break;
+ }
+ case 16:
+ {
+ if (ISSameMask(ddspf, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000))
+ {
+ return DDSFormat.r16_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0xFF, 0xFF00, 0x0, 0x0))
+ {
+ return DDSFormat.r8g8_unorm;
+ }
+
+ if (ISSameMask(ddspf, 0xff, 0x00000000, 0x00000000, 0xFF00))
+ {
+ return DDSFormat.r8g8_unorm;
+ }
+
+
+ if (ISSameMask(ddspf, 0xFF, 0xFF00, 0x0, 0x0))
+ {
+ return DDSFormat.r8g8_unorm;
+ }
+ break;
+ }
+
+
+ }
+
+
+ }
+ else if (ddspf.flags > 0 && ddspf.flags.Equals(DDPF.DDPF_ALPHA))
+ {
+ if (ddspf.RGBBitCount == 8)
+ {
+ return DDSFormat.a8_unorm;
+ }
+ }
+
+ else if (ddspf.flags > 0 && ddspf.flags.Equals(DDPF.DDPF_BUMPDUDV))
+ {
+
+ switch (ddspf.RGBBitCount)
+ {
+ case 16:
+ {
+ if (ISSameMask(ddspf, 0x00ff, 0xff00, 0, 0))
+ {
+ return DDSFormat.r8g8_snorm;
+ }
+
+ break;
+ }
+ }
+ }
+ else if (ddspf.flags > 0 && ddspf.flags.Equals(DDPF.DDPF_FOURCC))
+ {
+ switch (Encoding.ASCII.GetString(ddspf.fourCC))
+ {
+ case "DXT1":
+ return DDSFormat.bc1_unorm;
+ case "DXT3":
+ return DDSFormat.bc2_unorm;
+ case "DXT5":
+ return DDSFormat.bc3_unorm;
+ case "BC4U":
+ return DDSFormat.bc4_unorm;
+ case "BC4S":
+ return DDSFormat.bc4_snorm;
+ case "RGBG":
+ case "GBGR":
+ return DDSFormat.r8g8_b8g8_unorm;
+ case "BC5U":
+ case "ATI2":
+ return DDSFormat.r8g8_b8g8_unorm;
+ case "BC5S":
+ return DDSFormat.bc5_snorm;
+ case "YUY2":
+ return DDSFormat.yuy2;
+
+ }
+ }
+ return DDSFormat.unknown;
+ }
+ }
+}
diff --git a/Helper/DDSToBitmap.cs b/Helper/DDSToBitmap.cs
new file mode 100644
index 0000000..a4e524d
--- /dev/null
+++ b/Helper/DDSToBitmap.cs
@@ -0,0 +1,623 @@
+using System;
+using System.Collections;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using static Helper.DDSCooker;
+
+namespace Helper
+{
+ public class DDSToBitmap
+ {
+ private static DDS_Info info { get; set; }
+
+ //from http://code.google.com/p/kprojects
+ #region DXT1
+ static private Bitmap UncompressDXT1(IStream stream, int w, int h)
+ {
+ Bitmap res = new Bitmap((w < 4) ? 4 : w, (h < 4) ? 4 : h);
+
+ for (int j = 0; j < h; j += 4)
+ {
+ for (int i = 0; i < w; i += 4)
+ {
+ DecompressBlockDXT1(i, j, stream.GetBytes(8), res);
+ }
+ }
+ return res;
+ }
+
+ static private void DecompressBlockDXT1(int x, int y, byte[] blockStorage, Bitmap image)
+ {
+ ushort color0 = (ushort)(blockStorage[0] | blockStorage[1] << 8);
+ ushort color1 = (ushort)(blockStorage[2] | blockStorage[3] << 8);
+
+ int temp;
+
+ temp = (color0 >> 11) * 255 + 16;
+ byte r0 = (byte)((temp / 32 + temp) / 32);
+ temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
+ byte g0 = (byte)((temp / 64 + temp) / 64);
+ temp = (color0 & 0x001F) * 255 + 16;
+ byte b0 = (byte)((temp / 32 + temp) / 32);
+
+ temp = (color1 >> 11) * 255 + 16;
+ byte r1 = (byte)((temp / 32 + temp) / 32);
+ temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
+ byte g1 = (byte)((temp / 64 + temp) / 64);
+ temp = (color1 & 0x001F) * 255 + 16;
+ byte b1 = (byte)((temp / 32 + temp) / 32);
+
+ uint code = (uint)(blockStorage[4] | blockStorage[5] << 8 | blockStorage[6] << 16 | blockStorage[7] << 24);
+
+ for (int j = 0; j < 4; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ Color finalColor = Color.FromArgb(0);
+ byte positionCode = (byte)((code >> 2 * (4 * j + i)) & 0x03);
+
+ if (color0 > color1)
+ {
+ switch (positionCode)
+ {
+ case 0:
+ finalColor = Color.FromArgb(255, r0, g0, b0);
+ break;
+ case 1:
+ finalColor = Color.FromArgb(255, r1, g1, b1);
+ break;
+ case 2:
+ finalColor = Color.FromArgb(255, (2 * r0 + r1) / 3, (2 * g0 + g1) / 3, (2 * b0 + b1) / 3);
+ break;
+ case 3:
+ finalColor = Color.FromArgb(255, (r0 + 2 * r1) / 3, (g0 + 2 * g1) / 3, (b0 + 2 * b1) / 3);
+ break;
+ }
+ }
+ else
+ {
+ switch (positionCode)
+ {
+ case 0:
+ finalColor = Color.FromArgb(255, r0, g0, b0);
+ break;
+ case 1:
+ finalColor = Color.FromArgb(255, r1, g1, b1);
+ break;
+ case 2:
+ finalColor = Color.FromArgb(255, (r0 + r1) / 2, (g0 + g1) / 2, (b0 + b1) / 2);
+ break;
+ case 3:
+ finalColor = Color.FromArgb(255, 0, 0, 0);
+ break;
+ }
+ }
+
+ image.SetPixel(x + i, y + j, finalColor);
+ }
+ }
+ }
+ #endregion
+ //from http://code.google.com/p/kprojects
+ #region DXT5
+ static private Bitmap UncompressDXT5(IStream stream, int w, int h)
+ {
+ Bitmap res = new Bitmap((w < 4) ? 4 : w, (h < 4) ? 4 : h);
+
+ for (int j = 0; j < h; j += 4)
+ {
+ for (int i = 0; i < w; i += 4)
+ {
+ DecompressBlockDXT5(i, j, stream.GetBytes(16), res);
+ }
+ }
+ return res;
+ }
+
+ static void DecompressBlockDXT5(int x, int y, byte[] blockStorage, Bitmap image)
+ {
+ byte alpha0 = blockStorage[0];
+ byte alpha1 = blockStorage[1];
+
+ int bitOffset = 2;
+ uint alphaCode1 = (uint)(blockStorage[bitOffset + 2] | (blockStorage[bitOffset + 3] << 8) | (blockStorage[bitOffset + 4] << 16) | (blockStorage[bitOffset + 5] << 24));
+ ushort alphaCode2 = (ushort)(blockStorage[bitOffset + 0] | (blockStorage[bitOffset + 1] << 8));
+
+ ushort color0 = (ushort)(blockStorage[8] | blockStorage[9] << 8);
+ ushort color1 = (ushort)(blockStorage[10] | blockStorage[11] << 8);
+
+ int temp;
+
+ temp = (color0 >> 11) * 255 + 16;
+ byte r0 = (byte)((temp / 32 + temp) / 32);
+ temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
+ byte g0 = (byte)((temp / 64 + temp) / 64);
+ temp = (color0 & 0x001F) * 255 + 16;
+ byte b0 = (byte)((temp / 32 + temp) / 32);
+
+ temp = (color1 >> 11) * 255 + 16;
+ byte r1 = (byte)((temp / 32 + temp) / 32);
+ temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
+ byte g1 = (byte)((temp / 64 + temp) / 64);
+ temp = (color1 & 0x001F) * 255 + 16;
+ byte b1 = (byte)((temp / 32 + temp) / 32);
+
+ uint code = (uint)(blockStorage[12] | blockStorage[13] << 8 | blockStorage[14] << 16 | blockStorage[15] << 24);
+
+ for (int j = 0; j < 4; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ int alphaCodeIndex = 3 * (4 * j + i);
+ int alphaCode;
+
+ if (alphaCodeIndex <= 12)
+ {
+ alphaCode = (alphaCode2 >> alphaCodeIndex) & 0x07;
+ }
+ else if (alphaCodeIndex == 15)
+ {
+ alphaCode = (int)((alphaCode2 >> 15) | ((alphaCode1 << 1) & 0x06));
+ }
+ else
+ {
+ alphaCode = (int)((alphaCode1 >> (alphaCodeIndex - 16)) & 0x07);
+ }
+
+ byte finalAlpha;
+ if (alphaCode == 0)
+ {
+ finalAlpha = alpha0;
+ }
+ else if (alphaCode == 1)
+ {
+ finalAlpha = alpha1;
+ }
+ else
+ {
+ if (alpha0 > alpha1)
+ {
+ finalAlpha = (byte)(((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7);
+ }
+ else
+ {
+ if (alphaCode == 6)
+ finalAlpha = 0;
+ else if (alphaCode == 7)
+ finalAlpha = 255;
+ else
+ finalAlpha = (byte)(((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5);
+ }
+ }
+
+ byte colorCode = (byte)((code >> 2 * (4 * j + i)) & 0x03);
+
+ Color finalColor = new Color();
+ switch (colorCode)
+ {
+ case 0:
+ finalColor = Color.FromArgb(finalAlpha, r0, g0, b0);
+ break;
+ case 1:
+ finalColor = Color.FromArgb(finalAlpha, r1, g1, b1);
+ break;
+ case 2:
+ finalColor = Color.FromArgb(finalAlpha, (2 * r0 + r1) / 3, (2 * g0 + g1) / 3, (2 * b0 + b1) / 3);
+ break;
+ case 3:
+ finalColor = Color.FromArgb(finalAlpha, (r0 + 2 * r1) / 3, (g0 + 2 * g1) / 3, (b0 + 2 * b1) / 3);
+ break;
+ }
+ image.SetPixel(x + i, y + j, finalColor);
+ }
+ }
+ }
+ #endregion
+ //from https://github.com/ME3Tweaks/ME3ExplorerLib/blob/c9144346af32d9cab674f2cd0ad1bcb3358ed34f/Helpers/DDSImage.cs
+ #region DXT3
+ private static Bitmap UncompressDXT3(IStream stream, int w, int h)
+ {
+ const int bufferSize = 16;
+ byte[] blockStorage = new byte[bufferSize];
+ using (MemoryStream bitmapStream = new MemoryStream(w * h * 2))
+ {
+ using (BinaryWriter bitmapBW = new BinaryWriter(bitmapStream))
+ {
+ int ptr = 0;
+ for (int s = 0; s < h; s += 4)
+ {
+ for (int t = 0; t < w; t += 4)
+ {
+ blockStorage=stream.GetBytes(bufferSize, false, ptr);
+ ptr += bufferSize;
+ {
+ int color0 = blockStorage[8] | blockStorage[9] << 8;
+ int color1 = blockStorage[10] | blockStorage[11] << 8;
+
+ int temp;
+
+ temp = (color0 >> 11) * 255 + 16;
+ int r0 = ((temp >> 5) + temp) >> 5;
+ temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
+ int g0 = ((temp >> 6) + temp) >> 6;
+ temp = (color0 & 0x001F) * 255 + 16;
+ int b0 = ((temp >> 5) + temp) >> 5;
+
+ temp = (color1 >> 11) * 255 + 16;
+ int r1 = ((temp >> 5) + temp) >> 5;
+ temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
+ int g1 = ((temp >> 6) + temp) >> 6;
+ temp = (color1 & 0x001F) * 255 + 16;
+ int b1 = ((temp >> 5) + temp) >> 5;
+
+ int code = blockStorage[12] | blockStorage[13] << 8 | blockStorage[14] << 16 | blockStorage[15] << 24;
+
+ for (int j = 0; j < 4; j++)
+ {
+ bitmapStream.Seek(((s + j) * w * 4) + (t * 4), SeekOrigin.Begin);
+ for (int i = 0; i < 4; i++)
+ {
+ byte alpha = (byte)((blockStorage[(j * i) < 8 ? 0 : 1] >> (((i * j) % 8) * 4)) & 0xFF);
+ alpha = (byte)((alpha << 4) | alpha);
+ if (!IsAlpha())
+ alpha = 0xFF;
+
+ int fCol = 0;
+ int colorCode = (code >> 2 * (4 * j + i)) & 0x03;
+
+ switch (colorCode)
+ {
+ case 0:
+ fCol = b0 | g0 << 8 | r0 << 16 | 0xFF << alpha;
+ break;
+ case 1:
+ fCol = b1 | g1 << 8 | r1 << 16 | 0xFF << alpha;
+ break;
+ case 2:
+ fCol = (2 * b0 + b1) / 3 | (2 * g0 + g1) / 3 << 8 | (2 * r0 + r1) / 3 << 16 | 0xFF << alpha;
+ break;
+ case 3:
+ fCol = (b0 + 2 * b1) / 3 | (g0 + 2 * g1) / 3 << 8 | (r0 + 2 * r1) / 3 << 16 | 0xFF << alpha;
+ break;
+ }
+
+ bitmapBW.Write(fCol);
+ }
+ }
+ }
+ }
+ }
+
+
+ var bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+ {
+ BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,
+ bmp.Width,
+ bmp.Height),
+ ImageLockMode.WriteOnly,
+ bmp.PixelFormat);
+
+ Marshal.Copy(bitmapStream.ToArray(), 0, bmpData.Scan0, (int)bitmapStream.Length);
+ bmp.UnlockBits(bmpData);
+ }
+
+ return bmp;
+ }
+ }
+ }
+ #endregion
+
+ #region A8R8G8B8 or X8R8G8B8 or A8B8G8R8 or X8B8G8R8
+ static private Bitmap Uncompress8_8_8_8(IStream stream, int w, int h)
+ {
+ uint RBitMask = info.DDS_HEADER.ddspf.RBitMask;
+ uint GBitMask = info.DDS_HEADER.ddspf.GBitMask;
+ uint BBitMask = info.DDS_HEADER.ddspf.BBitMask;
+ uint ABitMask = info.DDS_HEADER.ddspf.ABitMask;
+
+
+ if (info.DDS_HEADER.ddspf.RGBBitCount == 0)
+ {
+ (RBitMask, GBitMask, BBitMask, ABitMask) = DDSCooker.GetMask(info.Format);
+ }
+
+ Bitmap bitmap = new Bitmap(w, h);
+ for (int y = 0; y < bitmap.Height; y++)
+ {
+ for (int x = 0; x < bitmap.Width; x++)
+ {
+ uint RGBABits = stream.GetUIntValue();
+ int b = GetMaskValue(BBitMask, RGBABits);
+ int g = GetMaskValue(GBitMask, RGBABits);
+ int r = GetMaskValue(RBitMask, RGBABits);
+ int a = GetMaskValue(ABitMask, RGBABits);
+ if (!IsAlpha())
+ {
+ a = 255;
+ }
+ bitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
+ }
+
+ }
+ return bitmap;
+ }
+ #endregion
+
+ #region A8L8
+ static private Bitmap UncompressA8L8(IStream stream, int w, int h)
+ {
+ Bitmap bitmap = new Bitmap(w, h);
+
+ for (int y = 0; y < bitmap.Height; y++)
+ {
+ for (int x = 0; x < bitmap.Width; x++)
+ {
+ uint RGBABits = stream.GetUShortValue();
+ int b = GetMaskValue(info.DDS_HEADER.ddspf.BBitMask, RGBABits);
+ int g = GetMaskValue(info.DDS_HEADER.ddspf.GBitMask, RGBABits);
+ int r = GetMaskValue(info.DDS_HEADER.ddspf.RBitMask, RGBABits);
+ int a = GetMaskValue(info.DDS_HEADER.ddspf.ABitMask, RGBABits);
+ if (!IsAlpha())
+ {
+ a = 255;
+ }
+ bitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
+ }
+
+ }
+ return bitmap;
+ }
+ #endregion
+
+ #region V8U8
+ static private Bitmap UncompressV8U8(IStream stream, int w, int h)
+ {
+ Bitmap bitmap = new Bitmap(w, h);
+ int Step = 0;
+ for (int y = 0; y < bitmap.Height; y++)
+ {
+ for (int x = 0; x < bitmap.Width; x++)
+ {
+ uint RGBABits = stream.GetUShortValue();
+ int r = 0x7F + (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.RBitMask, RGBABits);
+ int g = 0x7F + (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.GBitMask, RGBABits);
+ int b = 0xff;
+ int a = 0xff;
+
+ bitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
+ }
+
+ }
+ return bitmap;
+ }
+ #endregion
+
+ #region B4G4R4A4
+ static private Bitmap UncompressB4G4R4A4(IStream stream, int w, int h)
+ {
+ Bitmap bitmap = new Bitmap(w, h);
+ int Step = 0;
+ for (int y = 0; y < bitmap.Height; y++)
+ {
+ for (int x = 0; x < bitmap.Width; x++)
+ {
+ uint RGBABits = stream.GetUShortValue();
+ int r = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.RBitMask, RGBABits) << 4;
+ int g = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.GBitMask, RGBABits) << 4;
+ int b = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.BBitMask, RGBABits) << 4;
+ int a = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.ABitMask, RGBABits) << 4;
+ bitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
+ }
+
+ }
+ return bitmap;
+ }
+ #endregion
+
+ #region B5G5R5A1
+ static private Bitmap UncompressB5G5R5A1(IStream stream, int w, int h)
+ {
+ Bitmap bitmap = new Bitmap(w, h);
+ for (int y = 0; y < bitmap.Height; y++)
+ {
+ for (int x = 0; x < bitmap.Width; x++)
+ {
+ uint RGBABits = stream.GetUShortValue();
+ int r = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.RBitMask, RGBABits) << 3;
+ int g = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.GBitMask, RGBABits) << 3;
+ int b = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.BBitMask, RGBABits) << 3;
+ int a = (sbyte)GetMaskValue(info.DDS_HEADER.ddspf.ABitMask, RGBABits) == 1 ? 255 : 0;
+ bitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
+ }
+
+ }
+ return bitmap;
+ }
+ #endregion
+
+ #region L8 or A8
+ static private Bitmap Uncompress8bits(IStream stream, int w, int h)
+ {
+ Bitmap bitmap = new Bitmap(w, h);
+ for (int y = 0; y < bitmap.Height; y++)
+ {
+ for (int x = 0; x < bitmap.Width; x++)
+ {
+ uint RGBABits = stream.GetByteValue();
+ int r = 0xff;
+ int g = 0xff;
+ int b = 0xff;
+ int a = 0xff;
+ if (info.Format == DDSFormat.r8_unorm)
+ {
+ r = (int)RGBABits;
+ g = (int)RGBABits;
+ b = (int)RGBABits;
+ a = 0xff;
+ }
+ if (info.Format == DDSFormat.a8_unorm)
+ {
+ r = 0xff;
+ g = 0xff;
+ b = 0xff;
+ a = (int)RGBABits;
+ }
+
+ bitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
+ }
+
+ }
+ return bitmap;
+ }
+ #endregion
+
+ private static bool IsAlpha()
+ {
+ if (info.DDS_HEADER.ddspf.flags.Equals(DDPF.DDPF_PAL8A)
+ || info.DDS_HEADER.ddspf.flags.Equals(DDPF.DDPF_ALPHA)
+ || info.DDS_HEADER.ddspf.flags.Equals(DDPF.DDPF_RGBA))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static byte GetMaskValue(uint Mask, uint Bits)
+ {
+
+ BitArray Valuebits = new BitArray(BitConverter.GetBytes(Bits & Mask));
+ BitArray Maskbits = new BitArray(BitConverter.GetBytes(Mask));
+ int t = 0;
+ for (int n = 0; n < Maskbits.Length; n++)
+ {
+ if (Maskbits[n] == true)
+ {
+ bool value = Valuebits[n];
+ Valuebits[n] = false;
+ Valuebits[t++] = value;
+ }
+
+ }
+
+ byte[] bytes = new byte[(Valuebits.Length / 8) + 1];
+ Valuebits.CopyTo(bytes, 0);
+
+ return bytes[0];
+ }
+
+ public static Bitmap Convert(byte[] DDSBytes)
+ {
+
+ info = DDSCooker.DdsToTex(DDSBytes);
+
+ var stream = new MStream(info.Data);
+
+ return GetBitMapFromDDS(info.Format, stream);
+ }
+
+
+ public static Bitmap Convert(IStream stream)
+ {
+ info= DDSCooker.DdsToTex(stream);
+ return GetBitMapFromDDS(info.Format, stream);
+ }
+
+
+
+ public static Bitmap Convert(byte[] DDSBytes, DDSFormat format, int w, int h)
+ {
+ DDPF dwFlags = 0;
+ if (format == DDSFormat.bc1_unorm || format == DDSFormat.bc2_unorm || format == DDSFormat.bc3_unorm)
+ {
+ dwFlags = DDPF.DDPF_FOURCC;
+ }
+ else if (format == DDSFormat.r8_unorm || format == DDSFormat.r16_unorm || format == DDSFormat.r8g8_unorm)
+ {
+ dwFlags = DDPF.DDPF_LUMINANCE;
+ }
+ else if (format == DDSFormat.a8_unorm)
+ {
+ dwFlags = DDPF.DDPF_ALPHA;
+ }
+ else
+ {
+ dwFlags = DDPF.DDPF_ALPHAPIXELS | DDPF.DDPF_RGB;
+ }
+ (uint RBitMask, uint GBitMask, uint BBitMask, uint ABitMask) = DDSCooker.GetMask(format);
+ info = new DDS_Info()
+ {
+ DDS_HEADER = new DDS_HEADER()
+ {
+ width = w,
+ height = h,
+ ddspf = new DDS_PIXELFORMAT()
+ {
+ flags = dwFlags,
+ RGBBitCount = BitsPerPixel(format),
+ RBitMask = RBitMask,
+ GBitMask = GBitMask,
+ BBitMask = BBitMask,
+ ABitMask = ABitMask
+ }
+ },
+ Format = format,
+ Data = DDSBytes
+ };
+
+ var stream = new MStream(info.Data);
+ return GetBitMapFromDDS(format, stream);
+
+ }
+
+ private static Bitmap GetBitMapFromDDS(DDSFormat format, IStream stream)
+ {
+ switch (format)
+ {
+ case DDSFormat.bc1_unorm:
+ case DDSFormat.bc1_unorm_srgb:
+ return UncompressDXT1(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.bc2_unorm:
+ case DDSFormat.bc2_unorm_srgb:
+ return UncompressDXT3(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.bc3_unorm:
+ case DDSFormat.bc3_unorm_srgb:
+ return UncompressDXT5(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.b8g8r8a8_unorm:
+ case DDSFormat.b8g8r8x8_unorm:
+ case DDSFormat.b8g8r8a8_unorm_srgb:
+ case DDSFormat.b8g8r8x8_unorm_srgb:
+ case DDSFormat.r8g8b8a8_unorm:
+ case DDSFormat.r8g8b8a8_unorm_srgb:
+ return Uncompress8_8_8_8(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.r8g8_unorm:
+ return UncompressA8L8(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.r8g8_snorm:
+ return UncompressV8U8(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.r8_unorm:
+ case DDSFormat.a8_unorm:
+ return Uncompress8bits(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.b4g4r4a4_unorm:
+ return UncompressB4G4R4A4(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ case DDSFormat.b5g5r5a1_unorm:
+ return UncompressB5G5R5A1(stream, info.DDS_HEADER.width, info.DDS_HEADER.height);
+
+ default:
+ throw new Exception("Unsupported DDS Format");
+
+
+ }
+ }
+ }
+}
diff --git a/alan wake 2 rmdtoc tool.csproj b/alan wake 2 rmdtoc tool.csproj
index 06fb869..abac08f 100644
--- a/alan wake 2 rmdtoc tool.csproj
+++ b/alan wake 2 rmdtoc tool.csproj
@@ -17,7 +17,7 @@
AnyCPU
true
full
- true
+ false
bin\Debug\
DEBUG;TRACE
prompt
@@ -76,9 +76,21 @@
Component
+
+ UserControl
+
+
+ SearchBox.cs
+
+
+ Form
+
+
+ frmImageViewer.cs
+
Form
@@ -91,12 +103,20 @@
FrmStringTable.cs
+
+
+
+ SearchBox.cs
+
+
+ frmImageViewer.cs
+
FrmMain.cs