"NTRO" block. CResourceIntrospectionManifest
상속: Block
예제 #1
0
        private NTROSerialization.NTROStruct ReadStructure(ResourceIntrospectionManifest.ResourceDiskStruct refStruct, long startingOffset)
        {
            var structEntry = new NTROSerialization.NTROStruct(refStruct.Name);

            foreach (var field in refStruct.FieldIntrospection)
            {
                Reader.BaseStream.Position = startingOffset + field.OnDiskOffset;

                ReadFieldIntrospection(field, ref structEntry);
            }

            if (refStruct.BaseStructId != 0)
            {
                var previousOffset = Reader.BaseStream.Position;

                var newStruct = Resource.IntrospectionManifest.ReferencedStructs.First(x => x.Id == refStruct.BaseStructId);

                // Valve doesn't print this struct's type, so we can't just call ReadStructure *sigh*
                foreach (var field in newStruct.FieldIntrospection)
                {
                    Reader.BaseStream.Position = startingOffset + field.OnDiskOffset;

                    ReadFieldIntrospection(field, ref structEntry);
                }

                Reader.BaseStream.Position = previousOffset;
            }

            return structEntry;
        }
예제 #2
0
        private void ReadFieldIntrospection(ResourceIntrospectionManifest.ResourceDiskStruct.Field field, ref NTROSerialization.NTROStruct structEntry)
        {
            uint count = (uint)field.Count;
            bool pointer = false; // TODO: get rid of this

            if (count == 0)
            {
                count = 1;
            }

            long prevOffset = 0;

            if (field.Indirections.Count > 0)
            {
                // TODO
                if (field.Indirections.Count > 1)
                {
                    throw new NotImplementedException("More than one indirection, not yet handled.");
                }

                // TODO
                if (field.Count > 0)
                {
                    throw new NotImplementedException("Indirection.Count > 0 && field.Count > 0");
                }

                var indirection = field.Indirections[0]; // TODO: depth needs fixing?

                var offset = Reader.ReadUInt32();

                if (indirection == 0x03)
                {
                    pointer = true;

                    if (offset == 0)
                    {
                        structEntry.Add(field.FieldName, new NTROSerialization.NTROValue<byte?>(field.Type, (byte?)null, true)); //being byte shouldn't matter

                        return;
                    }

                    prevOffset = Reader.BaseStream.Position;

                    Reader.BaseStream.Position += offset - 4;
                }
                else if (indirection == 0x04)
                {
                    count = Reader.ReadUInt32();

                    prevOffset = Reader.BaseStream.Position;

                    if (count > 0)
                    {
                        Reader.BaseStream.Position += offset - 8;
                    }
                }
                else
                {
                    throw new NotImplementedException(string.Format("Unknown indirection. ({0})", indirection));
                }
            }

            //if (pointer)
            //{
            //    Writer.Write("{0} {1}* = (ptr) ->", ValveDataType(field.Type), field.FieldName);
            //}
            if (field.Count > 0 || field.Indirections.Count > 0)
            {
                var ntroValues = new NTROSerialization.NTROArray(field.Type, (int)count, pointer, field.Indirections.Count > 0);

                for (var i = 0; i < count; i++)
                {
                    ntroValues[i] = ReadField(field, pointer);
                }

                structEntry.Add(field.FieldName, ntroValues);
            }
            else
            {
                for (var i = 0; i < count; i++)
                {
                    structEntry.Add(field.FieldName, ReadField(field, pointer));
                }
            }

            if (prevOffset > 0)
            {
                Reader.BaseStream.Position = prevOffset;
            }
        }
