public static SignatureParameterDescription Parse(BytecodeReader reader, BytecodeReader parameterReader,
                                                          ChunkType chunkType, SignatureElementSize size)
        {
            uint stream = 0;

            if (size == SignatureElementSize._7 || size == SignatureElementSize._8)
            {
                stream = parameterReader.ReadUInt32();
            }
            uint nameOffset = parameterReader.ReadUInt32();
            var  nameReader = reader.CopyAtOffset((int)nameOffset);

            var result = new SignatureParameterDescription
            {
                SemanticName    = nameReader.ReadString(),
                SemanticIndex   = parameterReader.ReadUInt32(),
                SystemValueType = (Name)parameterReader.ReadUInt32(),
                ComponentType   = (RegisterComponentType)parameterReader.ReadUInt32(),
                Register        = parameterReader.ReadUInt32(),
                Stream          = stream,
            };

            uint mask = parameterReader.ReadUInt32();

            result.Mask          = mask.DecodeValue <ComponentMask>(0, 7);
            result.ReadWriteMask = mask.DecodeValue <ComponentMask>(8, 15);

            if (size == SignatureElementSize._8)
            {
                MinPrecision minPrecision = (MinPrecision)parameterReader.ReadUInt32();
                result.MinPrecision = minPrecision;
            }

            // This is my guesswork, but it works so far...
            if (chunkType == ChunkType.Osg5 ||
                chunkType == ChunkType.Osgn ||
                chunkType == ChunkType.Osg1)
            {
                result.ReadWriteMask = (ComponentMask)(ComponentMask.All - result.ReadWriteMask);
            }

            return(result);
        }
        public static InputOutputSignatureChunk Parse(BytecodeReader reader, ChunkType chunkType)
        {
            InputOutputSignatureChunk result;

            switch (chunkType)
            {
            case ChunkType.Isgn:
            case ChunkType.Isg1:
                result = new InputSignatureChunk();
                break;

            case ChunkType.Osgn:
            case ChunkType.Osg1:
            case ChunkType.Osg5:
                result = new OutputSignatureChunk();
                break;

            case ChunkType.Pcsg:
            case ChunkType.Psg1:
                result = new PatchConstantSignatureChunk();
                break;

            default:
                throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType);
            }

            var chunkReader  = reader.CopyAtCurrentPosition();
            var elementCount = chunkReader.ReadUInt32();
            var uniqueKey    = chunkReader.ReadUInt32();

            SignatureElementSize elementSize;

            switch (chunkType)
            {
            case ChunkType.Isgn:
            case ChunkType.Osgn:
            case ChunkType.Pcsg:
                elementSize = SignatureElementSize._6;
                break;

            case ChunkType.Osg5:
                elementSize = SignatureElementSize._7;
                break;

            case ChunkType.Osg1:
            case ChunkType.Isg1:
            case ChunkType.Psg1:
                elementSize = SignatureElementSize._8;
                break;

            default:
                throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType);
            }

            for (int i = 0; i < elementCount; i++)
            {
                result.Parameters.Add(SignatureParameterDescription.Parse(reader, chunkReader, chunkType, elementSize));
            }

            return(result);
        }