public override void Write(Stream destination)
        {
            using (CriTableWriter writer = CriTableWriter.Create(destination, CriTableWriterSettings.AdxSettings))
            {
                string tableName = "AAX";

                switch (Mode)
                {
                case CriAaxArchiveMode.Adx:
                    tableName = "AAX";
                    break;

                case CriAaxArchiveMode.Dsp:
                    tableName = "ADPCM_WII";
                    break;

                case CriAaxArchiveMode.Wav:
                    tableName = "SWLPCM";
                    break;
                }

                writer.WriteStartTable(tableName);
                writer.WriteField("data", typeof(byte[]));
                writer.WriteField("lpflg", typeof(byte));

                foreach (CriAaxEntry entry in entries.OrderBy(entry => entry.Flag))
                {
                    writer.WriteRow(true, entry.FilePath, (byte)entry.Flag);
                }

                writer.WriteEndTable();
            }
        }
Beispiel #2
0
            public CriCpkSection(Stream destination, string signature, bool enableMask)
            {
                this.destination = destination;
                headerPosition   = destination.Position;

                DataStream.WriteCString(destination, signature, 4);
                DataStream.WriteUInt32(destination, 0xFF);
                destination.Seek(8, SeekOrigin.Current);

                writer = CriTableWriter.Create(destination, new CriTableWriterSettings()
                {
                    LeaveOpen         = true,
                    EnableMask        = enableMask,
                    MaskXor           = 25951,
                    MaskXorMultiplier = 16661
                });
            }
        public static void Serialize(Stream destination, Type type, ICollection objects, CriTableWriterSettings settings)
        {
            ArrayList arrayList = null;

            if (objects != null)
            {
                arrayList = new ArrayList(objects);
            }

            CriTableWriter tableWriter = CriTableWriter.Create(destination, settings);

            string tableName = type.Name;
            CriSerializableAttribute serAttribute = type.GetCustomAttribute <CriSerializableAttribute>();

            if (serAttribute != null && !string.IsNullOrEmpty(serAttribute.TableName))
            {
                tableName = serAttribute.TableName;
            }

            tableWriter.WriteStartTable(tableName);

            SortedList <int, PropertyInfo> sortedProperties = new SortedList <int, PropertyInfo>();

            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                // Add the properties in order
                CriIgnoreAttribute ignoreAttribute = propertyInfo.GetCustomAttribute <CriIgnoreAttribute>();
                if (ignoreAttribute != null)
                {
                    continue;
                }

                // Ignore the properties that are not supportable
                if (propertyInfo.PropertyType != typeof(FileInfo) &&
                    propertyInfo.PropertyType != typeof(Stream) &&
                    propertyInfo.PropertyType != typeof(bool) &&
                    !propertyInfo.PropertyType.IsEnum &&
                    !CriField.FieldTypes.Contains(propertyInfo.PropertyType))
                {
                    continue;
                }

                CriFieldAttribute fieldAttribute = propertyInfo.GetCustomAttribute <CriFieldAttribute>();

                int order = ushort.MaxValue;
                if (fieldAttribute != null)
                {
                    order = fieldAttribute.Order;
                }

                while (sortedProperties.ContainsKey(order))
                {
                    order++;
                }

                sortedProperties.Add(order, propertyInfo);
            }

            tableWriter.WriteStartFieldCollection();
            foreach (var keyValuePair in sortedProperties)
            {
                PropertyInfo      propertyInfo   = keyValuePair.Value;
                CriFieldAttribute fieldAttribute = propertyInfo.GetCustomAttribute <CriFieldAttribute>();

                string fieldName    = propertyInfo.Name;
                Type   fieldType    = propertyInfo.PropertyType;
                object defaultValue = null;

                if (fieldType == typeof(FileInfo) || fieldType == typeof(Stream))
                {
                    fieldType = typeof(byte[]);
                }

                else if (fieldType == typeof(bool))
                {
                    fieldType = typeof(byte);
                }

                else if (fieldType.IsEnum)
                {
                    fieldType = Enum.GetUnderlyingType(propertyInfo.PropertyType);
                }

                if (fieldAttribute != null)
                {
                    if (!string.IsNullOrEmpty(fieldAttribute.FieldName))
                    {
                        fieldName = fieldAttribute.FieldName;
                    }
                }

                bool useDefaultValue = false;

                if (arrayList != null && arrayList.Count > 1)
                {
                    useDefaultValue = true;

                    defaultValue = propertyInfo.GetValue(arrayList[0]);

                    for (int i = 1; i < arrayList.Count; i++)
                    {
                        object objectValue = propertyInfo.GetValue(arrayList[i]);
                        if (defaultValue != null)
                        {
                            if (!defaultValue.Equals(objectValue))
                            {
                                useDefaultValue = false;
                                defaultValue    = null;
                                break;
                            }
                        }
                        else if (objectValue != null)
                        {
                            useDefaultValue = false;
                            defaultValue    = null;
                            break;
                        }
                    }
                }

                else if (arrayList == null || (arrayList != null && (arrayList.Count == 0 || (arrayList.Count == 1 && propertyInfo.GetValue(arrayList[0]) is null))))
                {
                    useDefaultValue = true;
                    defaultValue    = null;
                }

                if (defaultValue is bool boolean)
                {
                    defaultValue = (byte)(boolean ? 1 : 0);
                }

                else if (defaultValue is Enum)
                {
                    defaultValue = Convert.ChangeType(defaultValue, fieldType);
                }

                if (useDefaultValue)
                {
                    tableWriter.WriteField(fieldName, fieldType, defaultValue);
                }

                else
                {
                    tableWriter.WriteField(fieldName, fieldType);
                }
            }

            tableWriter.WriteEndFieldCollection();

            // Time for objects.
            if (arrayList != null)
            {
                foreach (object obj in arrayList)
                {
                    tableWriter.WriteStartRow();

                    int index = 0;
                    foreach (PropertyInfo propertyInfo in sortedProperties.Values)
                    {
                        object value        = propertyInfo.GetValue(obj);
                        Type   propertyType = propertyInfo.PropertyType;

                        if (value is bool boolean)
                        {
                            value = (byte)(boolean ? 1 : 0);
                        }

                        else if (value is Enum)
                        {
                            value = Convert.ChangeType(value, Enum.GetUnderlyingType(propertyType));
                        }

                        tableWriter.WriteValue(index, value);
                        index++;
                    }

                    tableWriter.WriteEndRow();
                }
            }

            tableWriter.WriteEndTable();
            tableWriter.Dispose();
        }
