By no means is this a cut and dry unpacker, nor was it meant to be perfectly coded or fast. It was just an experiment to enhance my abilities and to learn more. Hopefully some folks can learn about it here as well.
This was translated from the Python Script over to C# with the addition of unpacking the pack.d04 file.
Using this same structure, doing a "data.hd" and "data.pak" version should be easy. From this, I also believe an updater can be created from as well since it has read functionality, you should be able to do write functionality as well, although I have not experimented with that yet.
Code:
using System; using System.Collections.Generic; using System.IO; using System.IO.MemoryMappedFiles; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace ConsoleApp1 { class Program { public static int count = 0; static void Main(string[] args) { dekaron_unpack(); Console.ReadLine(); } public static void Dekaron_Unpack_2() { string dekaron_path = @"C:\test\"; string header_pack_file_name = dekaron_path + "pack.hdr"; if (!File.Exists(header_pack_file_name)) { Write("Please Check path and make sure pack.hdr is there"); return; } else { Write("pack.hdr file found. Press enter to continue. . ."); Console.ReadLine(); } } public static void dekaron_unpack() { string dekaron_path = @"C:\test\"; string header_pack_file_name = dekaron_path + "pack.hdr"; if (!File.Exists(header_pack_file_name)) { Write("Please Check path and make sure pack.hdr is there"); return; } else { Write("pack.hdr file found. Press enter to continue. . ."); Console.ReadLine(); byte[] pack_file_name; byte[] pack_file_directory_name_array; byte[] pack_file_file_name_array; uint d04fileCount = 0; string pack_chunk_file_name; string pack_file_directory_names = ""; string pack_file_file_name; string pack_chunk_file_file_directory; string pack_file_file_justname; uint pack_file_size, pack_file_file_count = 0; uint pack_file_file_pointer, pack_file_file_size; using (var pack_header_file = File.OpenRead(header_pack_file_name)) { pack_header_file.Seek(400, SeekOrigin.Begin); var pack_file_count = Helper.ReadUInt4Bytes(pack_header_file); Console.WriteLine("There are " + pack_file_count + " Pack files"); for (int i = 0; i < pack_file_count; i++) { GetString(out pack_file_name, pack_header_file, out pack_chunk_file_name); Console.WriteLine(pack_chunk_file_name); { string pack_files = dekaron_path + pack_chunk_file_name; using (var pack_memoryfile = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile(pack_files)) { var pack_file_directory_count = Helper.ReadUInt4Bytes(pack_header_file); if (!pack_chunk_file_name.Contains("d04") && !pack_chunk_file_name.Contains("d0n")) { for (int x = 0; x < pack_file_directory_count; x++) { GetString(out pack_file_directory_name_array, pack_header_file, out pack_file_directory_names); Console.WriteLine("Directory: ({0}) || Number of Folders: ({1})", pack_file_directory_names, pack_file_directory_count); ReadDirectories(pack_header_file, out pack_file_size, out pack_file_file_count); Console.WriteLine("Pack file: {0}, {1} bytes", pack_chunk_file_name, Convert.ToString(pack_file_size)); } for (int j = 0; j < pack_file_file_count; j++) { GetString(out pack_file_file_name_array, pack_header_file, out pack_file_file_name); ReadFiles(pack_header_file, out pack_file_file_pointer, out pack_file_file_size); Console.WriteLine("{0} (Size: {1}) (Position: :{2})", pack_file_file_name, pack_file_file_size, pack_header_file.Position); count++; pack_chunk_file_file_directory = Path.GetDirectoryName(pack_file_file_name); pack_file_file_justname = Path.GetFileName(pack_file_file_name); if (!Directory.Exists(dekaron_path + pack_chunk_file_file_directory)) { Directory.CreateDirectory(dekaron_path + pack_chunk_file_file_directory); var test = pack_memoryfile.CreateViewStream(); test.Seek(pack_file_file_pointer, SeekOrigin.Begin); byte[] buffer = new byte[pack_file_file_size]; test.Read(buffer, 0, (int)pack_file_file_size); ByteArrayToFile(dekaron_path + pack_chunk_file_file_directory + "\\" + pack_file_file_justname, buffer); test.Close(); } else if(Directory.Exists(dekaron_path + pack_chunk_file_file_directory)) { var test = pack_memoryfile.CreateViewStream(); test.Seek(pack_file_file_pointer, SeekOrigin.Begin); byte[] buffer = new byte[pack_file_file_size]; test.Read(buffer, 0, (int)pack_file_file_size); ByteArrayToFile(dekaron_path + pack_chunk_file_file_directory + "\\" + pack_file_file_justname, buffer); test.Close(); } #if DEBUG //Console.ReadKey(); #endif } } if (pack_chunk_file_name.Contains("d04")) { Console.WriteLine("Directory Count: " + pack_file_directory_count); for (int x = 0; x < pack_file_directory_count; x++) { GetString(out pack_file_directory_name_array, pack_header_file, out pack_file_directory_names); Console.WriteLine("Directory: ({0}) FilePosition: ({1})", pack_file_directory_names, pack_header_file.Position); } for (int h = 0; h < pack_file_directory_count; h++) { ReadDirectories(pack_header_file, out pack_file_size, out pack_file_file_count); if (h == 0) { d04fileCount = pack_file_file_count; } if (h == 8) { pack_header_file.Seek(4, SeekOrigin.Current); } } for (int z = 0; z < d04fileCount; z++) { GetString(out pack_file_file_name_array, pack_header_file, out pack_file_file_name); ReadFiles(pack_header_file, out pack_file_file_pointer, out pack_file_file_size); pack_chunk_file_file_directory = Path.GetDirectoryName(pack_file_file_name); pack_file_file_justname = Path.GetFileName(pack_file_file_name); if (!Directory.Exists(dekaron_path + pack_chunk_file_file_directory)) { Directory.CreateDirectory(dekaron_path + pack_chunk_file_file_directory); var test = pack_memoryfile.CreateViewStream(); test.Seek(pack_file_file_pointer, SeekOrigin.Begin); byte[] buffer = new byte[pack_file_file_size]; test.Read(buffer, 0, (int)pack_file_file_size); ByteArrayToFile(dekaron_path + pack_chunk_file_file_directory + "\\" + pack_file_file_justname, buffer); test.Close(); } else if (Directory.Exists(dekaron_path + pack_chunk_file_file_directory)) { var test = pack_memoryfile.CreateViewStream(); test.Seek(pack_file_file_pointer, SeekOrigin.Begin); byte[] buffer = new byte[pack_file_file_size]; test.Read(buffer, 0, (int)pack_file_file_size); ByteArrayToFile(dekaron_path + pack_chunk_file_file_directory + "\\" + pack_file_file_justname, buffer); test.Close(); } Console.WriteLine(pack_file_file_name + " (Size: " + pack_file_file_size.ToString() + ")"); count++; } } if (pack_chunk_file_name.Contains("d0n")) { for (int x = 0; x < pack_file_directory_count; x++) { GetString(out pack_file_directory_name_array, pack_header_file, out pack_file_directory_names); Console.WriteLine("Directory: ({0}) FilePosition: ({1})", pack_file_directory_names, pack_header_file.Position); Console.Write("pack.d0n is not support. Program will now close."); } } } } } } } } public static bool ByteArrayToFile(string fileName, byte[] byteArray) { try { using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { fs.Write(byteArray, 0, byteArray.Length); return true; } } catch (Exception ex) { Console.WriteLine("Exception caught in process: {0}", ex); return false; } } private static void ReadFiles(FileStream pack_header_file, out uint pack_file_file_pointer, out uint pack_file_file_size) { pack_file_file_pointer = Helper.ReadUInt4Bytes(pack_header_file); var pack_file_file_unknown0 = Helper.ReadUInt4Bytes(pack_header_file); pack_file_file_size = Helper.ReadUInt4Bytes(pack_header_file); var pack_file_file_unknown2 = Helper.ReadUInt4Bytes(pack_header_file); var pack_file_file_unknown3 = Helper.ReadUInt4Bytes(pack_header_file); } private static void ReadDirectories(FileStream pack_header_file, out uint pack_file_size, out uint pack_file_file_count) { pack_file_size = Helper.ReadUInt4Bytes(pack_header_file); var pack_file_unknown0 = Helper.ReadUInt4Bytes(pack_header_file); pack_file_file_count = Helper.ReadUInt4Bytes(pack_header_file); var pack_file_unknown1 = Helper.ReadUInt4Bytes(pack_header_file); } private static void GetString(out byte[] InputByteArray, FileStream pack_header_file, out string TheString) { var pack_chunk_file_name_length = Helper.ReadUInt4Bytes(pack_header_file); pack_header_file.Read(InputByteArray = new byte[pack_chunk_file_name_length], 0, (int)pack_chunk_file_name_length); TheString = Encoding.ASCII.GetString(InputByteArray); } public static void Write(string text) { Console.WriteLine(text); } } }