private static void SerializeField(Field field, XmlWriter xw) { string def = $"{field.DisplayType} {field.InternalName}"; if (ParamUtil.IsBitType(field.DisplayType) && field.BitSize != -1) { def += $":{field.BitSize}"; } else if (ParamUtil.IsArrayType(field.DisplayType)) { def += $"[{field.ArrayLength}]"; } if (field.Default != 0) { def += $" = {field.Default.ToString("R", CultureInfo.InvariantCulture)}"; } xw.WriteAttributeString("Def", def); xw.WriteDefaultElement("DisplayName", field.DisplayName, field.InternalName); xw.WriteDefaultElement("Enum", field.InternalType, field.DisplayType.ToString()); xw.WriteDefaultElement("Description", field.Description, null); xw.WriteDefaultElement("DisplayFormat", field.DisplayFormat, ParamUtil.GetDefaultFormat(field.DisplayType)); xw.WriteDefaultElement("EditFlags", field.EditFlags.ToString(), ParamUtil.GetDefaultEditFlags(field.DisplayType).ToString()); xw.WriteDefaultElement("Minimum", field.Minimum, ParamUtil.GetDefaultMinimum(field.DisplayType), "R", CultureInfo.InvariantCulture); xw.WriteDefaultElement("Maximum", field.Maximum, ParamUtil.GetDefaultMaximum(field.DisplayType), "R", CultureInfo.InvariantCulture); xw.WriteDefaultElement("Increment", field.Increment, ParamUtil.GetDefaultIncrement(field.DisplayType), "R", CultureInfo.InvariantCulture); xw.WriteDefaultElement("SortID", field.SortID, 0); xw.WriteDefaultElement("UnkB8", field.UnkB8, null); xw.WriteDefaultElement("UnkC0", field.UnkC0, null); xw.WriteDefaultElement("UnkC8", field.UnkC8, null); }
internal void XmlSerialize(XmlWriter xw) { string def = $"{DisplayType} {InternalName}"; if (ParamUtil.IsBitType(DisplayType) && BitSize != -1) { def += $":{BitSize}"; } else if (ParamUtil.IsArrayType(DisplayType)) { def += $"[{ArrayLength}]"; } if (Default != 0) { def += $" = {Default.ToString("R", CultureInfo.InvariantCulture)}"; } xw.WriteAttributeString("Def", def); xw.WriteDefaultElement(nameof(DisplayName), DisplayName, InternalName); xw.WriteDefaultElement("Enum", InternalType, DisplayType.ToString()); xw.WriteDefaultElement(nameof(Description), Description, null); xw.WriteDefaultElement(nameof(DisplayFormat), DisplayFormat, ParamUtil.GetDefaultFormat(DisplayType)); xw.WriteDefaultElement(nameof(EditFlags), EditFlags.ToString(), ParamUtil.GetDefaultEditFlags(DisplayType).ToString()); xw.WriteDefaultElement(nameof(Minimum), Minimum, ParamUtil.GetDefaultMinimum(DisplayType), "R", CultureInfo.InvariantCulture); xw.WriteDefaultElement(nameof(Maximum), Maximum, ParamUtil.GetDefaultMaximum(DisplayType), "R", CultureInfo.InvariantCulture); xw.WriteDefaultElement(nameof(Increment), Increment, ParamUtil.GetDefaultIncrement(DisplayType), "R", CultureInfo.InvariantCulture); xw.WriteDefaultElement(nameof(SortID), SortID, 0); }
/// <summary> /// Returns a string representation of the field. /// </summary> public override string ToString() { if (ParamUtil.IsBitType(DisplayType) && BitSize != -1) { return($"{DisplayType} {InternalName}:{BitSize}"); } else if (ParamUtil.IsArrayType(DisplayType)) { return($"{DisplayType} {InternalName}[{ArrayLength}]"); } else { return($"{DisplayType} {InternalName}"); } }
private static Field DeserializeField(XmlNode node) { var field = new Field(); string def = node.Attributes["Def"].InnerText; Match outerMatch = defOuterRx.Match(def); field.DisplayType = (DefType)Enum.Parse(typeof(DefType), outerMatch.Groups["type"].Value.Trim()); if (outerMatch.Groups["default"].Success) { field.Default = float.Parse(outerMatch.Groups["default"].Value, CultureInfo.InvariantCulture); } string internalName = outerMatch.Groups["name"].Value.Trim(); Match bitMatch = defBitRx.Match(internalName); Match arrayMatch = defArrayRx.Match(internalName); field.BitSize = -1; field.ArrayLength = 1; if (ParamUtil.IsBitType(field.DisplayType) && bitMatch.Success) { field.BitSize = int.Parse(bitMatch.Groups["size"].Value); internalName = bitMatch.Groups["name"].Value; } else if (ParamUtil.IsArrayType(field.DisplayType)) { field.ArrayLength = int.Parse(arrayMatch.Groups["length"].Value); internalName = arrayMatch.Groups["name"].Value; } field.InternalName = internalName; field.DisplayName = node.ReadStringOrDefault("DisplayName", field.InternalName); field.InternalType = node.ReadStringOrDefault("Enum", field.DisplayType.ToString()); field.Description = node.ReadStringIfExist("Description"); field.DisplayFormat = node.ReadStringOrDefault("DisplayFormat", ParamUtil.GetDefaultFormat(field.DisplayType)); field.EditFlags = (EditFlags)Enum.Parse(typeof(EditFlags), node.ReadStringOrDefault("EditFlags", ParamUtil.GetDefaultEditFlags(field.DisplayType).ToString())); field.Minimum = node.ReadSingleOrDefault("Minimum", ParamUtil.GetDefaultMinimum(field.DisplayType), CultureInfo.InvariantCulture); field.Maximum = node.ReadSingleOrDefault("Maximum", ParamUtil.GetDefaultMaximum(field.DisplayType), CultureInfo.InvariantCulture); field.Increment = node.ReadSingleOrDefault("Increment", ParamUtil.GetDefaultIncrement(field.DisplayType), CultureInfo.InvariantCulture); field.SortID = node.ReadInt32OrDefault("SortID", 0); field.UnkB8 = node.ReadStringIfExist("UnkB8"); field.UnkC0 = node.ReadStringIfExist("UnkC0"); field.UnkC8 = node.ReadStringIfExist("UnkC8"); return(field); }
internal Field(XmlNode node) { string def = node.Attributes["Def"].InnerText; Match outerMatch = defOuterRx.Match(def); DisplayType = (DefType)Enum.Parse(typeof(DefType), outerMatch.Groups["type"].Value.Trim()); if (outerMatch.Groups["default"].Success) { Default = float.Parse(outerMatch.Groups["default"].Value, CultureInfo.InvariantCulture); } string internalName = outerMatch.Groups["name"].Value.Trim(); Match bitMatch = defBitRx.Match(internalName); Match arrayMatch = defArrayRx.Match(internalName); BitSize = -1; ArrayLength = 1; if (ParamUtil.IsBitType(DisplayType) && bitMatch.Success) { BitSize = int.Parse(bitMatch.Groups["size"].Value); internalName = bitMatch.Groups["name"].Value; } else if (ParamUtil.IsArrayType(DisplayType)) { ArrayLength = int.Parse(arrayMatch.Groups["length"].Value); internalName = arrayMatch.Groups["name"].Value; } InternalName = internalName; DisplayName = node.ReadStringOrDefault(nameof(DisplayName), InternalName); InternalType = node.ReadStringOrDefault("Enum", DisplayType.ToString()); Description = node.ReadStringOrDefault(nameof(Description), null); DisplayFormat = node.ReadStringOrDefault(nameof(DisplayFormat), ParamUtil.GetDefaultFormat(DisplayType)); EditFlags = (EditFlags)Enum.Parse(typeof(EditFlags), node.ReadStringOrDefault(nameof(EditFlags), ParamUtil.GetDefaultEditFlags(DisplayType).ToString())); Minimum = node.ReadSingleOrDefault(nameof(Minimum), ParamUtil.GetDefaultMinimum(DisplayType), CultureInfo.InvariantCulture); Maximum = node.ReadSingleOrDefault(nameof(Maximum), ParamUtil.GetDefaultMaximum(DisplayType), CultureInfo.InvariantCulture); Increment = node.ReadSingleOrDefault(nameof(Increment), ParamUtil.GetDefaultIncrement(DisplayType), CultureInfo.InvariantCulture); SortID = node.ReadInt32OrDefault(nameof(SortID), 0); }
/// <summary> /// Calculates the size of cell data for each row. /// </summary> public int GetRowSize() { int size = 0; for (int i = 0; i < Fields.Count; i++) { Field field = Fields[i]; DefType type = field.DisplayType; if (ParamUtil.IsArrayType(type)) { size += ParamUtil.GetValueSize(type) * field.ArrayLength; } else { size += ParamUtil.GetValueSize(type); } if (ParamUtil.IsBitType(type) && field.BitSize != -1) { int bitOffset = field.BitSize; DefType bitType = type == DefType.dummy8 ? DefType.u8 : type; int bitLimit = ParamUtil.GetBitLimit(bitType); for (; i < Fields.Count - 1; i++) { Field nextField = Fields[i + 1]; DefType nextType = nextField.DisplayType; if (!ParamUtil.IsBitType(nextType) || nextField.BitSize == -1 || bitOffset + nextField.BitSize > bitLimit || (nextType == DefType.dummy8 ? DefType.u8 : nextType) != bitType) { break; } bitOffset += nextField.BitSize; } } } return(size); }
internal void WriteCells(BinaryWriterEx bw, byte format2D, int index) { if ((format2D & 0x7F) < 4) { bw.FillUInt32($"RowOffset{index}", (uint)bw.Position); } else { bw.FillInt64($"RowOffset{index}", bw.Position); } int bitOffset = -1; PARAMDEF.DefType bitType = PARAMDEF.DefType.u8; uint bitValue = 0; for (int i = 0; i < Cells.Count; i++) { Cell cell = Cells[i]; object value = cell.Value; PARAMDEF.Field field = cell.Def; PARAMDEF.DefType type = field.DisplayType; if (type == PARAMDEF.DefType.s8) { bw.WriteSByte((sbyte)value); } else if (type == PARAMDEF.DefType.s16) { bw.WriteInt16((short)value); } else if (type == PARAMDEF.DefType.s32) { bw.WriteInt32((int)value); } else if (type == PARAMDEF.DefType.f32) { bw.WriteSingle((float)value); } else if (type == PARAMDEF.DefType.fixstr) { bw.WriteFixStr((string)value, field.ArrayLength); } else if (type == PARAMDEF.DefType.fixstrW) { bw.WriteFixStrW((string)value, field.ArrayLength * 2); } else if (ParamUtil.IsBitType(type)) { if (field.BitSize == -1) { if (type == PARAMDEF.DefType.u8) { bw.WriteByte((byte)value); } else if (type == PARAMDEF.DefType.u16) { bw.WriteUInt16((ushort)value); } else if (type == PARAMDEF.DefType.u32) { bw.WriteUInt32((uint)value); } else if (type == PARAMDEF.DefType.dummy8) { bw.WriteBytes((byte[])value); } } else { if (bitOffset == -1) { bitOffset = 0; bitType = type == PARAMDEF.DefType.dummy8 ? PARAMDEF.DefType.u8 : type; bitValue = 0; } uint shifted = 0; if (bitType == PARAMDEF.DefType.u8) { shifted = (byte)value; } else if (bitType == PARAMDEF.DefType.u16) { shifted = (ushort)value; } else if (bitType == PARAMDEF.DefType.u32) { shifted = (uint)value; } // Shift left first to clear any out-of-range bits shifted = shifted << (32 - field.BitSize) >> (32 - field.BitSize - bitOffset); bitValue |= shifted; bitOffset += field.BitSize; bool write = false; if (i == Cells.Count - 1) { write = true; } else { PARAMDEF.Field nextField = Cells[i + 1].Def; PARAMDEF.DefType nextType = nextField.DisplayType; int bitLimit = ParamUtil.GetBitLimit(bitType); if (!ParamUtil.IsBitType(nextType) || nextField.BitSize == -1 || bitOffset + nextField.BitSize > bitLimit || (nextType == PARAMDEF.DefType.dummy8 ? PARAMDEF.DefType.u8 : nextType) != bitType) { write = true; } } if (write) { bitOffset = -1; if (bitType == PARAMDEF.DefType.u8) { bw.WriteByte((byte)bitValue); } else if (bitType == PARAMDEF.DefType.u16) { bw.WriteUInt16((ushort)bitValue); } else if (bitType == PARAMDEF.DefType.u32) { bw.WriteUInt32(bitValue); } } } } else { throw new NotImplementedException($"Unsupported field type: {type}"); } } }
internal void ReadCells(BinaryReaderEx br, PARAMDEF paramdef) { // In case someone decides to add new rows before applying the paramdef (please don't do that) if (DataOffset == 0) { return; } Def = paramdef; br.Position = DataOffset; var cells = new Cell[paramdef.Fields.Count]; int bitOffset = -1; PARAMDEF.DefType bitType = PARAMDEF.DefType.u8; uint bitValue = 0; for (int i = 0; i < paramdef.Fields.Count; i++) { PARAMDEF.Field field = paramdef.Fields[i]; object value = null; PARAMDEF.DefType type = field.DisplayType; if (type == PARAMDEF.DefType.s8) { value = br.ReadSByte(); } else if (type == PARAMDEF.DefType.s16) { value = br.ReadInt16(); } else if (type == PARAMDEF.DefType.s32) { value = br.ReadInt32(); } else if (type == PARAMDEF.DefType.f32) { value = br.ReadSingle(); } else if (type == PARAMDEF.DefType.fixstr) { value = br.ReadFixStr(field.ArrayLength); } else if (type == PARAMDEF.DefType.fixstrW) { value = br.ReadFixStrW(field.ArrayLength * 2); } else if (ParamUtil.IsBitType(type)) { if (field.BitSize == -1) { if (type == PARAMDEF.DefType.u8) { value = br.ReadByte(); } else if (type == PARAMDEF.DefType.u16) { value = br.ReadUInt16(); } else if (type == PARAMDEF.DefType.u32) { value = br.ReadUInt32(); } else if (type == PARAMDEF.DefType.dummy8) { value = br.ReadBytes(field.ArrayLength); } } } else { throw new NotImplementedException($"Unsupported field type: {type}"); } if (value != null) { bitOffset = -1; } else { PARAMDEF.DefType newBitType = type == PARAMDEF.DefType.dummy8 ? PARAMDEF.DefType.u8 : type; int bitLimit = ParamUtil.GetBitLimit(newBitType); if (field.BitSize == 0) { throw new NotImplementedException($"Bit size 0 is not supported."); } if (field.BitSize > bitLimit) { throw new InvalidDataException($"Bit size {field.BitSize} is too large to fit in type {newBitType}."); } if (bitOffset == -1 || newBitType != bitType || bitOffset + field.BitSize > bitLimit) { bitOffset = 0; bitType = newBitType; if (bitType == PARAMDEF.DefType.u8) { bitValue = br.ReadByte(); } else if (bitType == PARAMDEF.DefType.u16) { bitValue = br.ReadUInt16(); } else if (bitType == PARAMDEF.DefType.u32) { bitValue = br.ReadUInt32(); } } uint shifted = bitValue << (32 - field.BitSize - bitOffset) >> (32 - field.BitSize); bitOffset += field.BitSize; if (bitType == PARAMDEF.DefType.u8) { value = (byte)shifted; } else if (bitType == PARAMDEF.DefType.u16) { value = (ushort)shifted; } else if (bitType == PARAMDEF.DefType.u32) { value = shifted; } } cells[i] = new Cell(field, value); } Cells = cells; }