The online racing simulator
parsing .pth with C or VB
(6 posts, started )
parsing .pth with C or VB
Hi!

I think i need some help for parsing the .pth-files.

I originally want to use them in VB6, but don't know how. So I modified a dirty C source from an earlier project to show the values, which are stored in the pth-files. But then the problems began.


#include "stdafx.h"


#include <cstdlib>

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <ctime>

typedef struct {
int centreX; // fp
int centreY; // fp
int centreZ; // fp
float dirX; // float
float dirY; // float
float dirZ; // float
float limit_left; // outer limit
float limit_right; // outer limit
float drive_left; // road limit
float drive_right; // road limit
} LFSpth_node;


typedef struct {
char LFSPTH[6]; // do not read file if no match
char version; // 0 - do not read file if > 0
char revision; // 0 - do not read file if > 0
int num_nodes; // number
int finish_line; // number
LFSpth_node nodes; // NODE BLOCKS
} LFSpth;



/*
num unit offset description
--- ---- ------ -----------
HEADER BLOCK :
6 char 0 LFSPTH : do not read file if no match
1 byte 6 version : 0 - do not read file if > 0
1 byte 7 revision : 0 - do not read file if > 0
1 int 8 num nodes : number
1 int 12 finish line : number
......NODE BLOCKS

NODE BLOCK :
1 int 0 centre X : fp
1 int 4 centre Y : fp
1 int 8 centre Z : fp
1 float 12 dir X : float
1 float 16 dir Y : float
1 float 20 dir Z : float
1 float 24 limit left : outer limit
1 float 28 limit right : outer limit
1 float 32 drive left : road limit
1 float 36 drive right : road limit
*/




using namespace std;

//Vector, which contains the binary Data of Filename in char order
std::vector <unsigned char> input;


int main( int argc, char ** argv)
{
if (argc != 2) {
std::cerr << "usage: " << argv[0] << " file.pth\n";
exit(1);
}
char *Filename = argv[1];

//Temporary buffer
char buffer;
int buffercnt=0;

//Input Stream
std::ifstream filein;

//open Input stream in binary mode
filein.open(Filename,std::ios::binary);

if (!filein)
{
std::cout << "Error opening the file! Aborting...\n";
exit(1);
}

//Read file and fill buffer until EndOfFile
while (!filein.eof()) {

//read char
filein.get(buffer);
//insert char
input.push_back(buffer);

}
//close file
filein.close();

int offset=16;


char version=input[6];
char revision=input[7];
int num_nodes=input[8];
int finish_line=input[12];

std::string name;


std::cout << "Type:\t\t" << char(input[0]) << char(input[1]) << char(input[2]) << char(input[3]) << char(input[4]) << char(input[5]) << std::endl;
std::cout << "Version:\t" << int(version) << std::endl;
std::cout << "Revision:\t" << int(revision) << std::endl;
std::cout << "Nodes:\t\t" << int(num_nodes) << std::endl;
std::cout << "Finish Line:\t" << int(finish_line) << std::endl << std::endl;


for (int satz = 1; satz <= num_nodes; satz++) {

std::cout << "Node:\t\t\t" << satz << std::endl;

std::cout << "centre X:\t\t" << int(input[offset]) << std::endl;
std::cout << "centre Y:\t\t" << int(input[offset+4]) << std::endl;
std::cout << "centre Z:\t\t" << int(input[offset+8]) << std::endl;


float dirX = input[offset+12] << 24;
dirX += input[offset+13] << 16;
dirX += input[offset+14] << 8;
dirX += input[offset+15] ;

float dirY = input[offset+16];
dirY += input[offset+17] << 8;
dirY += input[offset+18] << 16;
dirY += input[offset+19] << 24;

float dirZ = input[offset+20];
dirZ += input[offset+21] << 8;
dirZ += input[offset+22] << 16;
dirZ += input[offset+23] << 24;

std::cout << "dir X:\t\t\t" << dirX << std::endl;
std::cout << "dir Y:\t\t\t" << dirY << std::endl;
std::cout << "dir Z:\t\t\t" << dirZ << std::endl;

std::cout << "limit left:\t\t" << float(input[offset+24]) << std::endl;
std::cout << "limit right:\t\t" << float(input[offset+28]) << std::endl;

std::cout << "drive left:\t\t" << float(input[offset+32]) << std::endl;
std::cout << "drive right:\t\t" << float(input[offset+36]) << std::endl << std::endl;


offset+=40;
}

return EXIT_SUCCESS;
}


I don't think, the float values are right. But i have no idea how to read them correctly. Is it right, that the "z direction" in BL1.pth is always zero?

I'll be very happy, if someone could show me a hint, how to do it.
Perhaps some code snip sets in VB6 or C.

As you see, I'm not very familiar with C or VB6. Years ago I programmed a lot of command line tools in AmigaE and MaxxonBasic, but now i feel like a noob. 8)

BTW: Many thx @RayOK for his VB6 examples.

Ciao... Pascal

