Esempio n. 1
0
        private static void WriteNode(StringBuilder sb, int indent, MetaCont cont, int blockId, int offset, XmlTagMode tagMode = XmlTagMode.None, MetaName structName = 0, string metaName = "")
        {
            var block = cont.Meta.GetBlock(blockId);

            if (block == null)
            {
                ErrorXml(sb, indent, "Couldn't find block " + blockId + "!");
                return;
            }

            if (structName == 0)
            {
                structName = (MetaName)block.StructureNameHash;
            }

            var name = HashString(structName);
            var data = Array.ConvertAll(block.Data.Data.ToArray(), e => (byte)e);

            var structInfo = cont.GetStructureInfo(structName);

            if (structInfo == null)
            {
                ErrorXml(sb, indent, "Couldn't find structure info " + name + "!");
                return;
            }
            if (structInfo.Entries == null)
            {
                ErrorXml(sb, indent, "Couldn't find structure info entries for " + name + "!");
                return;
            }


            switch (tagMode)
            {
            case XmlTagMode.Structure:
                OpenTag(sb, indent, name, true, metaName);
                break;

            case XmlTagMode.Item:
                OpenTag(sb, indent, "Item", true, metaName);
                break;

            case XmlTagMode.ItemAndType:
                OpenTag(sb, indent, "Item type=\"" + name + "\"", true, metaName);
                break;
            }

            var cind = indent + 1;
            StructureEntryInfo arrEntry = new StructureEntryInfo();

            for (int i = 0; i < structInfo.Entries.Count; i++)
            {
                var entry = structInfo.Entries[i];
                if ((MetaName)entry.EntryNameHash == MetaName.ARRAYINFO)
                {
                    arrEntry = entry;
                    continue;
                }
                var ename   = HashString((MetaName)entry.EntryNameHash);
                var eoffset = offset + entry.DataOffset;
                switch (entry.DataType)
                {
                default:
                    ErrorXml(sb, cind, ename + ": Unexpected entry DataType: " + entry.DataType.ToString());
                    break;

                case StructureEntryDataType.Array:

                    WriteArrayNode(sb, cind, cont, data, arrEntry, ename, eoffset);

                    break;

                case StructureEntryDataType.ArrayOfBytes:

                    WriteParsedArrayOfBytesNode(sb, cind, data, ename, eoffset, entry, arrEntry);

                    break;

                case StructureEntryDataType.ArrayOfChars:
                    OpenTag(sb, cind, ename, false);
                    uint charArrLen = (uint)entry.ReferenceKey;
                    for (int n = 0; n < charArrLen; n++)
                    {
                        var bidx = eoffset + n;
                        if ((bidx >= 0) && (bidx < data.Length))
                        {
                            byte b = data[bidx];
                            if (b == 0)
                            {
                                break;
                            }
                            sb.Append((char)b);
                        }
                    }
                    CloseTag(sb, 0, ename);
                    break;

                case StructureEntryDataType.Boolean:
                    var boolVal = BitConverter.ToBoolean(data, eoffset);
                    ValueTag(sb, cind, ename, boolVal?"true":"false");
                    break;

                case StructureEntryDataType.ByteEnum:
                    var byteEnumVal = data[eoffset];
                    ValueTag(sb, cind, ename, byteEnumVal.ToString());
                    break;

                case StructureEntryDataType.CharPointer:
                    var    charPtr = MetaUtils.ConvertData <CharPointer>(data, eoffset);
                    string charStr = MetaUtils.GetString(cont.Meta, charPtr);
                    OneLineTag(sb, cind, ename, charStr);
                    break;

                case StructureEntryDataType.DataBlockPointer:
                    OpenTag(sb, cind, ename);
                    var dataPtr = MetaUtils.ConvertData <DataBlockPointer>(data, eoffset);
                    ErrorXml(sb, cind + 1, "DataBlockPointer not currently supported here!");     //TODO! ymap occludeModels vertices data is this type!
                    CloseTag(sb, cind, ename);
                    break;

                case StructureEntryDataType.Float:
                    var floatVal = BitConverter.ToSingle(data, eoffset);
                    ValueTag(sb, cind, ename, floatVal.ToString(CultureInfo.InvariantCulture));
                    break;

                case StructureEntryDataType.Float_XYZ:
                    var v3 = MetaUtils.ConvertData <Vector3>(data, eoffset);
                    SelfClosingTag(sb, cind, ename + " x=\"" + v3.X.ToString(CultureInfo.InvariantCulture) + "\" y=\"" + v3.Y.ToString(CultureInfo.InvariantCulture) + "\" z=\"" + v3.Z.ToString(CultureInfo.InvariantCulture) + "\"");
                    break;

                case StructureEntryDataType.Float_XYZW:
                    var v4 = MetaUtils.ConvertData <Vector4>(data, eoffset);
                    SelfClosingTag(sb, cind, ename + " x=\"" + v4.X.ToString(CultureInfo.InvariantCulture) + "\" y=\"" + v4.Y.ToString(CultureInfo.InvariantCulture) + "\" z=\"" + v4.Z.ToString(CultureInfo.InvariantCulture) + "\" w=\"" + v4.W.ToString(CultureInfo.InvariantCulture) + "\"");
                    break;

                case StructureEntryDataType.Hash:
                    var hashVal = (MetaName)MetaUtils.ConvertData <uint>(data, eoffset);
                    var hashStr = HashString(hashVal);
                    StringTag(sb, cind, ename, hashStr);
                    break;

                case StructureEntryDataType.IntEnum:
                    var intEnumVal = BitConverter.ToInt32(data, eoffset);
                    var intEnumStr = GetEnumString(cont, entry, intEnumVal);
                    StringTag(sb, cind, ename, intEnumStr);
                    break;

                case StructureEntryDataType.IntFlags1:
                    var intFlags1Val = BitConverter.ToInt32(data, eoffset);
                    var intFlags1Str = GetEnumString(cont, entry, intFlags1Val);
                    StringTag(sb, cind, ename, intFlags1Str);
                    break;

                case StructureEntryDataType.IntFlags2:
                    var intFlags2Val = BitConverter.ToInt32(data, eoffset);
                    var intFlags2Str = GetEnumString(cont, entry, intFlags2Val);
                    StringTag(sb, cind, ename, intFlags2Str);
                    break;

                case StructureEntryDataType.ShortFlags:
                    var shortFlagsVal = BitConverter.ToInt16(data, eoffset);
                    var shortFlagsStr = shortFlagsVal.ToString();     // GetEnumString(cont, entry, shortFlagsVal);
                    StringTag(sb, cind, ename, shortFlagsStr);
                    break;

                case StructureEntryDataType.SignedByte:
                    sbyte sbyteVal = (sbyte)data[eoffset];
                    ValueTag(sb, cind, ename, sbyteVal.ToString());
                    break;

                case StructureEntryDataType.SignedInt:
                    var intVal = BitConverter.ToInt32(data, eoffset);
                    ValueTag(sb, cind, ename, intVal.ToString());
                    break;

                case StructureEntryDataType.SignedShort:
                    var shortVal = BitConverter.ToInt16(data, eoffset);
                    ValueTag(sb, cind, ename, shortVal.ToString());
                    break;

                case StructureEntryDataType.Structure:
                    OpenTag(sb, cind, ename);
                    WriteNode(sb, cind, cont, blockId, eoffset, XmlTagMode.None, (MetaName)entry.ReferenceKey);
                    CloseTag(sb, cind, ename);
                    break;

                case StructureEntryDataType.StructurePointer:
                    OpenTag(sb, cind, ename);
                    ErrorXml(sb, cind + 1, "StructurePointer not supported here! Tell dexy!");
                    CloseTag(sb, cind, ename);
                    break;

                case StructureEntryDataType.UnsignedByte:
                    var byteVal = data[eoffset];
                    ValueTag(sb, cind, ename, byteVal.ToString());
                    //ValueTag(sb, cind, ename, "0x" + byteVal.ToString("X").PadLeft(2, '0'));
                    break;

                case StructureEntryDataType.UnsignedInt:
                    var uintVal = BitConverter.ToUInt32(data, eoffset);
                    switch ((MetaName)entry.EntryNameHash)
                    {
                    default:
                        ValueTag(sb, cind, ename, uintVal.ToString());
                        break;

                    case MetaName.color:
                        ValueTag(sb, cind, ename, "0x" + uintVal.ToString("X").PadLeft(8, '0'));
                        break;
                    }

                    break;

                case StructureEntryDataType.UnsignedShort:
                    var ushortVal = BitConverter.ToUInt16(data, eoffset);
                    ValueTag(sb, cind, ename, ushortVal.ToString());    // "0x" + ushortVal.ToString("X").PadLeft(4, '0'));
                    break;
                }
            }

            switch (tagMode)
            {
            case XmlTagMode.Structure:
                CloseTag(sb, indent, name);
                break;

            case XmlTagMode.Item:
            case XmlTagMode.ItemAndType:
                CloseTag(sb, indent, "Item");
                break;
            }
        }
