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(); } }
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(); }
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); }