whitepeak.org

i-Magic VR File Format

As with the Fortius files, whenever fields have units associated with them, such as weight, distance etc., the Tacx software stores the SI unit any only converts to the Imperial system for display purposes.

Single byte characters (ASCII) are used throughout.

An .im file contains the following data blocks.

  1. Course information.
  2. Wind information (not always present).
  3. Course data.
  4. Ride information.
  5. Lap times.
  6. Scale factor data.
  7. Ride data (including cooling down data if present)

The i-Magic .im file format is not as straighforward as the Fortius layouts. In particular the position of the wind, lap and scale factor parts of the file is confusing. Although some of the information I've gained (for example the 'Course data offset' field in the Course Information Block) can help to locate certain sections, in any software I've written to read the .im files I have used the following approach.

  1. Read the Course Information Block (572 bytes).
  2. Seek to a position in the file of 572 + course record count * 34.
  3. Search for an occurance of the course name.
  4. The start of the Ride Information Block is the location of this string minus 4.
  5. The start of the Ride Data Block is size of file - (ride record count + 1) * 34. (Don't forget to allow for the cool-down data if there is any.)
  6. If the location of the Course Data Block is not 572 then the Wind Information Block is present.

This is more straightforward than it sounds! If anyone has a better solution please let me know.

Course Information Block

 

Field Offset Size .NET type Comments
Unknown 0 4   always 01 00 00 00?
Course name 4 260 Char[] 1 byte char
Terrain 264 260 Char[] 1 byte char
Year course created 524 2 UInt16
Month course created 526 2 UInt16
Day of week course created 528 2 UInt16
Day of month course created 530 2 UInt16
Hour of course creation 532 2 UInt16
Minute of course creation 534 2 UInt16
Seconds of course creation 536 2 UInt16
Unknown 538 6  
Course data offset 544 4 UInt32 24 = wind block present
Number of course data records 548 4 UInt32
Unknown 552 4  
Course length (km) 556 4 Single
Unknown 560 4  
Number of laps 564 4 UInt32
Unknown 568 4  
Total 572

Wind Information Block

This block is only present if the course data offset field in the course information block is 24 (the size of this block).

Field Offset Size .NET type Comments
Unknown 0 4  
Strength 4 4 Single 0 = none, 0.375 = low, 0.625 = medium, 1.0 = high
Direction 8 4 Single -90 = west, 0 = north, 90 = east, 180 = south, -180 = south
Unknown 12 12  
Total 24

Sometimes the wind information block is present but contains spurious values - this does not necessarily mean the file is corrupt.

It may be that in addition to this block being present there is another indicator of wind elsewhere in the file. In any event, it's best to check whether the direction and strength fields above are sensible before deciding whether the course does indeed have any wind.

Course Data Block

 

Field Offset Size .NET type Comments
x coordinate 0 4 Single
y coordinate 4 4 Single
z coordinate 8 4 Single
Unknown 12 22  
Total 34

Ride Information Block

 

Field Offset Size .NET type Comments
Unknown 0 4   always 01 00 00 00?
Course name 4 260 Char[] 1 byte char
Terrain 264 260 Char[] 1 byte char
Year of ride 524 2 UInt16
Month of ride 526 2 UInt16
Day of week 528 2 UInt16
Date of ride 530 2 UInt16
Time of ride (hours) 532 2 UInt16
Time of ride (mins) 534 2 UInt16
Time of ride (secs) 536 2 UInt16
Unknown 538 10  
Number of ride data records 548 4 UInt32
Unknown 552 4  
Ride distance (km) 556 4 Single This includes any cooldown
Ride duration (seconds) 560 4 Single This does not include any cooldown
Team name 564 20 Char[] 1 byte char
Rider name 584 20 Char[] 1 byte char
Weight of rider (kg) 604 4 Single
Gender 608 1 Byte 0 = male, 1 = female
Height of rider (cm) 609 4 Single
Rider year of birth 613 2 Uint16
Unknown 615 2  
Rider month of birth 617 1 Byte
Rider date of birth 618 1 Byte
Rider HR max 619 1 Byte
Rider HR min 620 1 Byte
Rider HR A Threshold 621 1 Byte
HR Zone 1 upper limit 622 1 Byte
HR Zone 2 upper limit 623 1 Byte
HR Zone 3 upper limit 624 1 Byte
HR Zone 4 upper limit 625 1 Byte
HR Zone 5 upper limit 626 1 Byte
Rider email 627 260 Char[]
Rider country 887 256 Char[]
Rider remarks 1143 256 Char[]
Course notes 1399 256 Char[]
Feeling 1655 21 Char[]
Temp 1676 11 Char[]
No. of cool down records 1687 4 Int32
Unknown 1691 6  
No. of laps 1697 4 UInt32
Total 1701

Lap Data Block

This is an array of 4 byte integers, the number of which is given in both the course information block and the ride information block.

Field Offset Size .NET type Comments
Lap time in seconds 0 4 UInt32

Scale Data Block

 

Field Offset Size .NET type Comments
Unknown 0 12  
Scale factor 12 4 Single
Skip field 16 4 Int32 see below
Unknown 20 4  
Total 24

In some run files the skip field has a value of 2; usually it is 0. When this happens there is an extra 8 bytes between this block and the next (the ride data block). This does not occur often - I've seen it only 4 files out of several hundred. I have a suspicion it may be related to crashes but I am not certain.

Like the wind information, the scale factor field can sometimes contain spurious values. In these cases, the Tacx Blue Analyser program just omits the display of the scale factor.

Ride Data Block

The number of ride records is given in the ride information block.

Field Offset Size .NET type Comments
x 0 4 Single
y 4 4 Single
z 8 4 Single
Unknown 12 12  
HR 24 1 Byte
Cadence 25 1 Byte
Power x 10 26 2 UInt16
Speed x 10 28 2 UInt16
Unknown 30 4  
Total 34

Note that any cool down data immediately follows, using the same record layout. The number of cooling down data records is given in the ride information block.