/// <summary>
        ///     Makes a string from the SourceRegister value. e.g -r10.xyzw
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        private string GetSourceToken(SourceRegister source)
        {
            //  Use reflection to determine which Source values to use with the OpCode,
            //  return empty string for any unused source
            var attribute = ( OpCodeAttributes )VectorOp.Attribute(typeof(OpCodeAttributes));

            if ((!attribute.ParamA || source != Source0) && (!attribute.ParamB || source != Source1) &&
                (!attribute.ParamC || source != Source2))
            {
                return(string.Empty);
            }

            switch (source.Type)
            {
            case SourceRegister.SourceType.Temporary:
                return(source.NegationPrefix + RegisterToken + source.TempID + source.Swizzle.GetSuffix( ));

            case SourceRegister.SourceType.Attribute:
                return(source.NegationPrefix + AttributeToken + AttributerSource + source.Swizzle.GetSuffix( ));

            case SourceRegister.SourceType.Constant:
                return(source.NegationPrefix + ConstantToken + ConstantSource + source.Swizzle.GetSuffix( ));

            default:
                throw new DataException("Invalid " + nameof(source.Type));
            }
        }
        public VertexProgramInstruction(byte[] data)
        {
            var dword0 = BitConverter.ToUInt32(data, 0);
            var dword1 = BitConverter.ToUInt32(data, 4);
            var dword2 = BitConverter.ToUInt32(data, 8);
            var dword3 = BitConverter.ToUInt32(data, 12);

            ScalarOp         = ( ScalarOps )GetBits(dword1, ScalarOpCodeMask, ScalarOpCodeShift);
            VectorOp         = ( VectorOps )GetBits(dword1, VectorOpCodeMask, VectorOpCodeShift);
            ConstantSource   = GetBits(dword1, ConstantSourceMask, ConstantSourceShift);
            AttributerSource = GetBits(dword1, AttributeSourceMask, AttributeSourceShift);

            var src0Bits = GetSplitBits(dword1, dword2, Src0MsbMask, Src0MsbShift, Src0LsbMask, Src0LsbShift,
                                        Src0LsbLength);
            var src1Bits = GetBits(dword2, Src1Mask, Src1Shift);
            var src2Bits = GetSplitBits(dword2, dword3, Src2MsbMask, Src2MsbShift, Src2LsbMask, Src2LsbShift,
                                        Src2LsbLength);

            Source0 = new SourceRegister(src0Bits);
            Source1 = new SourceRegister(src1Bits);
            Source2 = new SourceRegister(src2Bits);

            DstTempWriteMask   = new WriteMask(GetBits(dword3, Dst2WriteMaskMask, Dst2WriteMaskShift));
            RegisterSource     = GetBits(dword3, RegisterMask, RegisterShift);
            DstScalarWriteMask = new WriteMask(GetBits(dword3, Dst1WriteMaskMask, Dst1WriteMaskShift));
            DstVectorWriteMask = new WriteMask(GetBits(dword3, Dst0WriteMaskMask, Dst0WriteMaskShift));
            ScalarResult       = GetBits(dword3, ResultMask, ResultShift) == 1;
            Destination        = ( DestinationRegister )GetBits(dword3, Dst0Mask, Dst0Shift);
            IndexConstant      = GetBits(dword3, IndexConstantMask, IndexConstantShift);
            LastInstruction    = GetBits(dword3, LastMask, LastShift) == 1;
        }