コード例 #1
0
            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);
            }
コード例 #2
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);
        }
コード例 #3
0
            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}");
                    }
                }
            }
コード例 #4
0
            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;
            }
コード例 #5
0
            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);
            }
コード例 #6
0
            internal Field(BinaryReaderEx br, PARAMDEF def)
            {
                Parent = def;
                if (def.Unicode)
                {
                    DisplayName = br.ReadFixStrW(0x40);
                }
                else
                {
                    DisplayName = br.ReadFixStr(0x40);
                }

                DisplayType   = (DefType)Enum.Parse(typeof(DefType), br.ReadFixStr(8));
                DisplayFormat = br.ReadFixStr(8);
                Default       = br.ReadSingle();
                Minimum       = br.ReadSingle();
                Maximum       = br.ReadSingle();
                Increment     = br.ReadSingle();
                EditFlags     = (EditFlags)br.ReadInt32();

                int byteCount = br.ReadInt32();

                if (!ParamUtil.IsArrayType(DisplayType) && byteCount != ParamUtil.GetValueSize(DisplayType) ||
                    ParamUtil.IsArrayType(DisplayType) && byteCount % ParamUtil.GetValueSize(DisplayType) != 0)
                {
                    throw new InvalidDataException($"Unexpected byte count {byteCount} for type {DisplayType}.");
                }
                ArrayLength = byteCount / ParamUtil.GetValueSize(DisplayType);

                long descriptionOffset;

                if (def.Version >= 201)
                {
                    descriptionOffset = br.ReadInt64();
                }
                else
                {
                    descriptionOffset = br.ReadInt32();
                }

                InternalType = br.ReadFixStr(0x20);

                BitSize = -1;
                if (def.Version >= 102)
                {
                    // A few fields in DS1 FaceGenParam have a trailing space in the name
                    InternalName = br.ReadFixStr(0x20).Trim();

                    Match match = bitSizeRx.Match(InternalName);
                    if (match.Success)
                    {
                        InternalName = match.Groups["name"].Value;
                        BitSize      = int.Parse(match.Groups["size"].Value);
                    }

                    if (ParamUtil.IsArrayType(DisplayType))
                    {
                        match = arrayLengthRx.Match(InternalName);
                        int length = match.Success ? int.Parse(match.Groups["length"].Value) : 1;
                        if (length != ArrayLength)
                        {
                            throw new InvalidDataException($"Mismatched array length in {InternalName} with byte count {byteCount}.");
                        }
                        if (match.Success)
                        {
                            InternalName = match.Groups["name"].Value;
                        }
                    }
                }

                if (def.Version >= 104)
                {
                    SortID = br.ReadInt32();
                }

                if (def.Version >= 201)
                {
                    br.AssertPattern(0x1C, 0x00);
                }

                if (descriptionOffset != 0)
                {
                    if (def.Unicode)
                    {
                        Description = br.GetUTF16(descriptionOffset);
                    }
                    else
                    {
                        Description = br.GetShiftJIS(descriptionOffset);
                    }
                }
            }
コード例 #7
0
            internal void Write(BinaryWriterEx bw, PARAMDEF def, int index)
            {
                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"DisplayNameOffset{index}");
                }
                else if (def.Unicode)
                {
                    bw.WriteFixStrW(DisplayName, 0x40, (byte)(def.FormatVersion >= 104 ? 0x00 : 0x20));
                }
                else
                {
                    bw.WriteFixStr(DisplayName, 0x40, (byte)(def.FormatVersion >= 104 ? 0x00 : 0x20));
                }

                byte padding = (byte)(def.FormatVersion >= 200 ? 0x00 : 0x20);

                bw.WriteFixStr(DisplayType.ToString(), 8, padding);
                bw.WriteFixStr(DisplayFormat, 8, padding);
                bw.WriteSingle(Default);
                bw.WriteSingle(Minimum);
                bw.WriteSingle(Maximum);
                bw.WriteSingle(Increment);
                bw.WriteInt32((int)EditFlags);
                bw.WriteInt32(ParamUtil.GetValueSize(DisplayType) * (ParamUtil.IsArrayType(DisplayType) ? ArrayLength : 1));

                if (def.FormatVersion >= 200)
                {
                    bw.ReserveInt64($"DescriptionOffset{index}");
                }
                else
                {
                    bw.ReserveInt32($"DescriptionOffset{index}");
                }

                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"InternalTypeOffset{index}");
                }
                else
                {
                    bw.WriteFixStr(InternalType, 0x20, padding);
                }

                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"InternalNameOffset{index}");
                }
                else if (def.FormatVersion >= 102)
                {
                    bw.WriteFixStr(MakeInternalName(), 0x20, padding);
                }

                if (def.FormatVersion >= 104)
                {
                    bw.WriteInt32(SortID);
                }

                if (def.FormatVersion >= 200)
                {
                    bw.WriteInt32(0);
                    bw.ReserveInt64($"UnkB8Offset{index}");
                    bw.ReserveInt64($"UnkC0Offset{index}");
                    bw.ReserveInt64($"UnkC8Offset{index}");
                }
            }