예제 #3
0
        /// <summary>
        /// Reads the given <see cref="Stream"/>.
        /// </summary>
        /// <param name="input">The input <see cref="Stream"/> to read from.</param>
        public void Read(Stream input)
        {
            Reader = new BinaryReader(input);

            FileSize = Reader.ReadUInt32();

            if (FileSize == Package.MAGIC)
            {
                throw new InvalidDataException("Use Package() class to parse VPK files.");
            }

            // TODO: Some real files seem to have different file size
            if (FileSize != Reader.BaseStream.Length)
            {
                //throw new Exception(string.Format("File size does not match size specified in file. {0} != {1}", FileSize, Reader.BaseStream.Length));
            }

            HeaderVersion = Reader.ReadUInt16();

            if (HeaderVersion != KnownHeaderVersion)
            {
                throw new InvalidDataException(string.Format("Bad header version. ({0} != expected {1})", HeaderVersion, KnownHeaderVersion));
            }

            Version = Reader.ReadUInt16();

            var blockOffset = Reader.ReadUInt32();
            var blockCount = Reader.ReadUInt32();

            Reader.BaseStream.Position += blockOffset - 8; // 8 is 2 uint32s we just read

            for (var i = 0; i < blockCount; i++)
            {
                var blockType = Encoding.UTF8.GetString(Reader.ReadBytes(4));
                var block = ConstructFromType(blockType);

                var position = Reader.BaseStream.Position;

                // Offset is relative to current position
                block.Offset = (uint)position + Reader.ReadUInt32();
                block.Size = Reader.ReadUInt32();

                block.Read(Reader, this);

                switch (block.GetChar())
                {
                    case BlockType.REDI:
                        EditInfo = (ResourceEditInfo)block;

                        // Try to determine resource type by looking at first compiler indentifier
                        if (ResourceType == ResourceType.Unknown && EditInfo.Structs.ContainsKey(ResourceEditInfo.REDIStruct.SpecialDependencies))
                        {
                            var specialDeps = (Blocks.ResourceEditInfoStructs.SpecialDependencies)EditInfo.Structs[ResourceEditInfo.REDIStruct.SpecialDependencies];

                            if (specialDeps.List.Count > 0)
                            {
                                ResourceType = DetermineResourceTypeByCompilerIdentifier(specialDeps.List[0].CompilerIdentifier);
                            }
                        }

                        break;

                    case BlockType.RERL:
                        ExternalReferences = (ResourceExtRefList)block;
                        break;

                    case BlockType.NTRO:
                        IntrospectionManifest = (ResourceIntrospectionManifest)block;

                        if (ResourceType == ResourceType.Unknown && IntrospectionManifest.ReferencedStructs.Count > 0)
                        {
                            switch (IntrospectionManifest.ReferencedStructs[0].Name)
                            {
                                case "VSoundEventScript_t":
                                    ResourceType = ResourceType.SoundEventScript;
                                    break;

                                case "CWorldVisibility":
                                    ResourceType = ResourceType.WorldVisibility;
                                    break;
                            }
                        }

                        break;
                }

                Blocks.Add(block.GetChar(), block);

                Reader.BaseStream.Position = position + 8;
            }
        }
예제 #4
0
        private NTROSerialization.NTROValue ReadField(ResourceIntrospectionManifest.ResourceDiskStruct.Field field, bool pointer)
        {
            switch (field.Type)
            {
                case DataType.Struct:
                    var newStruct = Resource.IntrospectionManifest.ReferencedStructs.First(x => x.Id == field.TypeData);
                    return new NTROSerialization.NTROValue<NTROSerialization.NTROStruct>(field.Type, ReadStructure(newStruct, Reader.BaseStream.Position), pointer);

                case DataType.Enum:
                    // TODO: Lookup in ReferencedEnums
                    return new NTROSerialization.NTROValue<uint>(field.Type, Reader.ReadUInt32(), pointer);

                case DataType.SByte:
                    return new NTROSerialization.NTROValue<sbyte>(field.Type, Reader.ReadSByte(), pointer);

                case DataType.Byte:
                    return new NTROSerialization.NTROValue<byte>(field.Type, Reader.ReadByte(), pointer);

                case DataType.Boolean:
                    return new NTROSerialization.NTROValue<bool>(field.Type, Reader.ReadByte() == 1 ? true : false, pointer);

                case DataType.Int16:
                    return new NTROSerialization.NTROValue<short>(field.Type, Reader.ReadInt16(), pointer);

                case DataType.UInt16:
                    return new NTROSerialization.NTROValue<ushort>(field.Type, Reader.ReadUInt16(), pointer);

                case DataType.Int32:
                    return new NTROSerialization.NTROValue<int>(field.Type, Reader.ReadInt32(), pointer);

                case DataType.UInt32:
                    return new NTROSerialization.NTROValue<uint>(field.Type, Reader.ReadUInt32(), pointer);

                case DataType.Float:
                    return new NTROSerialization.NTROValue<float>(field.Type, Reader.ReadSingle(), pointer);

                case DataType.Int64:
                    return new NTROSerialization.NTROValue<long>(field.Type, Reader.ReadInt64(), pointer);

                case DataType.ExternalReference: // Handled elsewhere
                case DataType.UInt64:
                    return new NTROSerialization.NTROValue<ulong>(field.Type, Reader.ReadUInt64(), pointer);

                case DataType.Vector:
                    var vector3 = new NTROSerialization.Vector3(
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle()
                    );

                    return new NTROSerialization.NTROValue<NTROSerialization.Vector3>(field.Type, vector3, pointer);

                case DataType.Quaternion:
                case DataType.Color:
                case DataType.Fltx4:
                case DataType.Vector4D:
                    var vector4 = new NTROSerialization.Vector4(
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle()
                    );

                    return new NTROSerialization.NTROValue<NTROSerialization.Vector4>(field.Type, vector4, pointer);

                case DataType.String4:
                case DataType.String:
                    return new NTROSerialization.NTROValue<string>(field.Type, Reader.ReadOffsetString(Encoding.UTF8), pointer);

                case DataType.Matrix3x4:
                case DataType.Matrix3x4a:
                    var matrix3x4a = new NTROSerialization.Matrix3x4(
                        Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(),
                        Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(),
                        Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle()
                     );

                    return new NTROSerialization.NTROValue<NTROSerialization.Matrix3x4>(field.Type, matrix3x4a, pointer);

                case DataType.CTransform:
                    var transform = new NTROSerialization.CTransform(
                        Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(),
                        Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle()
                     );

                    return new NTROSerialization.NTROValue<NTROSerialization.CTransform>(field.Type, transform, pointer);

                default:
                    throw new NotImplementedException(string.Format("Unknown data type: {0}", field.Type));
            }
        }
