B4J Question UDP Packet Data (Bytearray) to "struct"?

DonManfred

Expert
Licensed User
Longtime User
Here i started a thread asking on how to Capture Broadcast UDP Packets.
I´m not able to test it as yet but i´m sure it will work when erel says it will.

So. Imagine it will work, then i am supposed to get different UDP Packets with different contents.

One packet for example is the ParticipantInfoStrings struct


From my investigations with delphi on win32 i can say that i got two kind of packets so far.
ONE with a size of 1347 and a lot other with the size of 1367 bytes.
The last one are the truct sTelemetryData

How would i need to use the bytearray i have to get the sBuildVersionNumber, sPacketType, sCarName and so on into B4J variables?

I need to understand how to interpret for example
u16 sBuildVersionNumber; // 0

How do i get a B4J variable from the first two bytes of the bytearray?

There are different types in the structs i have to rebuild.

u16, u32, u8, s8, s16, f32, char....

The structs for the telemetrydata is more complex


Any help/tips/hints are welcome ;-)
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You should post a full hex message. Without it is difficult to get it right.
Something like:
B4X:
'process globals
Type PIS (BuildVersionNumber As Short, PacketType As Byte, CarName As String, _
     TrackLocation As String, TrackVariation As String, Name(16) As String)


Sub ParseMessage(data() As Byte) As PIS
   Dim p As PIS
   p.Initialize
   Dim raf As RandomAccessFile
   raf.Initialize3(data, True) 'change the endianess if the version number is incorrect
   p.BuildVersionNumber = raf.ReadShort(0)
   p.PacketType = raf.ReadSignedByte(raf.CurrentPosition)
   Dim buffer(64) As Byte
   p.CarName = ReadString(raf, buffer)
   p.TrackLocation = ReadString(raf, buffer)
   p.TrackVariation = ReadString(raf, buffer)
   For i = 0 To p.Name.Length
     p.Name(i) = ReadString(raf, buffer)
   Next
   Return p
End Sub

Private Sub ReadString(raf As RandomAccessFile, buffer() As Byte) As String
   raf.ReadBytes(buffer, 0, buffer.Length, raf.CurrentPosition)
   Return BytesToString(buffer, 0, buffer.Length, "utf8")
End Sub
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Erel wins dodgy acronym of the day award for