PS: Sorry for my bad english.
-
(MonkOnHotTinRoof) DELETED by MonkOnHotTinRoof
i'm no C expert at all, but is
float dirZ = input[offset+20];
dirZ += input[offset+21] << 8;
dirZ += input[offset+22] << 16;
dirZ += input[offset+23] << 24;

the way to read a float?! Kinda doubt it because the 4 bytes in a float have different meanings than the bytes in an int.

reading a float i have done like :
float File_FloatIn (FILE *fp) {
float Float;
byte *f_ptr = (byte *) &Float;
for (int x=0; x<4; x++) f_ptr[x] = fgetc (fp);

//printf ("READ FLOAT: %f\n", Float);

return Float;
}

that way you put all the 4 bytes of a float directly in an actual float without shifting with bits and all that.
Quote from MonkOnHotTinRoof :
replace float dirX = ... with int tmpX = ..., then do
float dirX = *(float*)&tmpX;

that's it. thanks

But i always get dirZ=0 for every node. Perhaps i should check it with a hex editor.
#4 - Stuff
I made an example in VB6 and I also get 0 for every DirZ. Not sure about the path structure but I guess if we both get it, its intended.

Source.. use as you wish
Attached files
pthReader.zip - 6 KB - 181 views
@Victor:
Quote from Victor :Kinda doubt it because the 4 bytes in a float have different meanings than the bytes in an int.

reading a float i have done like :
float File_FloatIn (FILE *fp) {
float Float;
byte *f_ptr = (byte *) &Float;
for (int x=0; x<4; x++) f_ptr[x] = fgetc (fp);

//printf ("READ FLOAT: %f\n", Float);

return Float;
}

that way you put all the 4 bytes of a float directly in an actual float without shifting with bits and all that.

jepp, my shifting was totally bullshit. thx


@Stuff:
Quote from Stuff :I made an example in VB6 and I also get 0 for every DirZ. Not sure about the path structure but I guess if we both get it, its intended.

Source.. use as you wish

:boing:ahhhh...thx. I've also worked on VB6 yesterday and get it working too, but your source looks much nicer and more complete, so I merge it with my next. 8)
I wrote this but never used it for anything so I'm not 100% sure if it is all correct:


<?php 
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

// PTH format header
typedef struct {
    
char            LFSPTH[6];
    
unsigned char    version;
    
unsigned char    revision;
    
int            numNodes;
    
int            finishLine;
PTHHEADER;

// PTH format block
typedef struct {
    
int    cXcYcZ;            // Centre
    
float    dirXdirYdirZ;    // Dir
    
float    limitLeftlimitRight;
    
float    driveLeftdriveRight;
NODEBLOCK;

// PTH file
typedef struct {
    
PTHHEADER header;
    
NODEBLOCK *nodes;
    
bool loaded;
PTHFILE;

#define    fptof(x) (float) x/65536

// Loads a pth file or releases if fname = null
bool loadPTH(PTHFILEpthfchar *fname) {
    
// Release memory if loaded
    
if(pthf->loaded && pthf->nodes != NULL) {
        
delete[] pthf->nodes;
        
pthf->nodes NULL;
        
pthf->loaded false;
    }

    if(!
fname)
        return 
false;

    
// Open file
    
FILE *fopen(fname"rb");
    if(!
f)
        return 
false;

    
// Load header
    
fread(&pthf->headersizeof(PTHHEADER), 1f);
    if(
strcmp(pthf->header.LFSPTH"LFSPTH")) {
        
// Not a pth file? TODO: add more checking here (file size etc.)
        
fclose(f);
        return 
false;
    }

    
// Allocate memory & load nodes
    
pthf->nodes = new NODEBLOCK[pthf->header.numNodes];
    for(
int i=0;i<pthf->header.numNodes;i++)
        
fread(&pthf->nodes[i], sizeof(NODEBLOCK), 1f);

    
pthf->loaded true;
    
fclose(f);
    return 
true;
}

void main(void) {
    
PTHFILE pthf;
    
pthf.loaded false;

    if(!
loadPTH(&pthf"FE1.pth")) {
        
printf("Cant load PTH\n");
        return;
    }

    
printf("PTH loaded, numnodes: %d, finishline: %d\n"pthf.header.numNodespthf.header.finishLine);
    for(
int i=0;i<pthf.header.numNodes;i++) {
        
NODEBLOCK= &pthf.nodes[i];
        
printf(" - node %04d: c(%.2f %.2f %.2f) dir(%.2f %.2f %.2f)\n"ifptof(n->cX), fptof(n->cY), fptof(n->cZ), n->dirXn->dirYn->dirZ);
        
printf("              limit(%.2f %.2f) drive(%.2f %.2f)\n"n->limitLeftn->limitRightn->driveLeftn->driveRight);
    }

    
// Release memory
    
loadPTH(&pthfNULL);
}
?>


parsing .pth with C or VB
(6 posts, started )
FGED GREDG RDFGDR GSFDG