private ulong GetContentSize() { ulong size = 0; ushort align = CPK_Header.GetValue <ushort>("Align", TypeFlag.UInt16, 0); foreach (var entry in Entries) { size += (ulong)entry.Data?.Length; //byte alignment if ((size % align) != 0) { size += (align - (size % align)); } } return(size); }
public byte[] Write() { PadWithNullEntries(); ushort align = CPK_Header.GetValue <ushort>("Align", TypeFlag.UInt16, 0); List <byte> bytes = new List <byte>(); List <byte> contentBytes = new List <byte>(); //Update header ulong contentOffset = 0x800; ulong contentSize = GetContentSize(); CPK_Header.SetValue("Files", (uint)Entries.Count, TypeFlag.UInt32, 0); CPK_Header.SetValue("ContentOffset", contentOffset, TypeFlag.UInt64, 0); CPK_Header.SetValue("ContentSize", contentSize, TypeFlag.UInt64, 0); CPK_Header.SetValue("ItocOffset", contentOffset + contentSize, TypeFlag.UInt64, 0); //ITOC int numH = 0; int numL = 0; //Create DataL/DataH tables UTF_File dataH = new UTF_File("CpkItocH"); UTF_File dataL = new UTF_File("CpkItocL"); dataL.Columns.Add(new UTF_Column("ID", TypeFlag.UInt16, StorageFlag.PerRow)); dataL.Columns.Add(new UTF_Column("FileSize", TypeFlag.UInt16, StorageFlag.PerRow)); dataL.Columns.Add(new UTF_Column("ExtractSize", TypeFlag.UInt16, StorageFlag.PerRow)); dataH.Columns.Add(new UTF_Column("ID", TypeFlag.UInt16, StorageFlag.PerRow)); dataH.Columns.Add(new UTF_Column("FileSize", TypeFlag.UInt32, StorageFlag.PerRow)); dataH.Columns.Add(new UTF_Column("ExtractSize", TypeFlag.UInt32, StorageFlag.PerRow)); foreach (var entry in Entries) { if (entry.Data.Length > ushort.MaxValue) { dataH.AddValue("FileSize", TypeFlag.UInt32, numH, entry.Data.Length.ToString()); dataH.AddValue("ExtractSize", TypeFlag.UInt32, numH, entry.Data.Length.ToString()); dataH.AddValue("ID", TypeFlag.UInt16, numH, entry.ID.ToString()); numH++; } else { dataL.AddValue("FileSize", TypeFlag.UInt16, numL, entry.Data.Length.ToString()); dataL.AddValue("ExtractSize", TypeFlag.UInt16, numL, entry.Data.Length.ToString()); dataL.AddValue("ID", TypeFlag.UInt16, numL, entry.ID.ToString()); numL++; } //Write data if (entry.Data.Length > 0) { contentBytes.AddRange(entry.Data); if ((contentBytes.Count % align) != 0) { contentBytes.AddRange(new byte[(align - (contentBytes.Count % align))]); } } } //Create ITOC table ITOC = new UTF_File(); ITOC.TableName = "CpkItocInfo"; ITOC.Columns.Add(new UTF_Column("FilesL", TypeFlag.UInt32, StorageFlag.PerRow)); ITOC.Columns.Add(new UTF_Column("FilesH", TypeFlag.UInt32, StorageFlag.PerRow)); ITOC.Columns.Add(new UTF_Column("DataL", TypeFlag.Data, StorageFlag.PerRow)); ITOC.Columns.Add(new UTF_Column("DataH", TypeFlag.Data, StorageFlag.PerRow)); ITOC.AddValue("FilesL", TypeFlag.UInt32, 0, numL.ToString()); ITOC.AddValue("FilesH", TypeFlag.UInt32, 0, numH.ToString()); ITOC.AddData("DataL", 0, dataL.Write()); ITOC.AddData("DataH", 0, dataH.Write()); //Create file byte[] itocBytes = ITOC.Write(); CPK_Header.SetValue("ItocSize", itocBytes.Length, TypeFlag.UInt64, 0); byte[] headerBytes = CPK_Header.Write(); bytes.AddRange(BitConverter.GetBytes(CPK_SIGNATURE)); bytes.AddRange(BitConverter.GetBytes(CPK_Unk1)); bytes.AddRange(BitConverter.GetBytes((ulong)headerBytes.Length)); bytes.AddRange(headerBytes); bytes.AddRange(new byte[2040 - bytes.Count]); bytes.AddRange(BitConverter.GetBytes((ulong)CRI_SIGNATURE)); if (bytes.Count != 0x800) { throw new InvalidDataException("CPK header is wrong size."); } bytes.AddRange(contentBytes); bytes.AddRange(BitConverter.GetBytes(ITOC_SIGNATURE)); bytes.AddRange(BitConverter.GetBytes(ITOC_Unk1)); bytes.AddRange(BitConverter.GetBytes((ulong)itocBytes.Length)); bytes.AddRange(itocBytes); return(bytes.ToArray()); }