private int readFromOffset(int offset, byte[] rawData)
        {
            // the first 2 bytes are the version - discard it for now
            int frameTypeAndSequence = rawData[offset + 2];
            int frameType            = frameTypeAndSequence & 3;
            int sequence             = frameTypeAndSequence >> 2;
            int frameLength          = 0;

            if (frameType == 0)
            {
                telemPacketCount++;
                if (telemPacketCount > packetCountAtStartOfNextRateCheck)
                {
                    lastPacketRateEstimate = (int)((float)TimeSpan.TicksPerSecond * (float)(telemPacketCount - packetCountAtStartOfCurrentRateCheck) / (float)(DateTime.UtcNow.Ticks - ticksAtStartOfCurrentPacketRateCheck));
                    Console.WriteLine("Packet rate = " + lastPacketRateEstimate + "Hz, totals: type0 = " + telemPacketCount + " type1 = " + stringsPacketCount + " type2 = " + additionalStringsPacketCount +
                                      " in sequence = " + inSequenceTelemCount + " oos accepted = " + acceptedOutOfSequenceTelemCount + " oos rejected = " + discardedTelemCount);
                    packetCountAtStartOfCurrentRateCheck = telemPacketCount;
                    packetCountAtStartOfNextRateCheck    = packetCountAtStartOfCurrentRateCheck + packetRateCheckInterval;
                    ticksAtStartOfCurrentPacketRateCheck = DateTime.UtcNow.Ticks;
                }
                frameLength = sTelemetryData_PacketSize;
                Boolean sequenceCheckOK = isNextInSequence(sequence);
                if (sequenceCheckOK)
                {
                    inSequenceTelemCount++;
                }
                if (strictPacketOrdering && !sequenceCheckOK)
                {
                    discardedTelemCount++;
                }
                else
                {
                    GCHandle handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned);
                    try
                    {
                        sTelemetryData telem = (sTelemetryData)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sTelemetryData));
                        if (sequenceCheckOK || !telemIsOutOfSequence(telem))
                        {
                            buttonsState = ConvertBytesToBoolArray(telem.sDPad, telem.sJoyPad1, telem.sJoyPad2);
                            lastSequenceNumberForTelemPacket = sequence;
                            workingGameState = StructHelper.MergeWithExistingState(workingGameState, telem);
                            newSpotterData   = workingGameState.hasNewPositionData;
                        }
                    }
                    finally
                    {
                        handle.Free();
                    }
                }
            }
            else if (frameType == 1)
            {
                stringsPacketCount++;
                frameLength = sParticipantInfoStrings_PacketSize;
                GCHandle handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sParticipantInfoStrings strings = (sParticipantInfoStrings)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sParticipantInfoStrings));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, strings);
                }
                finally
                {
                    handle.Free();
                }
            }
            else if (frameType == 2)
            {
                additionalStringsPacketCount++;
                frameLength = sParticipantInfoStringsAdditional_PacketSize;
                GCHandle handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sParticipantInfoStringsAdditional additional = (sParticipantInfoStringsAdditional)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sParticipantInfoStringsAdditional));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, additional);
                }
                finally
                {
                    handle.Free();
                }
            }
            else
            {
                Console.WriteLine("Unrecognised frame type " + frameType + " from byte " + rawData[offset + 2]);
            }
            return(frameLength + offset);
        }
Example #2
0
        public static pCarsAPIStruct MergeWithExistingState(pCarsAPIStruct existingState, sParticipantInfoStrings udpParticipantStrings)
        {
            existingState.mCarClassName = udpParticipantStrings.sCarClassName;
            existingState.mCarName      = udpParticipantStrings.sCarName;

            existingState.mTrackLocation  = udpParticipantStrings.sTrackLocation;
            existingState.mTrackVariation = udpParticipantStrings.sTrackVariation;
            if (existingState.mParticipantData == null)
            {
                existingState.mParticipantData = new pCarsAPIParticipantStruct[56];
            }
            for (int i = 0; i < udpParticipantStrings.sName.Count(); i++)
            {
                existingState.mParticipantData[i].mName = udpParticipantStrings.sName[i].nameByteArray;
            }
            return(existingState);
        }