Recorder File Format for GSEOS 5.1 or earlier
Previous  Top  Next

Note
The recoder file format has changed with version 5.2. We now use an enhanced format that allows indexing and compression during recording, therefore there is no simple access from an API level. However, the tool RecExport can dump all recorder files to a flat ASCII or binary file.
The format bescribed below is for GSEOS versions < 5.2.

The GSEOS Recorder can record the data blocks defined in the block definition file (*.blk file). The data blocks contained in the binary recorder files can pe accessed via a simple filter. The following description shows how to make the GSEOS Recorder data available for further evaluation by writing a specific filter.

The files consist of three different record types: File Header, Block Header and Block Body.

Every file starts with a File Header that allows you to check whether this file is a GSEOS Recoder file for your project. It has only one single file header.
Every GSEOS Recorder file may contain different block types. The first time a specific block is recorded in that file a Block Header is written. It contains some block specific data like the block name. The Block Header is followed by one or more Block Bodies, which contain the data. The next time a data block of that type is recorded only the Block Body is written to the file. This means that there is always exactly one Block Header and one or more Block Bodies for a block type in the recorder file. The following picture shows a possible structure of File Header, Block Headers and Block Bodies:

File Header   
Block Header for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Header for Block "HK1"   
Block Body for Block "HK1"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "HK1"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Header for Block "HK2"   
Block Body for Block "HK2"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "HK1"   
Block Body for Block "HK2"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   
Block Body for Block "EDB"   

The layout of the FileHeader, Block Header and Block Body structures is as follows:

1.File Header  

Name
Size
Contents
Description

byID[5]
5
0xEB 0x90 "GSE"
Unique identification

wVersion
2
0x0100
Version of recorder format

szProjectName[19]
19
Name of Project (zero terminated)
Identification of project

dwTime
4
Time in seconds since Jan/01/70 00:00:00
File creation time

dwNull
4
0
Spare

         

2.Block Header  

Name
Size
Contents
Description

wID
2
"DE"
Block Header identification

wBlockID
2
File local block ID
Link to block bodies

szName[32]
32
Name of data block (zero terminated)
Name of data block

dwLen
4
40
Length of this structure

   

3.Block Body  

Name
Size
Contents
Description

wID
2
"TA"
Block Body identification

wBlockID
2
File local block ID (link to header)
Link to block header

dwStamp
4
Stamp number
The stamp number must be consecutive for each block type

dwSize
4
Size of data area in bytes


dwTime
4
Reception time in seconds since Jan/01/70 00:00:00.


abyData
dwSize
data bytes
Block data

dwLen
4
wSize+20
Length of this structure









The following source code is a sample on how to parse the recorder data:

