292 lines
6.1 KiB
C++
292 lines
6.1 KiB
C++
|
//log.cpp
|
||
|
//log [network] physics packets in order to replay the games
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include "networkphysics.h"
|
||
|
#include "gamemem.h"
|
||
|
#include "log.h"
|
||
|
#include "gameinitexit.h"
|
||
|
#include "gameframe.h"
|
||
|
#include "network.h"
|
||
|
|
||
|
typedef struct{
|
||
|
int offset;
|
||
|
short size;
|
||
|
short type;
|
||
|
} tLogEntry;
|
||
|
|
||
|
#define kLogSize (20*1024*1024)
|
||
|
#define kGhostLogSize (256*1024)
|
||
|
#define kIndexSize (256*1024)
|
||
|
|
||
|
char* gPacketLog;
|
||
|
char *gGhostLog;
|
||
|
tLogEntry *gPacketLogIndex;
|
||
|
tLogEntry *gGhostIndex;
|
||
|
int gLogPos=0;
|
||
|
int gIndexPos=0;
|
||
|
int gGhostLogPos=0;
|
||
|
int gGhostIndexPos=0;
|
||
|
|
||
|
void LogInit()
|
||
|
{
|
||
|
gPacketLog=(char*)malloc(kLogSize);
|
||
|
gGhostLog=(char*)malloc(kGhostLogSize);
|
||
|
gPacketLogIndex=(tLogEntry*)malloc(kIndexSize*sizeof(tLogEntry));
|
||
|
gGhostIndex=(tLogEntry*)malloc(kIndexSize*sizeof(tLogEntry));
|
||
|
}
|
||
|
|
||
|
void GetLogs(tFileRef *logs,int *logCount)
|
||
|
{
|
||
|
*logCount=0;
|
||
|
for(int i=0;i<gFileTableSize;i++)
|
||
|
if(char *extension=FileGetExtension(i))
|
||
|
if(!_stricmp(extension,kFileTypeLog))
|
||
|
if(*logCount<kMaxLogs)
|
||
|
logs[(*logCount)++]=i;
|
||
|
}
|
||
|
|
||
|
void LogPacket(int size, void *data,int type)
|
||
|
{
|
||
|
if(gIndexPos<kIndexSize)
|
||
|
if(gLogPos+size<kLogSize)
|
||
|
{
|
||
|
gPacketLogIndex[gIndexPos].size=size;
|
||
|
gPacketLogIndex[gIndexPos].offset=gLogPos;
|
||
|
gPacketLogIndex[gIndexPos].type=type;
|
||
|
gIndexPos++;
|
||
|
MemoryMove(gPacketLog+gLogPos,data,size);
|
||
|
gLogPos+=size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void LogToGhostLog()
|
||
|
{
|
||
|
//kLogSize>kGhostLogSize!!!!
|
||
|
MemoryMove(gGhostLog,gPacketLog,gLogPos>kGhostLogSize?kGhostLogSize:gLogPos);
|
||
|
MemoryMove(gGhostIndex,gPacketLogIndex,gIndexPos*sizeof(tLogEntry));
|
||
|
gGhostLogPos=gLogPos;
|
||
|
gGhostIndexPos=gIndexPos;
|
||
|
}
|
||
|
|
||
|
int LogCompare(const void *a,const void *b)
|
||
|
{
|
||
|
int aFrame=((tPhysicsMessage*)(gPacketLog+*(int*)a))->frame;
|
||
|
int bFrame=((tPhysicsMessage*)(gPacketLog+*(int*)b))->frame;
|
||
|
S32Swap(aFrame);
|
||
|
S32Swap(bFrame);
|
||
|
return aFrame-bFrame;
|
||
|
}
|
||
|
|
||
|
void LogSort()
|
||
|
{
|
||
|
qsort(gPacketLogIndex,gIndexPos,sizeof(tLogEntry),LogCompare);
|
||
|
}
|
||
|
|
||
|
void LogReset()
|
||
|
{
|
||
|
gLogPos=0;
|
||
|
gIndexPos=0;
|
||
|
}
|
||
|
|
||
|
void GhostLogReset()
|
||
|
{
|
||
|
gGhostLogPos=0;
|
||
|
gGhostIndexPos=0;
|
||
|
}
|
||
|
|
||
|
|
||
|
int LogGetPacket(int index,int *type,int *size,int log,void *buffer)
|
||
|
{
|
||
|
if(log==kLogReplayLog||gGhostLogPos==0){
|
||
|
if(index<gIndexPos)
|
||
|
{
|
||
|
*type=gPacketLogIndex[index].type;
|
||
|
*size=gPacketLogIndex[index].size;
|
||
|
memcpy(buffer,gPacketLog+gPacketLogIndex[index].offset,*size);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if(index<gGhostIndexPos)
|
||
|
if(gGhostIndex[index].offset<kGhostLogSize)
|
||
|
{
|
||
|
*type=gGhostIndex[index].type;
|
||
|
*size=gGhostIndex[index].size;
|
||
|
memcpy(buffer,gGhostLog+gGhostIndex[index].offset,*size);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void GameInfoSend(tGameInfo *gInfo);
|
||
|
void GameInfoReceive(tGameInfo *gInfo);
|
||
|
void ConvertGInfoSwap(tGameInfo *gInfo);
|
||
|
|
||
|
void LogSaveToDisk()
|
||
|
{
|
||
|
char ct[255],name[255];
|
||
|
time_t t;
|
||
|
time(&t);
|
||
|
ctime_r(&t,ct);
|
||
|
ct[19]='\0';
|
||
|
ct[13]='-';
|
||
|
ct[16]='-';
|
||
|
sprintf(name,"%s.redlog",ct);
|
||
|
|
||
|
CFBundleRef refMainBundle = CFBundleGetMainBundle();
|
||
|
if (!refMainBundle)
|
||
|
return;
|
||
|
|
||
|
// create a URL to the app bundle
|
||
|
CFURLRef refMainBundleURL = CFBundleCopyBundleURL (refMainBundle);
|
||
|
if(!refMainBundleURL)
|
||
|
return;
|
||
|
|
||
|
char path[512];
|
||
|
if(!CFURLGetFileSystemRepresentation(refMainBundleURL,true,(UInt8*)path,512))
|
||
|
return;
|
||
|
|
||
|
sprintf(path,"%s/../",path);
|
||
|
chdir(path);
|
||
|
sprintf(path,"%s/Plug-Ins/",path);
|
||
|
chdir(path);
|
||
|
FILE* f=fopen(name,"w");
|
||
|
if(!f)
|
||
|
return;
|
||
|
|
||
|
SysBeep(0);
|
||
|
GameInfoSend(gGameInfo);
|
||
|
fwrite(gGameInfo,sizeof(tGameInfo),1,f);
|
||
|
if(gGameInfo->numLaps==-1)
|
||
|
{
|
||
|
int w=gGhostIndexPos;
|
||
|
S32Swap(w);
|
||
|
fwrite(&w,sizeof(int),1,f);
|
||
|
|
||
|
w=gGhostLogPos;
|
||
|
S32Swap(w);
|
||
|
fwrite(&w,sizeof(int),1,f);
|
||
|
|
||
|
w=gReplayOldFrameCount;
|
||
|
S32Swap(w);
|
||
|
fwrite(&w,sizeof(int),1,f);
|
||
|
|
||
|
|
||
|
for(int i=0;i<gGhostIndexPos;i++)
|
||
|
{
|
||
|
S32Swap(gGhostIndex[i].offset);
|
||
|
S16Swap(gGhostIndex[i].type);
|
||
|
S16Swap(gGhostIndex[i].size);
|
||
|
}
|
||
|
fwrite(gGhostIndex,sizeof(tLogEntry),gGhostIndexPos,f);
|
||
|
for(int i=0;i<gGhostIndexPos;i++)
|
||
|
{
|
||
|
S32Swap(gGhostIndex[i].offset);
|
||
|
S16Swap(gGhostIndex[i].type);
|
||
|
S16Swap(gGhostIndex[i].size);
|
||
|
}
|
||
|
|
||
|
for(int i=0;i<gGhostIndexPos;i++)
|
||
|
{
|
||
|
switch(gGhostIndex[i].type)
|
||
|
{
|
||
|
case kMessageTypePhysics:
|
||
|
{
|
||
|
tPhysicsMessage *physMessage=(tPhysicsMessage*)(gGhostLog+gGhostIndex[i].offset);
|
||
|
physMessage->frame-=(gBestLapTime!=0?gBestLapStart+5:gCurrentLapStart+5);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fwrite(gGhostLog,sizeof(char),gGhostLogPos,f);
|
||
|
for(int i=0;i<gGhostIndexPos;i++)
|
||
|
{
|
||
|
switch(gGhostIndex[i].type)
|
||
|
{
|
||
|
case kMessageTypePhysics:
|
||
|
{
|
||
|
tPhysicsMessage *physMessage=(tPhysicsMessage*)(gGhostLog+gGhostIndex[i].offset);
|
||
|
physMessage->frame+=(gBestLapTime!=0?gBestLapStart+5:gCurrentLapStart+5);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int w=gIndexPos;
|
||
|
S32Swap(w);
|
||
|
fwrite(&w,sizeof(int),1,f);
|
||
|
|
||
|
w=gLogPos;
|
||
|
S32Swap(w);
|
||
|
fwrite(&w,sizeof(int),1,f);
|
||
|
|
||
|
w=gReplayOldFrameCount;
|
||
|
S32Swap(w);
|
||
|
fwrite(&w,sizeof(int),1,f);
|
||
|
|
||
|
for(int i=0;i<gIndexPos;i++)
|
||
|
{
|
||
|
S32Swap(gPacketLogIndex[i].offset);
|
||
|
S16Swap(gPacketLogIndex[i].type);
|
||
|
S16Swap(gPacketLogIndex[i].size);
|
||
|
}
|
||
|
fwrite(gPacketLogIndex,sizeof(tLogEntry),gIndexPos,f);
|
||
|
for(int i=0;i<gIndexPos;i++)
|
||
|
{
|
||
|
S32Swap(gPacketLogIndex[i].offset);
|
||
|
S16Swap(gPacketLogIndex[i].type);
|
||
|
S16Swap(gPacketLogIndex[i].size);
|
||
|
}
|
||
|
|
||
|
fwrite(gPacketLog,sizeof(char),gLogPos,f);
|
||
|
}
|
||
|
fclose(f);
|
||
|
|
||
|
FileRescanDirectory();
|
||
|
}
|
||
|
|
||
|
int LogLoad(tFileRef f,tGameInfo* gInfo)
|
||
|
{
|
||
|
char *ch=(char*)FileGetDataPtr(f);
|
||
|
|
||
|
*gInfo=*(tGameInfo*)ch;
|
||
|
ConvertGInfoSwap(gInfo);
|
||
|
GameInfoReceive(gInfo);
|
||
|
ch+=sizeof(tGameInfo);//-sizeof(UInt32)*kMaxPlayers;
|
||
|
|
||
|
for(int i=0;i<gInfo->numPlayers;i++)
|
||
|
if(gInfo->playerCars[i]==-1)
|
||
|
return false;
|
||
|
if(gInfo->map==-1)
|
||
|
return false;
|
||
|
if(gInfo->environment==-1)
|
||
|
return false;
|
||
|
|
||
|
gIndexPos=*(int*)ch;
|
||
|
S32Swap(gIndexPos);
|
||
|
gGhostIndexPos=gIndexPos;
|
||
|
ch+=sizeof(int);
|
||
|
|
||
|
gLogPos=*(int*)ch;
|
||
|
S32Swap(gLogPos);
|
||
|
ch+=sizeof(int);
|
||
|
|
||
|
gReplayOldFrameCount=*(int*)ch;
|
||
|
S32Swap(gReplayOldFrameCount);
|
||
|
ch+=sizeof(int);
|
||
|
|
||
|
MemoryMove(gPacketLogIndex,ch,sizeof(tLogEntry)*gIndexPos);
|
||
|
for(int i=0;i<gIndexPos;i++)
|
||
|
{
|
||
|
S32Swap(gPacketLogIndex[i].offset);
|
||
|
S16Swap(gPacketLogIndex[i].type);
|
||
|
S16Swap(gPacketLogIndex[i].size);
|
||
|
}
|
||
|
ch+=sizeof(tLogEntry)*gIndexPos;
|
||
|
|
||
|
MemoryMove(gPacketLog,ch,sizeof(char)*gLogPos);
|
||
|
return true;
|
||
|
}
|