public static Ctpk Read(byte[] data, string inputPath, string outputPath, bool isRawExtract = false) { Ctpk file = new Ctpk(); using (MemoryStream dataStream = new MemoryStream(data)) using (BinaryReader reader = new BinaryReader(dataStream)) { if (reader.ReadUInt32() != Magic) { Console.WriteLine("ERROR: Not a valid CTPK file."); } file.Version = reader.ReadUInt16(); file.NumberOfTextures = reader.ReadUInt16(); file.TextureSectionOffset = reader.ReadUInt32(); file.TextureSectionSize = reader.ReadUInt32(); file.HashSectionOffset = reader.ReadUInt32(); file.TextureInfoSection = reader.ReadUInt32(); // Section 1 + 3 for (int i = 0; i < file.NumberOfTextures; i++) { reader.BaseStream.Seek(0x20 * (i + 1), SeekOrigin.Begin); CTPKEntry entry = CTPKEntry.Read(reader); entry.FileIndexA = file._entries.Count; file._entries.Add(entry); } // Section 2 for (int i = 0; i < file.NumberOfTextures; i++) { file._entries[i].Info = reader.ReadUInt32(); } // Section 4 reader.BaseStream.Seek(file.HashSectionOffset, SeekOrigin.Begin); for (int i = 0; i < file.NumberOfTextures; i++) { file._entries[i].FilenameHash = reader.ReadUInt32(); int idx = reader.ReadInt32(); if (idx < file._entries.Count) { file._entries[idx].FileIndexB = i; } else { Console.WriteLine("ERROR(?): Found hash entry without a matching file entry"); } } // Section 5 reader.BaseStream.Seek(file.TextureInfoSection, SeekOrigin.Begin); for (int i = 0; i < file.NumberOfTextures; i++) { file._entries[i].Info2 = reader.ReadUInt32(); } // Section 6 for (int i = 0; i < file.NumberOfTextures; i++) { reader.BaseStream.Seek(file.TextureSectionOffset + file._entries[i].TextureOffset, SeekOrigin.Begin); file._entries[i].TextureRawData = new byte[file._entries[i].TextureSize]; reader.Read(file._entries[i].TextureRawData, 0, (int)file._entries[i].TextureSize); } for (int i = 0; i < file.NumberOfTextures; i++) { Console.WriteLine("Converting {0}...", file._entries[i].InternalFilePath); file._entries[i].ToFile(outputPath, isRawExtract); } } return(file); }
public static Ctpk Read(byte[] data, string filename) { Ctpk file = new Ctpk(); using (MemoryStream dataStream = new MemoryStream(data)) using (BinaryReader reader = new BinaryReader(dataStream)) { if (reader.ReadUInt32() != Magic) { Console.WriteLine("ERROR: Not a valid CTPK file."); } file.Version = reader.ReadUInt16(); file.NumberOfTextures = reader.ReadUInt16(); file.TextureSectionOffset = reader.ReadUInt32(); file.TextureSectionSize = reader.ReadUInt32(); file.HashSectionOffset = reader.ReadUInt32(); file.TextureInfoSection = reader.ReadUInt32(); // Section 1 + 3 for (int i = 0; i < file.NumberOfTextures; i++) { reader.BaseStream.Seek(0x20 * (i + 1), SeekOrigin.Begin); CTPKEntry entry = CTPKEntry.Read(reader); file._entries.Add(entry); } // Section 2 for (int i = 0; i < file.NumberOfTextures; i++) { file._entries[i].Info = reader.ReadUInt32(); } // Section 4 for (int i = 0; i < file.NumberOfTextures; i++) { file._entries[i].FilenameHash = reader.ReadUInt32(); } // Section 5 reader.BaseStream.Seek(file.TextureInfoSection, SeekOrigin.Begin); for (int i = 0; i < file.NumberOfTextures; i++) { file._entries[i].Info2 = reader.ReadUInt32(); } // Section 6 for (int i = 0; i < file.NumberOfTextures; i++) { reader.BaseStream.Seek(file.TextureSectionOffset + file._entries[i].TextureOffset, SeekOrigin.Begin); file._entries[i].TextureRawData = new byte[file._entries[i].TextureSize]; reader.Read(file._entries[i].TextureRawData, 0, (int)file._entries[i].TextureSize); } string basePath = Path.GetDirectoryName(filename); string baseFilename = Path.GetFileNameWithoutExtension(filename); if (!String.IsNullOrWhiteSpace(basePath)) { baseFilename = Path.Combine(basePath, baseFilename); } for (int i = 0; i < file.NumberOfTextures; i++) { Console.WriteLine("Converting {0}...", file._entries[i].InternalFilePath); file._entries[i].ToFile(baseFilename); } } return(file); }