Type PIS (BuildVersionNumber.......

On a serious note , you could use JNA Structure to get the data too
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
You should post a full hex message. Without it is difficult to get it right

It starts with this... Seems the b4j log cut the output

Something like

Thank you very much for the sample!!! It was a really help to get this working

I´m working on defining the desired ParseMethod for the telemetry packet right now

I´ll keep you informed
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
On a serious note , you could use JNA Structure to get the data too
Can you explain or even give a link to more information about this? (but i´ll try to do a search for it too)

I gues you are talking about the \jna-master\src\com\sun\jna\Structure.java?

Do you have an example on how to use this from B4J?
 
Last edited:
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
I must agree with Erel as there are so few packet types, you would end up writing far more code than using pure B4J.

If RandomAccessFile is an nio.ByteBuffer, then that is probably the cleanest solution to use.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Just if you are interested... It´s not finished though but it is a working start

B4X:
    Type Participant (BuildVersionNumber As Short, PacketType As Byte, CarName As String, _
     CarClassName As String, TrackLocation As String, TrackVariation As String, Name(16) As String)

    Type ParticipantInfo (WorldPosition(3) As Short, CurrentLapDistance As Short, RacePosition As Byte, _
    LapsCompleted As Byte, CurrentLap As Byte, Sector As Byte, LastSectorTime As Float)
  
    Type Telemetry (BuildVersionNumber As Short, PacketType As Byte, GameSessionstate As Byte, _
    ViewedParticipantIndex As Byte, NumParticipants As Byte, UnfilteredThrottle As Byte, _
    UnfilteredBrake As Byte, UnfilteredSteering As Byte, UnfilteredClutch As Byte, RaceStateFlags As Byte, _
    LapsInEvent As Byte, BestLapTime As Float, LastLapTime As Float, CurrentTime As Float, _
    SplitTimeAhead As Float, SplitTimeBehind As Float, SplitTime As Float, EventTimeRemaining As Float, _
    PersonalFastestLapTime As Float, WorldFastestLapTime As Float, CurrentSector1Time As Float, _
    CurrentSector2Time As Float, CurrentSector3Time As Float, FastestSector1Time As Float, FastestSector2Time As Float, _
    FastestSector3Time As Float, PersonalFastestSector1Time As Float, PersonalFastestSector2Time As Float, _
    PersonalFastestSector3Time As Float, _
    WorldFastestSector1Time As Float, WorldFastestSector2Time As Float, _
    WorldFastestSector3Time As Float, JoyPad As Short, HighestFlag As Byte, PitModeSchedule As Byte, _
    OilTempCelsius As Short, OilPressureKPa As Short, WaterTempCelsius As Short, WaterPressureKpa As Short, _
    FuelPressureKpa As Short, CarFlags As Byte, FuelCapacity As Byte, Brake As Byte, Throttle As Byte, _
    Clutch As Byte, Steering As Byte, FuelLevel As Float, Speed As Float, RPM As Short, MaxRPM As Short, _
    GearNumGears As Byte, BoostAmount As Byte, EnforcedPitstopLap As Byte, CrashState As Byte, _
    OdometerKM As Float, Orientation(3) As Float, LocalVelocity(3) As Float, WorldVelocity(3) As Float, _
    AngularVelocity(3) As Float, LocalAcceleration(3) As Float, WorldAcceleration(3) As Float, _
    ExtentsCentre(3) As Float, TyreFlags(4) As Byte, Terrain(4) As Byte, TyreY(4) As Float, TyreRPS(4) As Float, _
    TyreSlipSpeed(4) As Float, TyreTemp(4) As Byte, TyreGrip(4) As Byte, _
    TyreHeightAboveGround(4) As Float, TyreLateralStiffness(4) As Float, TyreWear(4) As Byte, BrakeDamage(4) As Byte, _
    SuspensionDamage(4) As Byte, BrakeTempCelsius(4) As Short, TyreTreadTemp(4) As Short, TyreLayerTemp(4) As Short, _
    TyreCarcassTemp(4) As Short, TyreRimTemp(4) As Short, TyreInternalAirTemp(4) As Short, _
    WheelLocalPositionY(4) As Float, RideHeight(4) As Float, SuspensionTravel(4) As Float, SuspensionVelocity(4) As Float, _
    AirPressure(4) As Short, EngineSpeed As Float, EngineTorque As Float, _
    AeroDamage As Byte, EngineDamage As Byte, AmbientTemperature As Byte, TrackTemperature As Byte, _
    RainDensity As Byte, WindSpeed As Byte, WindDirectionX As Byte, WindDirectionY As Byte, _
    Driver(56) As ParticipantInfo, TrackLength As Float, Wings(2) As Byte, DPad As Byte)

B4X:
Sub UDP_PacketArrived (Packet As UDPPacket)
    Dim msg As String
    msg = BytesToString(Packet.Data, Packet.Offset, Packet.Length, "UTF8")
    Log("> NEW PACKET")
    Log("Host: "&Packet.Host)
    Log("Adress: "&Packet.HostAddress)
    Log("Port: "&Packet.Port)
    Log("Len: "&Packet.Length)
    Log("ToString: "&Packet.toString)
    'Log("HEX: "&bconv.HexFromBytes(Packet.Data))
  
    If Packet.Length = 1347 Then
        Dim drivers As Participant = ParseMessage(Packet.Data)
        Log(drivers.BuildVersionNumber)

        Log(drivers.CarName)
        Log(drivers.CarClassName)
        Log(drivers.TrackLocation)
        Log(drivers.TrackVariation)
        For i = 0 To 15
            Log(i&": "&drivers.Name(i))      
        Next
    End If
    If Packet.Length = 1367 Then
        Dim t As Telemetry =    ParseTelemetry(Packet.Data)
        Log("Speed: "&t.Speed)      
        Log("Drivers: "&t.Driver.Length)
        ' All other Values of Telemetry are available too    
    End If

    memo.Text = memo.Text &CRLF&bconv.HexFromBytes(Packet.Data)
    'Msgbox.show("Message received: " & msg, "")
    Log(msg)
End Sub

B4X:
Sub ParseMessage(data() As Byte) As Participant
   Log("ParseMessage("&data.Length&")")
     Dim p As Participant
   p.Initialize
   Dim raf As RandomAccessFile
   raf.Initialize3(data, True) 'change the endianess if the version number is incorrect
   p.BuildVersionNumber = raf.ReadShort(0)
   p.PacketType = raf.ReadSignedByte(2)
   Dim buffer(64) As Byte
   p.CarName = ReadString(raf, buffer).Replace(Chr(0),Chr(32))
   p.CarClassName = ReadString(raf, buffer).Replace(Chr(0),Chr(32))
   p.TrackLocation = ReadString(raf, buffer).Replace(Chr(0),Chr(32))
   p.TrackVariation = ReadString(raf, buffer).Replace(Chr(0),Chr(32))
   For i = 0 To p.Name.Length-1
     p.Name(i) = ReadString(raf, buffer).Replace(Chr(0),Chr(32))
   Next
   Return p
End Sub
Sub ParseTelemetry(data() As Byte) As Telemetry
  Log("ParseTelemetry("&data.Length&")")
    Dim t As Telemetry
  t.Initialize
  Dim raf As RandomAccessFile
  raf.Initialize3(data, False) 'change the endianess if the version number is incorrect
    'struct sTelemetryData
  t.BuildVersionNumber = raf.ReadShort(0)
  t.PacketType = raf.ReadUnsignedByte(2)
    t.GameSessionstate = raf.ReadUnsignedByte(3)
    '  // Participant info
    t.ViewedParticipantIndex = raf.ReadSignedByte(4)
    '  s8    sNumParticipants;             // 5
    t.NumParticipants = raf.ReadSignedByte(5)
    '  // Unfiltered input
    '  u8    sUnfilteredThrottle;          // 6
    t.UnfilteredThrottle = raf.ReadUnsignedByte(6)
    '  u8    sUnfilteredBrake;             // 7
    t.UnfilteredBrake = raf.ReadUnsignedByte(7)
    '  s8    sUnfilteredSteering;          // 8
    t.UnfilteredSteering = raf.ReadUnsignedByte(8)
    '  u8    sUnfilteredClutch;            // 9
    t.UnfilteredClutch = raf.ReadUnsignedByte(9)
    '  u8    sRaceStateFlags;              // 10
    t.RaceStateFlags = raf.ReadUnsignedByte(10)
    '
    '  // Event information
    '  u8    sLapsInEvent;                 // 11
    t.LapsInEvent =  raf.ReadUnsignedByte(11)
    '
    '  // Timings
    '  f32   sBestLapTime;                 // 12
    t.BestLapTime = raf.ReadFloat(12)
    '  f32   sLastLapTime;                 // 16
    t.LastLapTime = raf.ReadFloat(16)
    '  f32   sCurrentTime;                 // 20
    t.CurrentTime = raf.ReadFloat(20)
    '  f32   sSplitTimeAhead;              // 24
    t.SplitTimeAhead = raf.ReadFloat(24)
    '  f32   sSplitTimeBehind;             // 28
    t.SplitTimeBehind = raf.ReadFloat(28)
    '  f32   sSplitTime;                   // 32
    t.SplitTime = raf.ReadFloat(32)
    '  f32   sEventTimeRemaining;          // 36
    t.EventTimeRemaining = raf.ReadFloat(36)
    '  f32   sPersonalFastestLapTime;      // 40
    t.PersonalFastestLapTime = raf.ReadFloat(40)
    '  f32   sWorldFastestLapTime;         // 44
    t.WorldFastestLapTime = raf.ReadFloat(44)
    '  f32   sCurrentSector1Time;          // 48
    t.CurrentSector1Time = raf.ReadFloat(48)
    '  f32   sCurrentSector2Time;          // 52
    t.CurrentSector2Time = raf.ReadFloat(52)
    '  f32   sCurrentSector3Time;          // 56
    t.CurrentSector3Time = raf.ReadFloat(56)
    '  f32   sFastestSector1Time;          // 60
    t.FastestSector1Time = raf.ReadFloat(60)
    '  f32   sFastestSector2Time;          // 64
    t.FastestSector2Time = raf.ReadFloat(64)
    '  f32   sFastestSector3Time;          // 68
    t.FastestSector3Time = raf.ReadFloat(68)
    '  f32   sPersonalFastestSector1Time;  // 72
    t.PersonalFastestSector1Time = raf.ReadFloat(72)
    '  f32   sPersonalFastestSector2Time;  // 76
    t.PersonalFastestSector2Time = raf.ReadFloat(76)
    '  f32   sPersonalFastestSector3Time;  // 80
    t.PersonalFastestSector3Time = raf.ReadFloat(80)
    '  f32   sWorldFastestSector1Time;     // 84
    t.WorldFastestSector1Time = raf.ReadFloat(84)
    '  f32   sWorldFastestSector2Time;     // 88
    t.WorldFastestSector2Time = raf.ReadFloat(88)
    '  f32   sWorldFastestSector3Time;     // 92
    t.WorldFastestSector3Time = raf.ReadFloat(92)
    '
    '  u16   sJoyPad;                      // 96
    t.JoyPad = raf.ReadShort(96)
    '
    '  // Flags
    '  u8    sHighestFlag;                 // 98
    t.HighestFlag = raf.ReadUnsignedByte(98)
    '
    '  // Pit info
    '  u8    sPitModeSchedule;             // 99
    t.PitModeSchedule = raf.ReadUnsignedByte(99)
    '
    '  // Car state
    '  s16   sOilTempCelsius;              // 100
    t.OilTempCelsius = raf.ReadShort(100)
    '  u16   sOilPressureKPa;              // 102
    t.OilPressureKPa = raf.ReadShort(102)
    '  s16   sWaterTempCelsius;            // 104
    t.WaterTempCelsius = raf.ReadShort(104)
    '  u16   sWaterPressureKpa;            // 106
    t.WaterPressureKpa = raf.ReadShort(106)
    '  u16   sFuelPressureKpa;             // 108
    t.FuelPressureKpa = raf.ReadShort(108)
    '  u8    sCarFlags;                    // 110
    t.CarFlags = raf.ReadUnsignedByte(110)
    '  u8    sFuelCapacity;                // 111
    t.FuelCapacity = raf.ReadUnsignedByte(111)
    '  u8    sBrake;                       // 112
    t.Brake = raf.ReadUnsignedByte(112)
    '  u8    sThrottle;                    // 113
    t.Throttle = raf.ReadUnsignedByte(113)
    '  u8    sClutch;                      // 114
    t.Clutch = raf.ReadUnsignedByte(114)
    '  s8    sSteering;                    // 115
    t.Steering = raf.ReadUnsignedByte(115)
    '  f32   sFuelLevel;                   // 116
    t.FuelLevel = raf.ReadFloat(116)
    '  f32   sSpeed;                       // 120
    t.Speed = raf.ReadFloat(120)
    '  u16   sRpm;                         // 124
    t.RPM = raf.ReadShort(124)
    '  u16   sMaxRpm;                      // 126
    t.MaxRPM = raf.ReadShort(126)
    '  u8    sGearNumGears;                // 128
    t.GearNumGears = raf.ReadUnsignedByte(128)
    '  u8    sBoostAmount;                 // 129
    t.BoostAmount = raf.ReadUnsignedByte(129)
    '  s8    sEnforcedPitStopLap;          // 130
    t.EnforcedPitstopLap = raf.ReadSignedByte(130)
    '  u8    sCrashState;                  // 131
    t.CrashState = raf.ReadUnsignedByte(131)
    '
    '  f32   sOdometerKM;                  // 132
    t.OdometerKM = raf.ReadFloat(132)
    '  f32   sOrientation[3];              // 136
    t.Orientation(0) = raf.ReadFloat(136)
    t.Orientation(1) = raf.ReadFloat(140)
    t.Orientation(2) = raf.ReadFloat(144)
    '  f32   sLocalVelocity[3];            // 148
    t.LocalVelocity(0) = raf.ReadFloat(148)
    t.LocalVelocity(1) = raf.ReadFloat(152)
    t.LocalVelocity(2) = raf.ReadFloat(156)
    '  f32   sWorldVelocity[3];            // 160
    t.WorldVelocity(0) = raf.ReadFloat(160)
    t.WorldVelocity(1) = raf.ReadFloat(164)
    t.WorldVelocity(2) = raf.ReadFloat(168)
    '  f32   sAngularVelocity[3];          // 172
    t.AngularVelocity(0) = raf.ReadFloat(172)
    t.AngularVelocity(1) = raf.ReadFloat(176)
    t.AngularVelocity(2) = raf.ReadFloat(180)
    '  f32   sLocalAcceleration[3];        // 184
    t.LocalAcceleration(0) = raf.ReadFloat(184)
    t.LocalAcceleration(1) = raf.ReadFloat(188)
    t.LocalAcceleration(2) = raf.ReadFloat(192)
    '  f32   sWorldAcceleration[3];        // 196
    t.WorldAcceleration(0) = raf.ReadFloat(196)
    t.WorldAcceleration(1) = raf.ReadFloat(200)
    t.WorldAcceleration(2) = raf.ReadFloat(204)
    '  f32   sExtentsCentre[3];            // 208
    t.ExtentsCentre(0) = raf.ReadFloat(208)
    t.ExtentsCentre(1) = raf.ReadFloat(212)
    t.ExtentsCentre(2) = raf.ReadFloat(216)
    '
    '  // Wheels / Tyres
    '  u8    sTyreFlags[4];                // 220
    t.TyreFlags(0) = raf.ReadUnsignedByte(220)
    t.TyreFlags(1) = raf.ReadUnsignedByte(221)
    t.TyreFlags(2) = raf.ReadUnsignedByte(222)
    t.TyreFlags(3) = raf.ReadUnsignedByte(223)
    '  u8    sTerrain[4];                  // 224
    t.Terrain(0) = raf.ReadUnsignedByte(224)
    t.Terrain(1) = raf.ReadUnsignedByte(225)
    t.Terrain(2) = raf.ReadUnsignedByte(226)
    t.Terrain(3) = raf.ReadUnsignedByte(227)
    '  f32   sTyreY[4];                    // 228
    t.TyreY(0) = raf.ReadFloat(228)
    t.TyreY(1) = raf.ReadFloat(232)
    t.TyreY(2) = raf.ReadFloat(236)
    t.TyreY(3) = raf.ReadFloat(240)

    '  f32   sTyreRPS[4];                  // 244
    t.TyreRPS(0) = raf.ReadFloat(244)
    t.TyreRPS(1) = raf.ReadFloat(248)
    t.TyreRPS(2) = raf.ReadFloat(252)
    t.TyreRPS(3) = raf.ReadFloat(256)
    '  f32   sTyreSlipSpeed[4];            // 260
    t.TyreSlipSpeed(0) = raf.ReadFloat(260)
    t.TyreSlipSpeed(1) = raf.ReadFloat(264)
    t.TyreSlipSpeed(2) = raf.ReadFloat(268)
    t.TyreSlipSpeed(3) = raf.ReadFloat(272)
    '  u8    sTyreTemp[4];                 // 276
    t.TyreTemp(0) = raf.ReadUnsignedByte(276)
    t.TyreTemp(1) = raf.ReadUnsignedByte(277)
    t.TyreTemp(2) = raf.ReadUnsignedByte(278)
    t.TyreTemp(3) = raf.ReadUnsignedByte(279)
    '  u8    sTyreGrip[4];                 // 280
    t.TyreGrip(0) = raf.ReadUnsignedByte(280)
    t.TyreGrip(1) = raf.ReadUnsignedByte(281)
    t.TyreGrip(2) = raf.ReadUnsignedByte(282)
    t.TyreGrip(3) = raf.ReadUnsignedByte(283)
    '  f32   sTyreHeightAboveGround[4];    // 284
    t.TyreHeightAboveGround(0) = raf.ReadFloat(284)
    t.TyreHeightAboveGround(1) = raf.ReadFloat(288)
    t.TyreHeightAboveGround(2) = raf.ReadFloat(292)
    t.TyreHeightAboveGround(3) = raf.ReadFloat(296)
    '  f32   sTyreLateralStiffness[4];     // 300
    t.TyreLateralStiffness(0) = raf.ReadFloat(300)
    t.TyreLateralStiffness(1) = raf.ReadFloat(304)
    t.TyreLateralStiffness(2) = raf.ReadFloat(308)
    t.TyreLateralStiffness(3) = raf.ReadFloat(312)
    '  u8    sTyreWear[4];                 // 316
    t.TyreWear(0) = raf.ReadUnsignedByte(316)
    t.TyreWear(1) = raf.ReadUnsignedByte(317)
    t.TyreWear(2) = raf.ReadUnsignedByte(318)
    t.TyreWear(3) = raf.ReadUnsignedByte(319)
    '  u8    sBrakeDamage[4];              // 320
    t.BrakeDamage(0) = raf.ReadUnsignedByte(320)
    t.BrakeDamage(1) = raf.ReadUnsignedByte(321)
    t.BrakeDamage(2) = raf.ReadUnsignedByte(322)
    t.BrakeDamage(3) = raf.ReadUnsignedByte(323)
    '  u8    sSuspensionDamage[4];         // 324
    t.SuspensionDamage(0) = raf.ReadUnsignedByte(324)
    t.SuspensionDamage(1) = raf.ReadUnsignedByte(325)
    t.SuspensionDamage(2) = raf.ReadUnsignedByte(326)
    t.SuspensionDamage(3) = raf.ReadUnsignedByte(327)
    '  s16   sBrakeTempCelsius[4];         // 328
    t.BrakeTempCelsius(0) = raf.ReadShort(328)
    t.BrakeTempCelsius(1) = raf.ReadShort(330)
    t.BrakeTempCelsius(2) = raf.ReadShort(332)
    t.BrakeTempCelsius(3) = raf.ReadShort(334)
    '  u16   sTyreTreadTemp[4];            // 336
    t.TyreTreadTemp(0) = raf.ReadShort(336)
    t.TyreTreadTemp(1) = raf.ReadShort(338)
    t.TyreTreadTemp(2) = raf.ReadShort(340)
    t.TyreTreadTemp(3) = raf.ReadShort(342)
    '  u16   sTyreLayerTemp[4];            // 344
    t.TyreLayerTemp(0) = raf.ReadShort(344)
    t.TyreLayerTemp(1) = raf.ReadShort(346)
    t.TyreLayerTemp(2) = raf.ReadShort(348)
    t.TyreLayerTemp(3) = raf.ReadShort(350)
    '  u16   sTyreCarcassTemp[4];          // 352
    t.TyreCarCassTemp(0) = raf.ReadShort(352)
    t.TyreCarCassTemp(1) = raf.ReadShort(354)
    t.TyreCarCassTemp(2) = raf.ReadShort(356)
    t.TyreCarCassTemp(3) = raf.ReadShort(358)
    '  u16   sTyreRimTemp[4];              // 360
    t.TyreRimTemp(0) = raf.ReadShort(360)
    t.TyreRimTemp(1) = raf.ReadShort(362)
    t.TyreRimTemp(2) = raf.ReadShort(364)
    t.TyreRimTemp(3) = raf.ReadShort(366)
    '  u16   sTyreInternalAirTemp[4];      // 368
    t.TyreInternalAirTemp(0) = raf.ReadShort(368)
    t.TyreInternalAirTemp(1) = raf.ReadShort(370)
    t.TyreInternalAirTemp(2) = raf.ReadShort(372)
    t.TyreInternalAirTemp(3) = raf.ReadShort(374)
    '  f32   sWheelLocalPositionY[4];      // 376
    't.WheelLocalPositionY(0) = raf.ReadFloat(376)
    't.WheelLocalPositionY(1) = raf.ReadFloat(380)
    't.WheelLocalPositionY(2) = raf.ReadFloat(384)
    't.WheelLocalPositionY(3) = raf.ReadFloat(388)
    '  f32   sRideHeight[4];               // 392
    t.RideHeight(0) = raf.ReadFloat(392)
    t.RideHeight(1) = raf.ReadFloat(396)
    t.RideHeight(2) = raf.ReadFloat(400)
    t.RideHeight(3) = raf.ReadFloat(404)
    '  f32   sSuspensionTravel[4];         // 408
    t.SuspensionTravel(0) = raf.ReadFloat(408)
    t.SuspensionTravel(1) = raf.ReadFloat(412)
    t.SuspensionTravel(2) = raf.ReadFloat(416)
    t.SuspensionTravel(3) = raf.ReadFloat(420)
    '  f32   sSuspensionVelocity[4];       // 424
    t.SuspensionVelocity(0) = raf.ReadFloat(424)
    t.SuspensionVelocity(1) = raf.ReadFloat(428)
    t.SuspensionVelocity(2) = raf.ReadFloat(432)
    t.SuspensionVelocity(3) = raf.ReadFloat(436)
    '  u16   sAirPressure[4];              // 440
    t.AirPressure(0) = raf.ReadShort(440)
    t.AirPressure(1) = raf.ReadShort(442)
    t.AirPressure(2) = raf.ReadShort(444)
    t.AirPressure(3) = raf.ReadShort(446)
    '
    '  // Extras
    '  f32   sEngineSpeed;                 // 448
    t.EngineSpeed = raf.ReadFloat(448)
    '  f32   sEngineTorque;                // 452
    t.EngineTorque = raf.ReadFloat(452)
    '
    '  // Car damage
    '  u8    sAeroDamage;                  // 456
    t.AeroDamage = raf.ReadUnsignedByte(456)
    '  u8    sEngineDamage;                // 457
    t.EngineDamage = raf.ReadUnsignedByte(457)
    '
    '  // Weather
    '  s8    sAmbientTemperature;          // 458
    t.AmbientTemperature = raf.ReadSignedByte(458)
    '  s8    sTrackTemperature;            // 459
    t.TrackTemperature = raf.ReadSignedByte(459)
    '  u8    sRainDensity;                 // 460
    t.RainDensity = raf.ReadUnSignedByte(460)
    '  s8    sWindSpeed;                   // 461
    t.WindSpeed = raf.ReadSignedByte(461)
    '  s8    sWindDirectionX;              // 462
    t.WindDirectionX = raf.ReadSignedByte(462)
    '  s8    sWindDirectionY;              // 463
    t.WindDirectionY = raf.ReadSignedByte(463)
    '
    Dim driverpos(56) As ParticipantInfo
    For i = 0 To 55
        'Log("pos "&(464+(i*16)))
        'Log(raf.ReadsignedByte(464))
        'If  raf.ReadsignedByte(464) <> 0 Then
            Dim driver As ParticipantInfo
            driver.Initialize
            driver.WorldPosition(0) = raf.ReadShort(464+(i*16))
            driver.WorldPosition(1) = raf.ReadShort(466+(i*16))
            driver.WorldPosition(2) = raf.ReadShort(468+(i*16))
            driver.CurrentLapDistance = raf.ReadShort(470+(i*16))
            driver.RacePosition = raf.ReadUnsignedByte(472+(i*16))
            driver.LapsCompleted = raf.ReadUnsignedByte(473+(i*16))
            driver.CurrentLap = raf.ReadUnsignedByte(474+(i*16))
            driver.Sector = raf.ReadUnsignedByte(475+(i*16))
            driver.LastSectorTime = raf.ReadFloat(476+(i*16))
            driverpos(i) = driver       
        'End If
    Next
    t.Driver = driverpos
    '  sParticipantInfo sParticipantInfo[56];  // 464
    '                                      // 56*16=896
    '  f32   sTrackLength;                 // 1360
    t.TrackLength = raf.ReadFloat(1360)
    '  u8    sWings[2];                    // 1364
    t.Wings(0) = raf.ReadUnsignedByte(1364)
    t.Wings(1) = raf.ReadUnsignedByte(1365)
    '  u8    sDPad;                        // 1366               
    t.DPad = raf.ReadUnsignedByte(1366)
    '                                      // 1368    struct Is padded To
    '};

   


   Return t
End Sub
Private Sub ReadString(raf As RandomAccessFile, buffer() As Byte) As String
   raf.ReadBytes(buffer, 0, buffer.Length, raf.CurrentPosition)
   Return BytesToString(buffer, 0, buffer.Length, "utf8")
End Sub
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Nice work, have you noticed more effort goes into games related programming than 'normal' applications lol.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…