Esempio n. 2
0
        private static void WriteNode(StringBuilder sb, int indent, PsoCont cont, int blockId, int offset, XmlTagMode tagMode = XmlTagMode.None, MetaName structName = 0)
        {
            var block = cont.Pso.GetBlock(blockId);

            if (block == null)
            {
                ErrorXml(sb, indent, "Couldn't find block " + blockId + "!");
                return;
            }


            var boffset = offset + block.Offset;

            if (structName == 0)
            {
                structName = (MetaName)block.NameHash;
            }

            var name = HashString(structName);
            var data = cont.Pso.DataSection.Data;

            var structInfo = cont.GetStructureInfo(structName);

            if (structInfo == null)
            {
                ErrorXml(sb, indent, "Couldn't find structure info " + name + "!");
                return;
            }
            if (structInfo.Entries == null)
            {
                ErrorXml(sb, indent, "Couldn't find structure info entries for " + name + "!");
                return;
            }

            switch (tagMode)
            {
            case XmlTagMode.Structure:
                OpenTag(sb, indent, name);
                break;

            case XmlTagMode.Item:
                OpenTag(sb, indent, "Item");
                break;

            case XmlTagMode.ItemAndType:
                OpenTag(sb, indent, "Item type=\"" + name + "\"");
                break;
            }


            var cind = indent + 1;

            for (int i = 0; i < structInfo.Entries.Count; i++)
            {
                var entry = structInfo.Entries[i];
                if ((MetaName)entry.EntryNameHash == MetaName.ARRAYINFO)
                {
                    continue;
                }
                var ename   = HashString((MetaName)entry.EntryNameHash);
                var eoffset = boffset + entry.DataOffset;
                switch (entry.Type)
                {
                default:
                    ErrorXml(sb, cind, ename + ": Unexpected entry DataType: " + entry.Type.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.Array:

                    WriteArrayNode(sb, cind, cont, blockId, offset, entry, structInfo, ename);

                    break;

                case RageLib.GTA5.PSO.DataType.Bool:
                    var boolVal = BitConverter.ToBoolean(data, eoffset);
                    ValueTag(sb, cind, ename, boolVal ? "true" : "false");
                    break;

                case RageLib.GTA5.PSO.DataType.SByte:     //was LONG_01h //signed byte?
                    //var long1Val = MetaUtils.SwapBytes(BitConverter.ToUInt64(data, eoffset));
                    //ValueTag(sb, cind, ename, long1Val.ToString());
                    var byte1Val = (sbyte)data[eoffset];
                    ValueTag(sb, cind, ename, byte1Val.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.UByte:
                    var byte2Val = data[eoffset];
                    ValueTag(sb, cind, ename, byte2Val.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.Enum:
                    var enumInfo = cont.GetEnumInfo((MetaName)entry.ReferenceKey);
                    switch (entry.Unk_5h)
                    {
                    default:
                        ErrorXml(sb, cind, ename + ": Unexpected Enum subtype: " + entry.Unk_5h.ToString());
                        break;

                    case 0:         //int enum
                        var intEVal = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset));
                        var intE    = enumInfo.FindEntry(intEVal);
                        StringTag(sb, cind, ename, HashString((MetaName)(intE?.EntryNameHash ?? 0)));
                        break;

                    case 2:         //byte enum
                        var byteEVal = data[eoffset];
                        var byteE    = enumInfo.FindEntry(byteEVal);
                        StringTag(sb, cind, ename, HashString((MetaName)(byteE?.EntryNameHash ?? 0)));
                        break;
                    }
                    break;

                case RageLib.GTA5.PSO.DataType.Flags:
                    uint        fCount    = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF;
                    uint        fEntry    = ((uint)entry.ReferenceKey & 0xFFFF);
                    var         fEnt      = structInfo.GetEntry((int)fEntry);
                    PsoEnumInfo flagsInfo = null;
                    if ((fEnt != null) && ((MetaName)fEnt.EntryNameHash == MetaName.ARRAYINFO))
                    {
                        flagsInfo = cont.GetEnumInfo((MetaName)fEnt.ReferenceKey);
                    }
                    if (flagsInfo == null)
                    {
                        flagsInfo = cont.GetEnumInfo((MetaName)entry.EntryNameHash);
                    }
                    uint?flagsVal = null;
                    switch (entry.Unk_5h)
                    {
                    default:
                        ErrorXml(sb, cind, ename + ": Unexpected Flags subtype: " + entry.Unk_5h.ToString());
                        break;

                    case 0:         //int flags
                        flagsVal = MetaUtils.SwapBytes(BitConverter.ToUInt32(data, eoffset));
                        break;

                    case 1:         //short flags
                        flagsVal = MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset));
                        break;

                    case 2:         //byte flags
                        flagsVal = data[eoffset];
                        break;
                    }
                    if (flagsVal.HasValue)
                    {
                        uint fv = flagsVal.Value;
                        if (flagsInfo != null)
                        {
                            string fstr = "";
                            for (int n = 0; n < flagsInfo.EntriesCount; n++)
                            {
                                var fentry = flagsInfo.Entries[n];
                                var fmask  = (1 << fentry.EntryKey);
                                if ((fv & fmask) > 0)
                                {
                                    if (fstr != "")
                                    {
                                        fstr += " ";
                                    }
                                    fstr += HashString((MetaName)fentry.EntryNameHash);
                                }
                            }
                            StringTag(sb, cind, ename, fstr);
                        }
                        else
                        {
                            if (fv != 0)
                            {
                                ValueTag(sb, cind, ename, fv.ToString());
                            }
                            else
                            {
                                SelfClosingTag(sb, cind, ename);
                            }
                        }
                    }
                    break;

                case RageLib.GTA5.PSO.DataType.Float:
                    var floatVal = MetaUtils.SwapBytes(BitConverter.ToSingle(data, eoffset));
                    ValueTag(sb, cind, ename, FloatUtil.ToString(floatVal));
                    break;

                case RageLib.GTA5.PSO.DataType.Float2:
                    var v2 = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector2>(data, eoffset));
                    SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v2.X) + "\" y=\"" + FloatUtil.ToString(v2.Y) + "\"");
                    break;

                case RageLib.GTA5.PSO.DataType.Float3:
                    var v3 = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector3>(data, eoffset));
                    SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3.X) + "\" y=\"" + FloatUtil.ToString(v3.Y) + "\" z=\"" + FloatUtil.ToString(v3.Z) + "\"");
                    break;

                case RageLib.GTA5.PSO.DataType.Float3a:     //TODO: check this!
                    var v3a = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector3>(data, eoffset));
                    SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3a.X) + "\" y=\"" + FloatUtil.ToString(v3a.Y) + "\" z=\"" + FloatUtil.ToString(v3a.Z) + "\"");
                    break;

                case RageLib.GTA5.PSO.DataType.Float4a:     //TODO: check this! //...why are there 3 different types of float3?
                    var v3b = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector3>(data, eoffset));
                    SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v3b.X) + "\" y=\"" + FloatUtil.ToString(v3b.Y) + "\" z=\"" + FloatUtil.ToString(v3b.Z) + "\"");
                    break;

                case RageLib.GTA5.PSO.DataType.Float4:
                    var v4 = MetaUtils.SwapBytes(MetaUtils.ConvertData <Vector4>(data, eoffset));
                    SelfClosingTag(sb, cind, ename + " x=\"" + FloatUtil.ToString(v4.X) + "\" y=\"" + FloatUtil.ToString(v4.Y) + "\" z=\"" + FloatUtil.ToString(v4.Z) + "\" w=\"" + FloatUtil.ToString(v4.W) + "\"");
                    break;

                case RageLib.GTA5.PSO.DataType.SInt:     //TODO: convert hashes?
                    var int5Val = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset));
                    ValueTag(sb, cind, ename, int5Val.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.UInt:
                    switch (entry.Unk_5h)
                    {
                    default:
                        ErrorXml(sb, cind, ename + ": Unexpected Integer subtype: " + entry.Unk_5h.ToString());
                        break;

                    case 0:         //signed int
                        var int6aVal = MetaUtils.SwapBytes(BitConverter.ToInt32(data, eoffset));
                        ValueTag(sb, cind, ename, int6aVal.ToString());
                        break;

                    case 1:         //unsigned int
                        var int6bVal = MetaUtils.SwapBytes(BitConverter.ToUInt32(data, eoffset));
                        ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0'));
                        break;
                    }
                    break;

                case RageLib.GTA5.PSO.DataType.Long:
                    var long2Val = MetaUtils.SwapBytes(BitConverter.ToUInt64(data, eoffset));
                    ValueTag(sb, cind, ename, long2Val.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.Map:

                    WriteMapNode(sb, indent, cont, eoffset, entry, structInfo, ename);

                    break;

                case RageLib.GTA5.PSO.DataType.SShort:
                    var short3Val = (short)MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset));
                    ValueTag(sb, cind, ename, short3Val.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.UShort:
                    var short4Val = MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset));
                    ValueTag(sb, cind, ename, short4Val.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.HFloat:    //half float?
                    var short1EVal = MetaUtils.SwapBytes(BitConverter.ToUInt16(data, eoffset));
                    ValueTag(sb, cind, ename, short1EVal.ToString());
                    break;

                case RageLib.GTA5.PSO.DataType.String:
                    var str0 = GetStringValue(cont.Pso, entry, data, eoffset);
                    if (str0 == null)
                    {
                        ErrorXml(sb, cind, ename + ": Unexpected String subtype: " + entry.Unk_5h.ToString());
                    }
                    else
                    {
                        StringTag(sb, cind, ename, str0);
                    }
                    break;

                case RageLib.GTA5.PSO.DataType.Structure:
                    switch (entry.Unk_5h)
                    {
                    default:
                        ErrorXml(sb, cind, ename + ": Unexpected Structure subtype: " + entry.Unk_5h.ToString());
                        break;

                    case 0:         //default structure
                        OpenTag(sb, cind, ename);
                        WriteNode(sb, cind, cont, blockId, offset + entry.DataOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey);
                        CloseTag(sb, cind, ename);
                        break;

                    case 3:         //structure pointer...
                    case 4:         //also pointer? what's the difference?
                        var ptrVal = MetaUtils.ConvertData <PsoPOINTER>(data, eoffset);
                        ptrVal.SwapEnd();
                        var  pbid = ptrVal.BlockID;
                        bool pbok = true;
                        if (pbid <= 0)
                        {
                            pbok = false;         //no block specified?
                        }
                        if (pbid > cont.Pso.DataMappingSection.EntriesCount)
                        {
                            pbok = false;         //bad pointer? different type..? should output an error message here?
                        }
                        if (pbok)
                        {
                            WriteNode(sb, cind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey);
                        }
                        else
                        {
                            SelfClosingTag(sb, cind, ename);
                        }
                        break;
                    }
                    break;
                }
            }



            switch (tagMode)
            {
            case XmlTagMode.Structure:
                CloseTag(sb, indent, name);
                break;

            case XmlTagMode.Item:
            case XmlTagMode.ItemAndType:
                CloseTag(sb, indent, "Item");
                break;
            }
        }