Replay file structure

knackko

Hi,

I would like to make some C/C++ stuff with .vcr replay file, I saw on rfactor.net dev corner the replay format description but it will cost a lot of time to do .h file with this and i am sure that someone ever do this, so my question is : is there anybody who coded .h file of replay format description? I think so as rF VCR merge exists.

Thanks :cool:
 
I've played with VCR files a bit. I could post some information but I'm not sure if ISI is ok with that.
 
Thanks for reply,
ISI gives the structure so I think that's ok with that, don't you think?
Otherwise, you can send me a mp, it should be nice !
 
Thanks for clarifying :)

Well' I don't have any .h file, but here's what I know so far

File starts with this:

std::string comment; // string varies in length. It's terminated with 0x0A character in file
char unknown1[8];
unsigned long rfmFileNameLength;
char* rfmFileName; //varies in length (given above)
unsigned long unknownStringLength1;
char* unknownString1; //not sure if' there is any string at all here. I got unknownString = 0 in replays I've tested so far
unsigned long scnFileNameLength;
char* scnFileName;
unsigned long aiwFileNameLength;
char* aiwFileName;
unsigned long unknown2;
unsigned long playerCount;

Now comes player list, each player described by

unsigned char slotID;
unsigned char driverNameLength;
char* driverName;
unsigned char coDriverNameLength;
char* coDriverName;
char vehicleName[32];
char skinFile[32];
unsigned char upgradePack[8];
float entryTime;
float exitTime;

Now there are 36 bytes I Ignore. I gess there is some kind of event count here and other stuff. I just read events until I hit the end of file :)

After these 36 bytes comes the event list. They're packed in groups. Each group has a timestamp and a list of events that occured at that time.

float timestamp;
unsigned char eventCount;
unsigned char unknown1; //or is eventCount a 16-bit value?

Now events in this group:

unsigned long eventHeader;
unsigned char eventTimeAdjustment;

Now you can use GetClass, GetFlag, GetType and GetSize functions from header given by ISI.

If your application recognizes the event, it can read it, if not it can skip next GetSize() bytes and read next event in group.

Here's partial info on one of events (class = ECLASS_LOC, type = ETYPE_ZIPLOC_1 ... ETYPE_ZIPLOC_7)

unsigned long mInfo1;
unsigned long mInfo2;
unsigned char unk1[18];
float posX; // position of the car
float posY;
float posZ;
float angX; // orientation of the car
float angY;
float angZ;

Now, from mInfo1 you can extract some things:

int rps = mInfo1 >> 18; // engine rpm?
int thr = (mInfo1 >> 12) & 0x01f; // throttle pedal 0...31
int brk = (mInfo1 & 0x0800) ? 1 : 0; // brake lights
int ste = (mInfo1 & 0x07f) - 64; //steering wheel position -64...+63
int acc = mInfo2 >> 24; // sorry, can't remember what it was :)

There's more stuff in mInfo2 and in these 18 bytes I marked as unknown. Probably suspension positions, angular and linear velocity of the car, maybe brake glow. If someone has time to figure it out, and perhas info on format of other events, he can post it here.


Of course remember to unzip .vcr file first if it's compressed :)
 
Yes, the biggest catch was that events are grouped. Until I found that out from guy who wrote RFVCRMerge I was totally stuck.

Ziploc event has around 50 bytes, so that unknown part is 18 bytes long, not 18-bits.

As for player reference in event - try looking for it in mInfo1, mInfo2 and these 18 unknown bytes. It seems obvious it must be there.
 
I already send a mail to RFVCRMerge guy but he did not answer me, I will try new.

before cars pos, I have try to extract headers to begin with code :)
 