/*****************************************************************************/
/*                                                                           */
/*  DUMPDAT32.CPP                                                            */
/*  Dumps the recorder contents of GSEOS recorder files for GSEOS 4.0 and    */
/*  higher.                                                                  */
/*                                                                           */
/*  Copyright (C) 1997-1999, GSE Software, Inc.                              */
/*  Author: Thomas Hauck   (th)                                              */
/*                                                                           */
/*  History:                                                                 */
/*  Feb-10-1999 th V 2.0 Adapted to new 32-bit structures.                   */
/*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <dir.h>
#include <dos.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>

#define MAX_FILES   700
#define MAX_BLOCKS  400
#define MAX_ERRORS  100

#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long

#define BOOL  int
#define TRUE  1
#define FALSE 0


#define        BLOCKNAME_LEN  32        // length of blockname

typedef struct DATABLOCK
               {
                 DWORD dwLastStamp ;
                 int   iBlockID ;
                 char  szName[BLOCKNAME_LEN] ;
               } DATABLOCK ;

typedef struct DATAFILE
               {
                 char szName[16] ;
                 DWORD dwTime ;
               } DATAFILE ;

typedef struct FILEHEADER
               {
                 BYTE byID[5];
                 WORD wVersion;
                 char szProjectName[19];
                 DWORD dwTime;
                 DWORD dwNULL;
               } FILEHEADER ;

typedef struct BLOCKHEADER
               {
                 WORD  wID;
                 WORD  wBlockID;
                 char  szName[BLOCKNAME_LEN];
                 DWORD dwLen;

               } BLOCKHEADER ;

typedef struct BLOCKBODY
               {
                 WORD  wID;
                 WORD  wBlockID;
                 DWORD dwStamp;
                 DWORD dwSize;
                 DWORD dwTime;
               } BLOCKBODY ;


static BLOCKHEADER sBlkHdr ;
static BLOCKBODY   sBlkBody ;
static FILEHEADER  sFileHdr ;

static DATABLOCK sBlock[MAX_BLOCKS] ;
static WORD wBlockCount = 0;

static DATAFILE sFile[MAX_FILES] ;
static int iFileCount = 0 ;

static BYTE abyBuffer[0x20000] ;

int fCompTime(DATAFILE * p1, DATAFILE * p2)
{
  if (p1->dwTime < p2->dwTime)
    return -1 ;
  else if (p1->dwTime == p2->dwTime)
    return 0 ;
  else
    return 1 ;
}

int main(int argc, char * argv[])
{
  BOOL bWriteDirectory;

  BYTE abyID[2] ;

  int i,j,
      iDone,
      iErrCount = 0,
      iBlockNumber,
      iFirstArg;

  char szPath[64],
       szFileMask[64],
       szFileName[64],
       szProjectName[64] ;

  DWORD dwLen;

  struct ffblk ffblk ;

  FILE * pFile ;


  bWriteDirectory = FALSE ;

  iFirstArg = 1 ;

  while ((iFirstArg < argc) && (argv[iFirstArg][0] == '-'))
  {
    switch(argv[iFirstArg][1])
    {
      case 'l' : bWriteDirectory = TRUE ;
                 break ;

      default  : printf("Wrong option switch : %s\n",argv[iFirstArg]) ;
                 exit(-1) ;
    }
    iFirstArg++ ;
  }

  if (argc-iFirstArg != 2)
  {
    printf("usage :\n") ;
    printf("dumpdat32 [switches] path projectname\n\n") ;
    printf("This program dumps GSEOS 4.0 data files from the specified path\n") ;
    printf("to standard output.\n") ;
    return -1 ;
  }


  strcpy(szProjectName,argv[iFirstArg+1]) ;
  strcpy(szPath,argv[iFirstArg+0]) ;
  if (strlen(szPath))
  {
    if (szPath[strlen(szPath)-1] != '\\')
      strcat(szPath,"\\") ;
  }

  strcat(strcpy(szFileMask,szPath),"*.*") ;

  /* ----------------------------------------------------------------------
     Build list of data files and sort them by file
     ---------------------------------------------------------------------- */

  iDone = findfirst(szFileMask,&ffblk,0) ;

  while (!iDone)
  {
    fprintf(stderr,"\r%13s ...",ffblk.ff_name) ;

    /* ------------------------------------
       open the file and read the header
       ------------------------------------ */

    strcat(strcpy(szFileName,szPath),ffblk.ff_name) ;

    pFile = fopen(szFileName,"r+b") ;

    if (!pFile)
    {
      fprintf(stderr,"\n Error : '%s' could not be opended.\n",szFileName) ;
      exit(-1) ;
    }
    else
    {
      if (fread(&sFileHdr,sizeof(sFileHdr),1,pFile) != 1)
      {
        fprintf(stderr,"\n Warning : file header could not be read from '%s'\n",szFileName) ;
      }
      else
      {

        if ( (sFileHdr.byID[0]  == 0xEB  ) &&
             (sFileHdr.byID[1]  == 0x90  ) &&
             (sFileHdr.byID[2]  == 'G'   ) &&
             (sFileHdr.byID[3]  == 'S'   ) &&
             (sFileHdr.byID[4]  == 'E'   ) &&
             ((sFileHdr.wVersion == 0x0100) || (sFileHdr.wVersion == 0x0200)) &&
             (strcmp(strupr(sFileHdr.szProjectName),strupr(szProjectName)) == 0) )
        {
          if (iFileCount < MAX_FILES)
          {
            strcpy(sFile[iFileCount].szName,ffblk.ff_name) ;
            sFile[iFileCount].dwTime = sFileHdr.dwTime ;
            iFileCount++ ;
          }
          else
          {
            fprintf(stderr,"\nWarning : too many files, can open only %d files !\n",MAX_FILES) ;
            fclose(pFile) ;
          }
        }
        else
        {
          fprintf(stderr,"  no valid data file\n") ;
        }
      }

      fclose(pFile) ;

    }

    iDone = findnext(&ffblk) ;

  }

  /* ----------------------------------------------------
     sort the files found by time
     ---------------------------------------------------- */

  qsort(sFile,iFileCount,sizeof(DATAFILE),(int (*)(const void *a, const void *b))fCompTime) ;


  /* ----------------------------------------------------------------------
     if a Directory is requested, push it out now
     ---------------------------------------------------------------------- */

  if (bWriteDirectory)
  {
    printf("Directory of %s data files\n\n",strupr(szProjectName)) ;
    for (i=0; i<iFileCount; i++)
    {
      printf("%12.12s  %s",sFile[i].szName, ctime(&(sFile[i].dwTime))) ;
    }
    exit (-1) ;
  }

  /* -----------------------------------------------------------------------
     start the output
     ----------------------------------------------------------------------- */

  printf("GSEOS 4.0 data dump\n") ;
  printf("--------------------\n\n\n") ;
  printf("Data path : %s\n",szPath) ;

  /* ---------------------------------------------
     loop over all files
     --------------------------------------------- */

  for (i=0; i< iFileCount; i++)
  {
    WORD w;

    /* ----------------------------------------------
       open file and write message if not successfull
       ---------------------------------------------- */

    iBlockNumber = 1 ;
    for (w=0; w<wBlockCount; w++)
    {
      sBlock[w].iBlockID = -1 ;
    }

    strcat(strcpy(szFileName,szPath),sFile[i].szName) ;
    pFile = fopen(szFileName,"r+b") ;
    printf("\nFile : %s of %s\n",sFile[i].szName,ctime(&(sFile[i].dwTime))) ;

    if (!pFile)
    {
      extern char * sys_errlist[] ;
      extern int errno ;

      fprintf(stderr,"\n Error : '%s' could not be opended (%s).\n",sFile[i].szName,sys_errlist[errno]) ;
      iErrCount++ ;
      if (iErrCount > MAX_ERRORS)
        goto TOO_MANY_ERRORS ;
    }
    else
    {
      /* -------------------------------------------------
         read the header again and test the data
         ------------------------------------------------- */

      if (fread(&sFileHdr,sizeof(sFileHdr),1,pFile) != 1)
      {
        printf(">> FileHdr could not be read from '%s'\n",sFile[i].szName) ;
        iErrCount++ ;
        if (iErrCount > MAX_ERRORS)
          goto TOO_MANY_ERRORS ;
      }
      else
      {
        if (sFileHdr.dwNULL != 0)
        {
          printf(">> FileHdr.dwNULL is not 0 but %4.4X\n",sFileHdr.dwNULL) ;
          iErrCount++ ;
          if (iErrCount > MAX_ERRORS)
            goto TOO_MANY_ERRORS ;
        }

        /* ------------------------------------------------
           read records from file until file is empty
           ------------------------------------------------ */

        while (fread(abyID,sizeof(abyID),1,pFile) == 1)
        {
          if ( (abyID[0] == 'D') &&
               (abyID[1] == 'E') )
          {
            /* --------------------------------------------
               block definition record
               -------------------------------------------- */

            if (fread(&(sBlkHdr.wBlockID),sizeof(sBlkHdr)-2,1,pFile) != 1)
            {
              printf(">> BlkHdr could not be read from '%s'\n",sFile[i].szName) ;
              iErrCount++ ;
              if (iErrCount > MAX_ERRORS)
                goto TOO_MANY_ERRORS ;
            }
            else
            {

              /* ---------------------------------------
                 test if block ID has already been used
                 --------------------------------------- */

              for (j=0; j<wBlockCount; j++)
              {
                if (sBlkHdr.wBlockID == sBlock[j].iBlockID)
                {
                  printf(">> BlockID %d used twice.\n",sBlkHdr.wBlockID) ;
                  printf("   Block '%s' will not be recognized.\n",sBlkHdr.szName) ;
                  iErrCount++ ;
                  if (iErrCount > MAX_ERRORS)
                    goto TOO_MANY_ERRORS ;
                  break ;
                }
              }

              if (j == wBlockCount)
              {
                WORD w = 0;
                while ( (w<wBlockCount) &&
                        (strcmp(sBlock[w].szName,sBlkHdr.szName)) )
                  w++ ;

                sBlock[w].iBlockID   = sBlkHdr.wBlockID ;  // set a new block ID
                if (w == wBlockCount)
                {
                  strcpy(sBlock[w].szName,sBlkHdr.szName) ;
                  wBlockCount++ ;
                  sBlock[w].dwLastStamp = 0 ;
                }

                if (sBlkHdr.dwLen != sizeof(sBlkHdr))
                {
                  printf("BlkHdr.dwLen is incorrect for definition of block '%s' (%d)\n",
                         sBlkHdr.szName,sBlkHdr.dwLen) ;
                  iErrCount++ ;
                  if (iErrCount > MAX_ERRORS)
                    goto TOO_MANY_ERRORS ;
                }
              }

            }
          }
          else if ( (abyID[0] == 'T') &&
                    (abyID[1] == 'A') )
          {
            /* --------------------------------------------
               block data record
               -------------------------------------------- */

            if (fread(&(sBlkBody.wBlockID),sizeof(sBlkBody)-2,1,pFile) != 1)
            {
              printf(">> BlkBody could not be read from '%s'\n",sFile[i].szName) ;
              iErrCount++ ;
              if (iErrCount > MAX_ERRORS)
                goto TOO_MANY_ERRORS ;
            }
            else
            {
              for (j=0; j<wBlockCount; j++)
              {
                if (sBlkBody.wBlockID == sBlock[j].iBlockID)
                {
                  if (sBlock[j].dwLastStamp+1 != sBlkBody.dwStamp)
                  {
                    printf("\n>> Missing sample #%d of block %s. Next recorded sample is #%d\n\n",
                           sBlock[j].dwLastStamp+1,
                           sBlock[j].szName,
                           sBlkBody.dwStamp) ;
                  }
                  printf("\nBlock %3d : %18.18s #%d:[%d]  %s\n",
                         iBlockNumber++,
                         sBlock[j].szName,
                         sBlkBody.dwStamp,
                         sBlkBody.dwSize,
                         ctime(&(sBlkBody.dwTime))) ;
                  sBlock[j].dwLastStamp = sBlkBody.dwStamp ;
                  break ;
                }
              }
              if (j == wBlockCount)
              {
                printf("\n\n>> Block with ID %d is not defined !\n\n",sBlkBody.wBlockID) ;
                iErrCount++ ;
                if (iErrCount > MAX_ERRORS)
                  goto TOO_MANY_ERRORS ;
              }


              if (fread(abyBuffer,sBlkBody.dwSize,1,pFile) != 1)
              {
                printf(">> Data could not be read\n") ;
                iErrCount++ ;
                if (iErrCount > MAX_ERRORS)
                  goto TOO_MANY_ERRORS ;
              }
              else
              {
                int iPos ;
                int k ;

                iPos = 0;
                for (j=0; j<sBlkBody.dwSize; j++)
                {
                  if (iPos == 0)
                  {
                    printf("%4.4X  ",j) ;
                  }

                  printf("%2.2X ",(WORD)abyBuffer[j]) ;
                  iPos++ ;

                  if (iPos == 16)
                  {
                    printf("  ") ;
                    for (k=j-15; k<=j; k++)
                    {
                      if (abyBuffer[k] >= 0x20)
                        printf("%c",abyBuffer[k]) ;
                      else
                        printf(".") ;
                    }
                    printf("\n") ;
                    iPos = 0 ;
                  }
                }

                if (iPos != 0)
                {
                  j = j - iPos ;
                  for (k=iPos; k<16; k++)
                    printf("   ") ;
                  printf("  ") ;
                  for (;j<sBlkBody.dwSize; j++)
                  {
                    if (abyBuffer[j] >= 0x20)
                      printf("%c",abyBuffer[j]) ;
                    else
                      printf(".") ;
                  }
                  printf("\n") ;
                }
                printf("\n") ;
              }

            }

            if (fread(&dwLen,sizeof(dwLen),1,pFile) != 1)
            {
              printf(">> Back Pointer could not be read\n") ;
              iErrCount++ ;
              if (iErrCount > MAX_ERRORS)
                goto TOO_MANY_ERRORS ;
            }
            else
            {

              if (dwLen != sBlkBody.dwSize+sizeof(sBlkBody)+sizeof(DWORD))
              {
                printf(">> Back Pointer has wrong value (0x%4.4X), expected 0x%4.4X\n",
                       dwLen, sBlkBody.dwSize+sizeof(sBlkBody)+sizeof(DWORD)) ;
                iErrCount++ ;
                if (iErrCount > MAX_ERRORS)
                  goto TOO_MANY_ERRORS ;
              }
            }

          }
          else
          {
            printf(">> Record Header has wrong format : 0x%4.4X\n", abyID[0], abyID[1]) ;
            iErrCount++ ;
            if (iErrCount > MAX_ERRORS)
              goto TOO_MANY_ERRORS ;
          }
        }
      }
      fclose(pFile) ;

    }
  }

  return 0 ;

  TOO_MANY_ERRORS :
  printf("\nToo many errors, program aborted.\n") ;

  return -1 ;

}