예제 #1
0
        private static string GetStringValue(PsoFile pso, PsoStructureEntryInfo entry, byte[] data, int eoffset)
        {
            switch (entry.Unk_5h)
            {
            default:
                return(null);

            case 0:
                var str0len = (int)((entry.ReferenceKey >> 16) & 0xFFFF);
                return(Encoding.ASCII.GetString(data, eoffset, str0len).Replace("\0", ""));

            case 1:
            case 2:
                var dataPtr2 = MetaUtils.ConvertData <DataBlockPointer>(data, eoffset);
                dataPtr2.SwapEnd();
                return(PsoUtils.GetString(pso, dataPtr2));

            case 3:
                var charPtr3 = MetaUtils.ConvertData <CharPointer>(data, eoffset);
                charPtr3.SwapEnd();
                var strval = PsoUtils.GetString(pso, charPtr3);
                return(strval ?? "");

            case 7:
            case 8:
                MetaName hashVal = (MetaName)MetaUtils.SwapBytes(MetaUtils.ConvertData <uint>(data, eoffset));
                return(HashString(hashVal));
            }
        }
예제 #2
0
        public override void Parse(MetaFile meta, CMapTypes CMapTypes)
        {
            this.Meta          = meta;
            this.MetaStructure = CMapTypes;

            // this.Extensions = CMapTypes.extensions;

            // CBaseArchetypeDef + CMloArchetypeDef + CTimeArchetypeDef
            var archPtrs = MetaUtils.GetPointerArray(this.Meta, this.MetaStructure.archetypes);

            if (archPtrs != null)
            {
                for (int i = 0; i < archPtrs.Length; i++)
                {
                    var ptr   = archPtrs[i];
                    var block = Meta.GetBlock(ptr.BlockID);

                    if (block == null)
                    {
                        continue;
                    }

                    if ((ptr.Offset < 0) || (block.Data == null) || (ptr.Offset >= block.Data.Length))
                    {
                        continue;
                    }

                    byte[] data = Array.ConvertAll(block.Data.ToArray(), e => (byte)e);

                    switch ((MetaName)block.StructureNameHash)
                    {
                    case MetaName.CBaseArchetypeDef:
                    {
                        var struc = PsoUtils.ConvertDataRaw <RageLib.Resources.GTA5.PC.Meta.CBaseArchetypeDef>(data, ptr.Offset);
                        var arch  = new MCBaseArchetypeDef();
                        arch.Parse(meta, struc);
                        this.Archetypes.Add(arch);
                        break;
                    }

                    case MetaName.CMloArchetypeDef:
                    {
                        var struc = PsoUtils.ConvertDataRaw <RageLib.Resources.GTA5.PC.Meta.CMloArchetypeDef>(data, ptr.Offset);
                        var arch  = new MCMloArchetypeDef();
                        arch.Parse(meta, struc);
                        this.MloArchetypes.Add(arch);
                        break;
                    }

                    case MetaName.CTimeArchetypeDef:
                    {
                        var struc = PsoUtils.ConvertDataRaw <RageLib.Resources.GTA5.PC.Meta.CTimeArchetypeDef>(data, ptr.Offset);
                        var arch  = new MCTimeArchetypeDef();
                        arch.Parse(meta, struc);
                        this.TimeArchetypes.Add(arch);
                        break;
                    }

                    default: continue;
                    }
                }
            }

            this.Name = (MetaName)CMapTypes.name;
            // this.Dependencies = CMapTypes.dependencies;
            var compositeEntityTypes = MetaUtils.ConvertDataArray <CCompositeEntityType>(meta, CMapTypes.compositeEntityTypes);

            this.CompositeEntityTypes = compositeEntityTypes?.Select(e => { var msw = new MCCompositeEntityType(); msw.Parse(meta, e); return(msw); }).ToList();
        }