I'm also interested for extract all drivers/times to xml file. I'm also sent email to RFVCRMerge autor but no response :( .

If anybody can help me or i can help he in this project email me. I'm programmer in .net but c++ isn't common for me.

I'm need extract all content to xml as log structure. ;)

My web extract and import all laps from xml log but always this haven't all data :(
 
Last edited:
Replay file may not be a good idea to get lap times since it doesn't contain that kind of information.
You would have to analyse replay and try to measure lap times - that would be a bit complex (you would have to know where start/finish line is etc.) and inaccurate.

To export lap times you need a plugin. You can download example plugins (source code) from main rFactor website. These export some things. you would only need to re-weire them to export what you want in format you want. And yes, it would require C or C++ programming, since it's a dll file.

However, such plugins exist allready. We have some programmers in our leagues and we use such plugins. Perhaps my friend MaXyM could point you in the right direction :)

Unfortunately, we also have problem with rFactor not giving our plugins all data.
 
but rfVCRmerge contains this information... isn't it?

I'm want this and i'm also know if replay contains laps because my servers always are in continue sesion (param: "Pause While Zero players") it's for dedicated server writes xml log.

i will test with rfactor libraries but if you had a better code would be great being able to prove ;)
 
but rfVCRmerge contains this information... isn't it?

I'm want this and i'm also know if replay contains laps because my servers always are in continue sesion (param: "Pause While Zero players") it's for dedicated server writes xml log.

i will test with rfactor libraries but if you had a better code would be great being able to prove ;)

I've done a plugin to extract laptimes because our servers are "paused while zero player". But output file is something like csv, not xml :), you can see an example here:
http://knackko.com/rfactor/bestlap/bestlaps-101004-213530.log
One line per driver, with track information, mod&car, split and total laptimes, date when laptime where done.
Im not a C/C++ dedicated programmer so i made this as I can ! :)

This plugin check laptimes every 20s ans print output file if new laptime. There is one file per session. This file is upload via ftp to my web server and parsed/analysed with php script (quick and dirty), data are stored on mysql database (only if laptime for driver+car is better than the one already stored). Laptimes are then available on my web server here: http://knackko.com/bestlap/bestlap_query_test.php
 
Last edited:
Yes, the biggest catch was that events are grouped. Until I found that out from guy who wrote RFVCRMerge I was totally stuck.

Ziploc event has around 50 bytes, so that unknown part is 18 bytes long, not 18-bits.

As for player reference in event - try looking for it in mInfo1, mInfo2 and these 18 unknown bytes. It seems obvious it must be there.

So I've been coding yesterday evening, with C++, I am not a dev so it takes times to find good instructions, but I succeed in extracting first headers, now I've some debug to do to extract each driver information. I've got some doubt to succeed on extract all events after ! but I'll try
 
but rfVCRmerge contains this information... isn't it?
Maybe I was mistaken. You can of course calculate lap times from replay, but that wouldn't be a good approach and that was what I meant.
But come to think of it - lap times are probably stored, too - because we see lap time when viewing replay in rfactor. I don't know which event you would have to extract for that, though.

@knackko
don't worry - just follow step-by-step what I described above :)
 
Hi all. I've been referred to a few times in this thread and feel I'm a bit late to this conversation!

The event you are looking for is ECLASS_SYS/ETYPE_CHECKPOINT. It is generated when a car crosses a sector boundary.