예제 #5
0
        private NTROValue ReadField(ResourceIntrospectionManifest.ResourceDiskStruct.Field field, bool pointer)
        {
            switch (field.Type)
            {
                case DataType.Struct:
                    var newStruct = Resource.IntrospectionManifest.ReferencedStructs.First(x => x.Id == field.TypeData);
                    return new NTROValue<NTROStruct>(field.Type, ReadStructure(newStruct, Reader.BaseStream.Position), pointer);

                case DataType.Enum:
                    // TODO: Lookup in ReferencedEnums
                    return new NTROValue<uint>(field.Type, Reader.ReadUInt32(), pointer);

                case DataType.SByte:
                    return new NTROValue<sbyte>(field.Type, Reader.ReadSByte(), pointer);

                case DataType.Byte:
                    return new NTROValue<byte>(field.Type, Reader.ReadByte(), pointer);

                case DataType.Boolean:
                    return new NTROValue<bool>(field.Type, Reader.ReadByte() == 1 ? true : false, pointer);

                case DataType.Int16:
                    return new NTROValue<short>(field.Type, Reader.ReadInt16(), pointer);

                case DataType.UInt16:
                    return new NTROValue<ushort>(field.Type, Reader.ReadUInt16(), pointer);

                case DataType.Int32:
                    return new NTROValue<int>(field.Type, Reader.ReadInt32(), pointer);

                case DataType.UInt32:
                    return new NTROValue<uint>(field.Type, Reader.ReadUInt32(), pointer);

                case DataType.Float:
                    return new NTROValue<float>(field.Type, Reader.ReadSingle(), pointer);

                case DataType.Int64:
                    return new NTROValue<long>(field.Type, Reader.ReadInt64(), pointer);

                case DataType.ExternalReference:
                    var id = Reader.ReadUInt64();
                    var value = id > 0
                        ? Resource.ExternalReferences?.ResourceRefInfoList.FirstOrDefault(c => c.Id == id)
                        : null;

                    return new NTROValue<ResourceExtRefList.ResourceReferenceInfo>(field.Type, value, pointer);

                case DataType.UInt64:
                    return new NTROValue<ulong>(field.Type, Reader.ReadUInt64(), pointer);

                case DataType.Vector:
                    var vector3 = new Vector3(
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle());

                    return new NTROValue<Vector3>(field.Type, vector3, pointer);

                case DataType.Quaternion:
                case DataType.Color:
                case DataType.Fltx4:
                case DataType.Vector4D:
                case DataType.Vector4D_44:
                    var vector4 = new Vector4(
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle());

                    return new NTROValue<Vector4>(field.Type, vector4, pointer);

                case DataType.String4:
                case DataType.String:
                    return new NTROValue<string>(field.Type, Reader.ReadOffsetString(Encoding.UTF8), pointer);

                case DataType.Matrix3x4:
                case DataType.Matrix3x4a:
                    var matrix3x4a = new Matrix3x4(
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle());

                    return new NTROValue<Matrix3x4>(field.Type, matrix3x4a, pointer);

                case DataType.CTransform:
                    var transform = new CTransform(
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle(),
                        Reader.ReadSingle());

                    return new NTROValue<CTransform>(field.Type, transform, pointer);

                default:
                    throw new NotImplementedException($"Unknown data type: {field.Type} (name: {field.FieldName})");
            }
        }