Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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());
        }