Beispiel #4
0
        public override void Write(Stream destination)
        {
            string GetToolVersion()
            {
                AssemblyName assemblyName = Assembly.GetEntryAssembly().GetName();

                return($"{assemblyName.Name}, {assemblyName.Version.ToString()}");
            }

            DataPool vldPool = new DataPool(Align, 2048);

            vldPool.ProgressChanged += OnProgressChanged;

            using (CriCpkSection cpkSection = new CriCpkSection(destination, "CPK ", enableMask))
            {
                cpkSection.Writer.WriteStartTable("CpkHeader");

                cpkSection.Writer.WriteField("UpdateDateTime", typeof(ulong));
                cpkSection.Writer.WriteField("FileSize", typeof(ulong));
                cpkSection.Writer.WriteField("ContentOffset", typeof(ulong));
                cpkSection.Writer.WriteField("ContentSize", typeof(ulong));

                if (mode == CriCpkMode.FileName || mode == CriCpkMode.FileNameAndId)
                {
                    cpkSection.Writer.WriteField("TocOffset", typeof(ulong));
                    cpkSection.Writer.WriteField("TocSize", typeof(ulong));
                    cpkSection.Writer.WriteField("TocCrc", typeof(uint), null);
                    cpkSection.Writer.WriteField("EtocOffset", typeof(ulong));
                    cpkSection.Writer.WriteField("EtocSize", typeof(ulong));
                }

                else
                {
                    cpkSection.Writer.WriteField("TocOffset", typeof(ulong), null);
                    cpkSection.Writer.WriteField("TocSize", typeof(ulong), null);
                    cpkSection.Writer.WriteField("TocCrc", typeof(uint), null);
                    cpkSection.Writer.WriteField("EtocOffset", typeof(ulong), null);
                    cpkSection.Writer.WriteField("EtocSize", typeof(ulong), null);
                }

                if (mode == CriCpkMode.Id || mode == CriCpkMode.FileNameAndId)
                {
                    cpkSection.Writer.WriteField("ItocOffset", typeof(ulong));
                    cpkSection.Writer.WriteField("ItocSize", typeof(ulong));
                    cpkSection.Writer.WriteField("ItocCrc", typeof(uint), null);
                }

                else
                {
                    cpkSection.Writer.WriteField("ItocOffset", typeof(ulong), null);
                    cpkSection.Writer.WriteField("ItocSize", typeof(ulong), null);
                    cpkSection.Writer.WriteField("ItocCrc", typeof(uint), null);
                }

                cpkSection.Writer.WriteField("GtocOffset", typeof(ulong), null);
                cpkSection.Writer.WriteField("GtocSize", typeof(ulong), null);
                cpkSection.Writer.WriteField("GtocCrc", typeof(uint), null);

                cpkSection.Writer.WriteField("EnabledPackedSize", typeof(ulong));
                cpkSection.Writer.WriteField("EnabledDataSize", typeof(ulong));
                cpkSection.Writer.WriteField("TotalDataSize", typeof(ulong), null);

                cpkSection.Writer.WriteField("Tocs", typeof(uint), null);
                cpkSection.Writer.WriteField("Files", typeof(uint));
                cpkSection.Writer.WriteField("Groups", typeof(uint));
                cpkSection.Writer.WriteField("Attrs", typeof(uint));
                cpkSection.Writer.WriteField("TotalFiles", typeof(uint), null);
                cpkSection.Writer.WriteField("Directories", typeof(uint), null);
                cpkSection.Writer.WriteField("Updates", typeof(uint), null);

                cpkSection.Writer.WriteField("Version", typeof(ushort));
                cpkSection.Writer.WriteField("Revision", typeof(ushort));
                cpkSection.Writer.WriteField("Align", typeof(ushort));
                cpkSection.Writer.WriteField("Sorted", typeof(ushort));
                cpkSection.Writer.WriteField("EID", typeof(ushort), null);

                cpkSection.Writer.WriteField("CpkMode", typeof(uint));
                cpkSection.Writer.WriteField("Tvers", typeof(string));

                if (!string.IsNullOrEmpty(Comment))
                {
                    cpkSection.Writer.WriteField("Comment", typeof(string));
                }

                else
                {
                    cpkSection.Writer.WriteField("Comment", typeof(string), null);
                }

                cpkSection.Writer.WriteField("Codec", typeof(uint));
                cpkSection.Writer.WriteField("DpkItoc", typeof(uint));

                MemoryStream tocMemoryStream  = null;
                MemoryStream itocMemoryStream = null;
                MemoryStream etocMemoryStream = null;

                if (mode == CriCpkMode.FileName || mode == CriCpkMode.FileNameAndId)
                {
                    tocMemoryStream  = new MemoryStream();
                    etocMemoryStream = new MemoryStream();

                    var orderedEntries = entries.OrderBy(entry => entry.Name).ToList();

                    using (CriCpkSection tocSection = new CriCpkSection(tocMemoryStream, "TOC ", enableMask))
                        using (CriCpkSection etocSection = new CriCpkSection(etocMemoryStream, "ETOC", enableMask))
                        {
                            tocSection.Writer.WriteStartTable("CpkTocInfo");

                            tocSection.Writer.WriteField("DirName", typeof(string));
                            tocSection.Writer.WriteField("FileName", typeof(string));
                            tocSection.Writer.WriteField("FileSize", typeof(uint));
                            tocSection.Writer.WriteField("ExtractSize", typeof(uint));
                            tocSection.Writer.WriteField("FileOffset", typeof(ulong));
                            tocSection.Writer.WriteField("ID", typeof(uint));
                            tocSection.Writer.WriteField("UserString", typeof(string));

                            etocSection.Writer.WriteStartTable("CpkEtocInfo");

                            etocSection.Writer.WriteField("UpdateDateTime", typeof(ulong));
                            etocSection.Writer.WriteField("LocalDir", typeof(string));

                            foreach (CriCpkEntry entry in orderedEntries)
                            {
                                tocSection.Writer.WriteRow(true,
                                                           (entry.DirectoryName).Replace('\\', '/'),
                                                           entry.Name,
                                                           (uint)entry.Length,
                                                           (uint)entry.Length,
                                                           (ulong)(vldPool.Length - 2048),
                                                           entry.Id,
                                                           entry.Comment);

                                etocSection.Writer.WriteRow(true,
                                                            CpkDateTimeFromDateTime(entry.UpdateDateTime),
                                                            entry.DirectoryName);

                                vldPool.Put(entry.FilePath);
                            }

                            tocSection.Writer.WriteEndTable();
                            etocSection.Writer.WriteEndTable();
                        }

                    if (mode == CriCpkMode.FileNameAndId)
                    {
                        itocMemoryStream = new MemoryStream();

                        using (CriCpkSection itocSection = new CriCpkSection(itocMemoryStream, "ITOC", enableMask))
                        {
                            itocSection.Writer.WriteStartTable("CpkExtendId");

                            itocSection.Writer.WriteField("ID", typeof(int));
                            itocSection.Writer.WriteField("TocIndex", typeof(int));

                            foreach (CriCpkEntry entry in orderedEntries)
                            {
                                itocSection.Writer.WriteRow(true,
                                                            (int)entry.Id,
                                                            orderedEntries.IndexOf(entry));
                            }

                            itocSection.Writer.WriteEndTable();
                        }
                    }
                }

                else if (mode == CriCpkMode.Id)
                {
                    itocMemoryStream = new MemoryStream();

                    using (CriCpkSection itocSection = new CriCpkSection(itocMemoryStream, "ITOC", enableMask))
                    {
                        itocSection.Writer.WriteStartTable("CpkItocInfo");

                        itocSection.Writer.WriteField("FilesL", typeof(uint));
                        itocSection.Writer.WriteField("FilesH", typeof(uint));
                        itocSection.Writer.WriteField("DataL", typeof(byte[]));
                        itocSection.Writer.WriteField("DataH", typeof(byte[]));

                        List <CriCpkEntry> filesL = entries.Where(entry => entry.Length < ushort.MaxValue).ToList();
                        List <CriCpkEntry> filesH = entries.Where(entry => entry.Length > ushort.MaxValue).ToList();

                        itocSection.Writer.WriteStartRow();

                        using (MemoryStream dataMemoryStream = new MemoryStream())
                            using (CriTableWriter dataWriter = CriTableWriter.Create(dataMemoryStream))
                            {
                                dataWriter.WriteStartTable("CpkItocL");

                                dataWriter.WriteField("ID", typeof(ushort));
                                dataWriter.WriteField("FileSize", typeof(ushort));
                                dataWriter.WriteField("ExtractSize", typeof(ushort));

                                foreach (CriCpkEntry entry in filesL)
                                {
                                    dataWriter.WriteRow(true,
                                                        (ushort)entry.Id,
                                                        (ushort)entry.Length,
                                                        (ushort)entry.Length);
                                }

                                dataWriter.WriteEndTable();

                                itocSection.Writer.WriteValue("DataL", dataMemoryStream.ToArray());
                            }

                        using (MemoryStream dataMemoryStream = new MemoryStream())
                            using (CriTableWriter dataWriter = CriTableWriter.Create(dataMemoryStream))
                            {
                                dataWriter.WriteStartTable("CpkItocH");

                                dataWriter.WriteField("ID", typeof(ushort));
                                dataWriter.WriteField("FileSize", typeof(uint));
                                dataWriter.WriteField("ExtractSize", typeof(uint));

                                foreach (CriCpkEntry entry in filesH)
                                {
                                    dataWriter.WriteRow(true,
                                                        (ushort)entry.Id,
                                                        (uint)entry.Length,
                                                        (uint)entry.Length);
                                }

                                dataWriter.WriteEndTable();

                                itocSection.Writer.WriteValue("DataH", dataMemoryStream.ToArray());
                            }

                        itocSection.Writer.WriteValue("FilesL", (uint)filesL.Count);
                        itocSection.Writer.WriteValue("FilesH", (uint)filesH.Count);
                        itocSection.Writer.WriteEndRow();
                        itocSection.Writer.WriteEndTable();
                    }

                    foreach (CriCpkEntry entry in entries.OrderBy(entry => entry.Id))
                    {
                        vldPool.Put(entry.FilePath);
                    }
                }

                else
                {
                    throw new NotImplementedException($"Unimplemented CPK mode ({mode})");
                }

                cpkSection.Writer.WriteStartRow();
                cpkSection.Writer.WriteValue("UpdateDateTime", CpkDateTimeFromDateTime(DateTime.Now));

                cpkSection.Writer.WriteValue("ContentOffset", (ulong)2048);
                cpkSection.Writer.WriteValue("ContentSize", (ulong)(vldPool.Length - 2048));

                if (tocMemoryStream != null)
                {
                    cpkSection.Writer.WriteValue("TocOffset", (ulong)vldPool.Put(tocMemoryStream));
                    cpkSection.Writer.WriteValue("TocSize", (ulong)tocMemoryStream.Length);
                }

                if (itocMemoryStream != null)
                {
                    cpkSection.Writer.WriteValue("ItocOffset", (ulong)vldPool.Put(itocMemoryStream));
                    cpkSection.Writer.WriteValue("ItocSize", (ulong)itocMemoryStream.Length);
                }

                if (etocMemoryStream != null)
                {
                    cpkSection.Writer.WriteValue("EtocOffset", (ulong)vldPool.Put(etocMemoryStream));
                    cpkSection.Writer.WriteValue("EtocSize", (ulong)etocMemoryStream.Length);
                }

                long totalDataSize = 0;
                foreach (CriCpkEntry entry in entries)
                {
                    totalDataSize += entry.Length;
                }

                cpkSection.Writer.WriteValue("EnabledPackedSize", totalDataSize);
                cpkSection.Writer.WriteValue("EnabledDataSize", totalDataSize);

                cpkSection.Writer.WriteValue("Files", (uint)entries.Count);

                cpkSection.Writer.WriteValue("Version", (ushort)7);
                cpkSection.Writer.WriteValue("Revision", (ushort)2);
                cpkSection.Writer.WriteValue("Align", Align);
                cpkSection.Writer.WriteValue("Sorted", (ushort)1);

                cpkSection.Writer.WriteValue("CpkMode", (uint)mode);
                cpkSection.Writer.WriteValue("Tvers", GetToolVersion());
                cpkSection.Writer.WriteValue("Comment", Comment);

                cpkSection.Writer.WriteValue("FileSize", (ulong)vldPool.Length);

                cpkSection.Writer.WriteEndRow();
                cpkSection.Writer.WriteEndTable();
            }

            DataStream.Pad(destination, 2042);
            DataStream.WriteCString(destination, "(c)CRI", 6);

            vldPool.Write(destination);
        }