The data for the event is:
- 4 bytes float; laptime so far up to the checkpoint
- 4 bytes float; exact time that checkpoint was crossed (can be different to this event's time)
- 1 byte; lap number
- 1 byte; sector id. Strangely this is 0 for sector 1, 64 for sector 2 and 128 for sector 3
I haven't worked out what the remaining data in the event is for, but there can be 11 bytes or 14 bytes for the event in total.

I hope this helps!

And sorry for not answering all of your earlier requests. I hope you can understand that I get a lot of requests and not enough time to answer all of them :eek: . I can answer a specific "Where is the data for ...?" question easier than a general "How do I read VCR files?".
 
Hi Lumpy, it is nice to see your post !
In fact when I asked "how i read VCR files" i did not know how much infos where in a VCR file. Now I know more on it with the help of K Szczech and i have some code to read it. But i am lost in events part, to be more precise, i want to catch every positions points (x,y,z) of each car.
The main goal is to make an input with those data to something like rFactor Cut Detection, because i dont want to detect it during the race (not too much cpu/memory ressources). With both project like rFactor Cut Detection and rfactor live, i think we can have a good solution to detect cut tracking.
 
Remember that this is only from reverse engineering vcr files that I have. Who knows what it does when there are more than 255 laps - maybe something to do with the remaining bytes in the event? It would be interesting to find out. Anyone have such a replay?
 
Remember that this is only from reverse engineering vcr files that I have. Who knows what it does when there are more than 255 laps - maybe something to do with the remaining bytes in the event? It would be interesting to find out. Anyone have such a replay?

I wondered if it was reverse engineering... great work, I think you spent a lot of time on it !
I have no replay with more than 255 laps, sorry.
 
I found that for ECLASS_LOC, type = ETYPE_ZIPLOC_1 ... ETYPE_ZIPLOC_7), posY and posZ are inversed, so it is more:

unsigned long mInfo1;
unsigned long mInfo2;
unsigned char unk1[18];
float posX; // position of the car
float posZ;
float posY;
float angX; // orientation of the car
float angZ;
float angY;

In my code:

float posX=decode_float(ptr,length); // position of the car
float posZ=decode_float(ptr,length);
float posY=decode_float(ptr,length);
float angX=decode_float(ptr,length); // orientation of the car
float angZ=decode_float(ptr,length);
float angY=decode_float(ptr,length);

float posX=decode_float(ptr,length); // position of the car
float posZ=decode_float(ptr,length);
float posY=decode_float(ptr,length);

No?
 
Could be. Doesn't matter - just use whatever works :)

Whatever coordinate system I'll find in a file, I just convert it to what I prefer (I use OpenGL-like system, since I program in OpenGL).
 
I wondered if it was reverse engineering... great work, I think you spent a lot of time on it !
Thanks - I did! :D

The replay file format is provided to the public.
This is not entirely true. Bits of it are, and the ISI developers are willing help if you ask the right question. But, to the best of my knowledge, this thread is now the most detailed practical public description of the format available.
 
Yes it is a nice thread ! it is nice to know how works this file.
Do you have ISI dev contacts? I want to ask them if replay files contains tire locations and why all those ETYPE_ZIPLOC and ETYPE_SIMPLELOC...
 
I have yet to see a SIMPLELOC in the wild so I suspect this is used for client/server comms rather than the VCR file itself. The reason for the different ZIPLOC event types; the current gear is encoded in the type ;)
 
Ohh Nices answers!!!

follow it!

@knackko:
You may share these libraries? if it included the source code would be great to get me any more information to use;)
 
The reason for the different ZIPLOC event types; the current gear is encoded in the type ;)

Hahaha, good thinking there, Lumpy :)
It eluded me completely that ziploc has 1-7, N and R versions. I guess that means I'm no longer oldschool programmer and just an object-oriented one now. Back in 90's, when I did lots of assembler programming, I would surely notice that :D
 
Ohh Nices answers!!!

follow it!

@knackko:
You may share these libraries? if it included the source code would be great to get me any more information to use;)

Yes it is possible. Sorry for this late anwser but I didn't have much time to dev this week.
 
Hello,
I try to find the speed of the car in the ZIP loc segment. I see a source code taking 3 short as vx, vy, vz (from offset 16, 18 and 20). But this data give me totally heratic curve (so it seem this is not the good data)

I try to find some short in the 18 unknown byte (like describe in the previous posts), and i found something that can have the same behaviour (curve) as the speed, but in a inverted form (i need to use 1/value to take the speed, and this speed seems to be the algebra speed and not one of the 3 coordinate x,y,z)

So i found someting using the short at offset 8 or a short at offset 10. But can't be sure the speed is really in one of those short, and don't know why i need to use 1/value.

If someone know where to find the car speed i will be very interrested.
Thank in adsvance
 

Back
Top