예제 #3
0
        private static void WriteArrayNode(StringBuilder sb, int indent, PsoCont cont, int blockId, int offset, PsoStructureEntryInfo entry, PsoStructureInfo estruct, string ename)
        {
            var    block    = cont.Pso.GetBlock(blockId);
            var    boffset  = offset + block.Offset;
            var    eoffset  = boffset + entry.DataOffset;
            var    aOffset  = offset + entry.DataOffset;
            var    aBlockId = blockId;
            uint   aCount   = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF;
            var    aind     = indent + 1;
            string arrTag   = ename;
            PsoStructureEntryInfo arrEntry = estruct.GetEntry((int)(entry.ReferenceKey & 0xFFFF));

            if (arrEntry == null)
            {
                ErrorXml(sb, indent, "ARRAYINFO not found for " + ename + "!");
                return;
            }

            var data = cont.Pso.DataSection.Data;

            switch (entry.Unk_5h)
            {
            default:
                ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString());
                break;

            case 0:     //Array_Structure
                var arrStruc = MetaUtils.ConvertData <Array_Structure>(data, eoffset);
                arrStruc.SwapEnd();
                aBlockId = (int)arrStruc.PointerDataId;
                aOffset  = (int)arrStruc.PointerDataOffset;
                aCount   = arrStruc.Count1;
                break;

            case 1:     //Raw in-line array
                break;

            case 2:     //also raw in-line array, but how different from above?
                break;

            case 4:                       //pointer array? default array?
                if (arrEntry.Unk_5h == 3) //pointers...
                {
                    var arrStruc4 = MetaUtils.ConvertData <Array_Structure>(data, eoffset);
                    arrStruc4.SwapEnd();
                    aBlockId = (int)arrStruc4.PointerDataId;
                    aOffset  = (int)arrStruc4.PointerDataOffset;
                    aCount   = arrStruc4.Count1;
                }
                break;

            case 129:     //also raw inline array? in junctions.pso
                break;
            }

            switch (arrEntry.Type)
            {
            default:
                ErrorXml(sb, indent, ename + ": WIP! Unsupported array entry DataType: " + arrEntry.Type.ToString());
                break;

            case RageLib.GTA5.PSO.DataType.Array:
                var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF;
                if (rk0 > 0)
                {
                    //var arrStruc5 = MetaUtils.ConvertDataArray<Array_StructurePointer>(data, eoffset, (int)rk0);
                    //for (int n = 0; n < rk0; n++) arrStruc5[n].SwapEnd();
                    aOffset = offset + entry.DataOffset;

                    OpenTag(sb, indent, arrTag);
                    for (int n = 0; n < rk0; n++)     //ARRAY ARRAY!
                    {
                        WriteArrayNode(sb, aind, cont, blockId, aOffset, arrEntry, estruct, "Item");

                        aOffset += 16;    //ptr size... todo: what if not pointer array?
                    }
                    CloseTag(sb, indent, ename);
                }
                else
                {
                    SelfClosingTag(sb, indent, arrTag);
                }
                break;

            case RageLib.GTA5.PSO.DataType.Structure:
                switch (arrEntry.Unk_5h)
                {
                case 0:
                    break;

                case 3:        //structure pointer array
                    var arrStrucPtr = MetaUtils.ConvertData <Array_StructurePointer>(data, eoffset);
                    arrStrucPtr.SwapEnd();
                    aBlockId = (int)arrStrucPtr.PointerDataId;
                    aOffset  = (int)arrStrucPtr.PointerDataOffset;
                    aCount   = arrStrucPtr.Count1;
                    if (aCount > 0)
                    {
                        var ptrArr = PsoUtils.GetPointerArray(cont.Pso, arrStrucPtr);
                        OpenTag(sb, indent, arrTag);
                        for (int n = 0; n < aCount; n++)
                        {
                            var ptrVal = ptrArr[n];
                            WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType);
                        }
                        CloseTag(sb, indent, ename);
                    }
                    break;

                default:
                    break;
                }
                arrTag += " itemType=\"" + HashString((MetaName)arrEntry.ReferenceKey) + "\"";
                if (aCount > 0)
                {
                    var aBlock = cont.Pso.GetBlock(aBlockId);
                    var atyp   = cont.GetStructureInfo((MetaName)arrEntry.ReferenceKey);
                    if (aBlock == null)
                    {
                        ErrorXml(sb, indent, ename + ": Array block not found: " + aBlockId.ToString());
                    }
                    else if ((MetaName)aBlock.NameHash != MetaName.PsoPOINTER)
                    {
                        OpenTag(sb, indent, arrTag);
                        if (atyp == null)
                        {
                            ErrorXml(sb, indent, ename + ": Array type not found: " + HashString((MetaName)arrEntry.ReferenceKey));
                        }
                        else
                        {
                            for (int n = 0; n < aCount; n++)
                            {
                                WriteNode(sb, aind, cont, aBlockId, aOffset, XmlTagMode.Item, (MetaName)arrEntry.ReferenceKey);
                                aOffset += atyp.StructureLength;
                                if ((n < (aCount - 1)) && (aBlock != null) && (aOffset >= aBlock.Length))
                                {
                                    break;
                                }
                            }
                        }
                        CloseTag(sb, indent, ename);
                    }
                    else
                    {
                    }       //pointer array should get here, but it's already handled above. should improve this.
                }
                else
                {
                    SelfClosingTag(sb, indent, arrTag);
                }
                break;

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

                case 0:         //hash array...
                    var arrHash = MetaUtils.ConvertData <Array_uint>(data, eoffset);
                    arrHash.SwapEnd();
                    var hashArr = PsoUtils.GetHashArray(cont.Pso, arrHash);
                    WriteItemArray(sb, hashArr, indent, ename, "Hash", HashString);
                    break;
                }
                break;

            case RageLib.GTA5.PSO.DataType.Float2:
                aCount  = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF;
                arrTag += " itemType=\"Vector2\"";
                var v2Arr = MetaUtils.ConvertDataArray <Vector2>(data, eoffset, (int)aCount);
                WriteRawArray(sb, v2Arr, indent, ename, "Vector2", FormatVector2Swap, 1);
                break;

            case RageLib.GTA5.PSO.DataType.Float3:
                aCount  = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF;
                arrTag += " itemType=\"Vector3\"";     //this is actually aligned as vector4, the W values are crazy in places
                var v4Arr = MetaUtils.ConvertDataArray <Vector4>(data, eoffset, (int)aCount);
                WriteRawArray(sb, v4Arr, indent, ename, "Vector3", FormatVector4SwapXYZOnly, 1);
                break;

            case RageLib.GTA5.PSO.DataType.UByte:
                var barr = new byte[aCount];
                if (aCount > 0)
                {
                    var bblock = cont.Pso.GetBlock(aBlockId);
                    var boffs  = bblock.Offset + aOffset;
                    Buffer.BlockCopy(data, boffs, barr, 0, (int)aCount);
                }
                WriteRawArray(sb, barr, indent, ename, "byte");
                break;

            case RageLib.GTA5.PSO.DataType.Bool:
                var barr2 = new byte[aCount];
                if (aCount > 0)
                {
                    var bblock = cont.Pso.GetBlock(aBlockId);
                    var boffs  = bblock.Offset + aOffset;
                    Buffer.BlockCopy(data, boffs, barr2, 0, (int)aCount);
                }
                WriteRawArray(sb, barr2, indent, ename, "boolean");     //todo: true/false output
                break;

            case RageLib.GTA5.PSO.DataType.Float:
                var arrFloat = MetaUtils.ConvertData <Array_float>(data, eoffset);
                arrFloat.SwapEnd();
                var floatArr = PsoUtils.GetFloatArray(cont.Pso, arrFloat);
                WriteRawArray(sb, floatArr, indent, ename, "float");
                break;

            case RageLib.GTA5.PSO.DataType.UShort:
                var arrShort = MetaUtils.ConvertData <Array_Structure>(data, eoffset);
                arrShort.SwapEnd();
                var shortArr = PsoUtils.GetUShortArray(cont.Pso, arrShort);
                WriteRawArray(sb, shortArr, indent, ename, "ushort");
                break;

            case RageLib.GTA5.PSO.DataType.UInt:
                var intArr = MetaUtils.ConvertDataArray <int>(data, eoffset, (int)aCount);
                WriteRawArray(sb, intArr, indent, ename, "int");
                break;

            case RageLib.GTA5.PSO.DataType.SInt:
                var arrUint2 = MetaUtils.ConvertData <Array_uint>(data, eoffset);
                arrUint2.SwapEnd();
                var intArr2 = PsoUtils.GetUintArray(cont.Pso, arrUint2);
                WriteRawArray(sb, intArr2, indent, ename, "int");
                break;

            case RageLib.GTA5.PSO.DataType.Enum:
                var arrEnum = MetaUtils.ConvertData <Array_uint>(data, eoffset);
                arrEnum.SwapEnd();
                var enumArr = PsoUtils.GetUintArray(cont.Pso, arrEnum);
                var enumDef = cont.GetEnumInfo((MetaName)arrEntry.ReferenceKey);
                WriteItemArray(sb, enumArr, indent, ename, "enum", (ie) => {
                    var eval = enumDef?.FindEntry((int)ie);
                    return(HashString((MetaName)(eval?.EntryNameHash ?? 0)));
                });
                break;
            }
        }