Cleaned up demo parsing a little.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2541 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2007-07-23 12:00:17 +00:00
parent b41d8b205e
commit 1069d3bfd5

View file

@ -147,40 +147,120 @@ void CL_WriteDemoMessage (sizebuf_t *msg)
VFS_FLUSH (cls.demofile); VFS_FLUSH (cls.demofile);
} }
unsigned char unreaddata[4096]; int demo_preparsedemo(unsigned char *buffer, int bytes)
int unreadcount; {
int readdemobytes(void *data, int len) int parsed = 0;
int ofs;
unsigned int length;
#define dem_mask 7
if (cls.demoplayback != DPB_MVD)
return bytes; //no need if its not an mvd (this simplifies it a little)
while (bytes>2)
{
switch(buffer[1]&dem_mask)
{
case dem_set:
ofs = -10;
break;
case dem_multiple:
ofs = 6;
break;
default:
ofs = 2;
break;
}
if (ofs > 0)
{
if (ofs+4 > bytes)
break;
length = (buffer[ofs+0]<<0) + (buffer[ofs+1]<<8) + (buffer[ofs+2]<<16) + (buffer[ofs+3]<<24);
if (length > 1500)
return parsed;
ofs+=4;
}
else
{
length = -ofs;
ofs = 2;
}
//ofs is now the offset of the data
if (ofs+length > bytes)
{
return parsed; //not got it all
}
if ((buffer[1]&dem_mask) == dem_all && (buffer[1] & ~dem_mask) && length < MAX_NQMSGLEN)
{
net_message.cursize = length;
memcpy(net_message.data, buffer+ofs, length);
CL_ParseServerMessage();
}
parsed += ofs+length;
buffer += ofs+length;
bytes -= ofs+length;
}
return parsed;
}
unsigned char demobuffer[1024*16];
int demobuffersize;
int demopreparsedbytes;
int readdemobytes(int *readpos, void *data, int len)
{ {
int i; int i;
// if (rand()&63 == 63) if (demopreparsedbytes < 0) //won't happen in normal running, but can still happen on corrupt data... if we don't disconnect first.
// return 0; demopreparsedbytes = 0;
if (unreadcount) i = VFS_READ(cls.demofile, demobuffer+demobuffersize, sizeof(demobuffer)-demobuffersize);
if (i > 0)
{ {
if (len > unreadcount) demobuffersize += i;
{ demopreparsedbytes += demo_preparsedemo(demobuffer+demopreparsedbytes, demobuffersize-demopreparsedbytes);
//this can only happen when the remaining 'unread' buffer from the initial qtv stream is part-way used up. }
i = VFS_READ(cls.demofile, unreaddata+unreadcount, len - unreadcount); else if (i < 0)
unreadcount += i; { //0 means no data available yet
printf("VFS_READ failed: %i\n", i);
if (len > unreadcount)
return 0;
}
unreadcount -= len;
memcpy(data, unreaddata, len);
memmove(unreaddata, unreaddata+len, unreadcount);
return len;
} }
i = VFS_READ(cls.demofile, data, len); if (len > demobuffersize)
return i; {
len = demobuffersize;
//CL_StopPlayback();
}
memcpy(data, demobuffer+*readpos, len);
*readpos += len;
return len;
} }
void unreadbytes(int count, void *data)
void demo_flushbytes(int bytes)
{ {
memmove(unreaddata+count, unreaddata, unreadcount); if (bytes > demobuffersize)
memcpy(unreaddata, data, count); Sys_Error("demo_flushbytes: flushed too much!\n");
unreadcount += count; memmove(demobuffer, demobuffer+bytes, demobuffersize - bytes);
demobuffersize -= bytes;
demopreparsedbytes -= bytes;
}
void demo_flushcache(void)
{
demobuffersize = 0;
demopreparsedbytes = 0;
}
void demo_resetcache(int bytes, void *data)
{
demo_flushcache();
demobuffersize = bytes;
memcpy(demobuffer, data, bytes);
//preparse it now
bytes = 0;
readdemobytes(&bytes, NULL, 0);
} }
@ -264,6 +344,8 @@ qboolean CL_GetDemoMessage (void)
qbyte c, msecsadded=0; qbyte c, msecsadded=0;
usercmd_t *pcmd; usercmd_t *pcmd;
q1usercmd_t q1cmd; q1usercmd_t q1cmd;
int demopos = 0;
int msglength;
#ifdef NQPROT #ifdef NQPROT
if (cls.demoplayback == DPB_NETQUAKE if (cls.demoplayback == DPB_NETQUAKE
@ -315,14 +397,16 @@ qboolean CL_GetDemoMessage (void)
return 0; return 0;
} }
} }
readdemobytes(&net_message.cursize, 4); if (readdemobytes(&demopos, &msglength, 4) != 4)
// VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); {
return 0;
}
if (cls.demoplayback == DPB_NETQUAKE) if (cls.demoplayback == DPB_NETQUAKE)
{ {
VectorCopy (cl.viewangles[1], cl.viewangles[2]); VectorCopy (cl.viewangles[1], cl.viewangles[2]);
for (i=0 ; i<3 ; i++) for (i=0 ; i<3 ; i++)
{ {
readdemobytes(&f, 4); readdemobytes(&demopos, &f, 4);
cl.simangles[0][i] = cl.viewangles[1][i] = LittleFloat (f); cl.simangles[0][i] = cl.viewangles[1][i] = LittleFloat (f);
} }
VectorCopy (cl.viewangles[1], cl.viewangles[0]); VectorCopy (cl.viewangles[1], cl.viewangles[0]);
@ -330,25 +414,18 @@ qboolean CL_GetDemoMessage (void)
olddemotime = realtime; olddemotime = realtime;
net_message.cursize = LittleLong (net_message.cursize); msglength = LittleLong (msglength);
if (net_message.cursize > MAX_NQMSGLEN) if (msglength > MAX_NQMSGLEN)
{ {
Con_Printf ("Demo message > MAX_MSGLEN"); Con_Printf ("Demo message > MAX_MSGLEN");
CL_StopPlayback (); CL_StopPlayback ();
return 0; return 0;
} }
if (net_message.cursize<0) if (readdemobytes(&demopos, net_message.data, msglength) != msglength)
{ {
Con_Printf ("Demo finished\n");
CL_StopPlayback ();
return 0;
}
r = readdemobytes(net_message.data, net_message.cursize);
if (r != net_message.cursize)
{
CL_StopPlayback ();
return 0; return 0;
} }
net_message.cursize = msglength;
return 1; return 1;
} }
@ -358,20 +435,24 @@ readnext:
if (cls.demoplayback == DPB_MVD) if (cls.demoplayback == DPB_MVD)
{ {
if (realtime < 0) if (realtime < 0)
{
readdemobytes(&demopos, NULL, 0);
return 0; return 0;
}
if (olddemotime > realtime) if (olddemotime > realtime)
olddemotime = realtime; olddemotime = realtime;
if (realtime + 1.0 < olddemotime) if (realtime + 1.0 < olddemotime)
realtime = olddemotime - 1.0; realtime = olddemotime - 1.0;
if (readdemobytes(&msecsadded, sizeof(msecsadded)) == 0) if (readdemobytes(&demopos, &msecsadded, sizeof(msecsadded)) != sizeof(msecsadded))
return 0; return 0;
demotime = olddemotime + msecsadded*(1.0f/1000); demotime = olddemotime + msecsadded*(1.0f/1000);
nextdemotime = demotime; nextdemotime = demotime;
} }
else else
{ {
readdemobytes(&demotime, sizeof(demotime)); if (readdemobytes(&demopos, &demotime, sizeof(demotime)) != sizeof(demotime))
return 0;
demotime = LittleFloat(demotime); demotime = LittleFloat(demotime);
} }
@ -383,11 +464,6 @@ readnext:
else if (demotime > cls.td_lastframe) else if (demotime > cls.td_lastframe)
{ {
cls.td_lastframe = demotime; cls.td_lastframe = demotime;
// rewind back to time
if (cls.demoplayback == DPB_MVD)
unreadbytes(sizeof(msecsadded), &msecsadded);
else
unreadbytes(sizeof(demotime), &demotime);
return 0; // already read this frame's message return 0; // already read this frame's message
} }
if (!cls.td_starttime && cls.state == ca_active) if (!cls.td_starttime && cls.state == ca_active)
@ -403,20 +479,10 @@ readnext:
{ {
// too far back // too far back
realtime = demotime - 1.0; realtime = demotime - 1.0;
// rewind back to time
if (cls.demoplayback == DPB_MVD)
unreadbytes(sizeof(msecsadded), &msecsadded);
else
unreadbytes(sizeof(demotime), &demotime);
return 0; return 0;
} }
else if (realtime < demotime) else if (realtime < demotime)
{ {
// rewind back to time
if (cls.demoplayback == DPB_MVD)
unreadbytes(sizeof(msecsadded), &msecsadded);
else
unreadbytes(sizeof(demotime), &demotime);
return 0; // don't need another message yet return 0; // don't need another message yet
} }
} }
@ -440,25 +506,8 @@ readnext:
Host_Error ("CL_GetDemoMessage: cls.state != ca_active"); Host_Error ("CL_GetDemoMessage: cls.state != ca_active");
// get the msg type // get the msg type
if (!readdemobytes (&c, sizeof(c))) if (!readdemobytes (&demopos, &c, sizeof(c)))
{
if (1)//!VFS_GETLEN(cls.demofile))
{
if (cls.demoplayback == DPB_MVD)
{
r = 0;
unreadbytes(1, &r);
}
else
{
demotime = LittleFloat(demotime);
unreadbytes(4, &demotime);
}
}
else
CL_StopPlayback ();
return 0; return 0;
}
// Con_Printf("demo packet %x\n", (int)c); // Con_Printf("demo packet %x\n", (int)c);
switch (c&7) switch (c&7)
{ {
@ -470,9 +519,9 @@ readnext:
unsigned char rateid; unsigned char rateid;
unsigned char audio[8192]; unsigned char audio[8192];
if (readdemobytes (&samps, 2) == 2) if (readdemobytes (&demopos, &samps, 2) == 2)
{ {
if (readdemobytes (&bits, 1) == 1) if (readdemobytes (&demopos, &bits, 1) == 1)
{ {
if (samps > sizeof(audio)) if (samps > sizeof(audio))
{ {
@ -480,9 +529,9 @@ readnext:
CL_StopPlayback(); CL_StopPlayback();
return 0; return 0;
} }
if (readdemobytes (&rateid, 1) == 1) if (readdemobytes (&demopos, &rateid, 1) == 1)
{ {
if (readdemobytes (audio, samps) == samps) if (readdemobytes (&demopos, audio, samps) == samps)
{ {
FILE *f; FILE *f;
samps = samps/(bits/8); samps = samps/(bits/8);
@ -496,16 +545,10 @@ readnext:
S_RawAudio(0, audio, 11025, samps, 1, bits/8); S_RawAudio(0, audio, 11025, samps, 1, bits/8);
break; break;
} }
unreadbytes(1, &rateid);
} }
unreadbytes(1, &bits);
} }
unreadbytes(1, &samps);
} }
unreadbytes(1, &c);
r = 0;
unreadbytes(1, &r);
return 0; return 0;
} }
else else
@ -513,7 +556,7 @@ readnext:
// user sent input // user sent input
i = cls.netchan.outgoing_sequence & UPDATE_MASK; i = cls.netchan.outgoing_sequence & UPDATE_MASK;
pcmd = &cl.frames[i].cmd[0]; pcmd = &cl.frames[i].cmd[0];
r = readdemobytes (&q1cmd, sizeof(q1cmd)); r = readdemobytes (&demopos, &q1cmd, sizeof(q1cmd));
if (r != sizeof(q1cmd)) if (r != sizeof(q1cmd))
{ {
CL_StopPlayback (); CL_StopPlayback ();
@ -537,7 +580,7 @@ readnext:
cls.netchan.outgoing_sequence++; cls.netchan.outgoing_sequence++;
for (i=0 ; i<3 ; i++) for (i=0 ; i<3 ; i++)
{ {
readdemobytes (&f, 4); readdemobytes (&demopos, &f, 4);
cl.viewangles[0][i] = LittleFloat (f); cl.viewangles[0][i] = LittleFloat (f);
} }
/* }*/ /* }*/
@ -546,65 +589,19 @@ readnext:
case dem_read: case dem_read:
readit: readit:
// get the next message // get the next message
if (readdemobytes (&net_message.cursize, 4) != 4) if (readdemobytes (&demopos, &msglength, 4) != 4)
{
if (1)//!VFS_GETLEN(cls.demofile))
{
if ((c & 7) == dem_multiple)
unreadbytes(4, &i);
unreadbytes(1, &c);
if (cls.demoplayback == DPB_MVD)
{
r = 0;
unreadbytes(1, &r);
}
else
{
demotime = LittleFloat(demotime);
unreadbytes(4, &demotime);
}
}
else
CL_StopPlayback ();
return 0; return 0;
} msglength = LittleLong (msglength);
net_message.cursize = LittleLong (net_message.cursize); //Con_Printf("read: %ld bytes\n", msglength);
//Con_Printf("read: %ld bytes\n", net_message.cursize); if ((unsigned int)msglength > MAX_OVERALLMSGLEN)
if ((unsigned int)net_message.cursize > MAX_OVERALLMSGLEN)
{ {
Con_Printf ("Demo message > MAX_OVERALLMSGLEN\n"); Con_Printf ("Demo message > MAX_OVERALLMSGLEN\n");
CL_StopPlayback (); CL_StopPlayback ();
return 0; return 0;
} }
r = readdemobytes (net_message.data, net_message.cursize); if (readdemobytes (&demopos, net_message.data, msglength) != msglength)
if (r != net_message.cursize)
{
if (1)//!VFS_GETLEN(cls.demofile))
{
net_message.cursize = LittleLong (net_message.cursize);
unreadbytes(4, &net_message.cursize);
if ((c & 7) == dem_multiple)
unreadbytes(4, &i);
unreadbytes(1, &c);
if (cls.demoplayback == DPB_MVD)
{
r = 0;
unreadbytes(1, &r);
}
else
{
demotime = LittleFloat(demotime);
unreadbytes(4, &demotime);
}
}
else
CL_StopPlayback ();
return 0; return 0;
} net_message.cursize = msglength;
if (cls.demoplayback == DPB_MVD) if (cls.demoplayback == DPB_MVD)
{ {
@ -624,14 +621,18 @@ readit:
if (tracknum == -1 || cls_lastto != tracknum) if (tracknum == -1 || cls_lastto != tracknum)
goto readnext; goto readnext;
break; break;
case dem_all:
if (c & ~dem_mask)
goto readnext;
break;
} }
} }
break; break;
case dem_set : case dem_set :
readdemobytes (&i, 4); readdemobytes (&demopos, &i, 4);
cls.netchan.outgoing_sequence = LittleLong(i); cls.netchan.outgoing_sequence = LittleLong(i);
readdemobytes (&i, 4); readdemobytes (&demopos, &i, 4);
cls.netchan.incoming_sequence = LittleLong(i); cls.netchan.incoming_sequence = LittleLong(i);
if (cls.demoplayback == DPB_MVD) if (cls.demoplayback == DPB_MVD)
@ -639,30 +640,8 @@ readit:
goto readnext; goto readnext;
case dem_multiple: case dem_multiple:
if (readdemobytes (&i, sizeof(i)) != sizeof(i)) if (readdemobytes (&demopos, &i, sizeof(i)) != sizeof(i))
{
if (1)//!VFS_GETLEN(cls.demofile))
{
if ((c & 7) == dem_multiple)
unreadbytes(4, &i);
unreadbytes(1, &c);
if (cls.demoplayback == DPB_MVD)
{
r = 0;
unreadbytes(1, &r);
}
else
{
demotime = LittleFloat(demotime);
unreadbytes(4, &demotime);
}
}
else
CL_StopPlayback ();
return 0; return 0;
}
cls_lastto = LittleLong(i); cls_lastto = LittleLong(i);
cls_lasttype = dem_multiple; cls_lasttype = dem_multiple;
goto readit; goto readit;
@ -688,6 +667,8 @@ readit:
return 0; return 0;
} }
demo_flushbytes(demopos);
return 1; return 1;
} }
@ -1104,7 +1085,8 @@ void CL_Record_f (void)
MSG_WriteAngle (&buf, ent->angles[j]); MSG_WriteAngle (&buf, ent->angles[j]);
} }
if (buf.cursize > MAX_QWMSGLEN/2) { if (buf.cursize > MAX_QWMSGLEN/2)
{
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
@ -1204,7 +1186,8 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, svc_updatestatlong); MSG_WriteByte (&buf, svc_updatestatlong);
MSG_WriteByte (&buf, i); MSG_WriteByte (&buf, i);
MSG_WriteLong (&buf, cl.stats[0][i]); MSG_WriteLong (&buf, cl.stats[0][i]);
if (buf.cursize > MAX_QWMSGLEN/2) { if (buf.cursize > MAX_QWMSGLEN/2)
{
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
@ -1332,8 +1315,8 @@ void CL_PlayDemo(char *demoname)
// disconnect from server // disconnect from server
// //
CL_Disconnect_f (); CL_Disconnect_f ();
unreadcount = 0; //just in case demo_flushcache();
// //
// open the demo file // open the demo file
// //
@ -1444,7 +1427,7 @@ void CL_QTVPlay (vfsfile_t *newf)
cls.demofile = newf; cls.demofile = newf;
unreadcount = 0; //just in case demo_flushcache(); //just in case
cls.demoplayback = DPB_MVD; cls.demoplayback = DPB_MVD;
cls.findtrack = true; cls.findtrack = true;
@ -1601,7 +1584,7 @@ void CL_QTVPoll (void)
{ {
CL_QTVPlay(qtvrequest); CL_QTVPlay(qtvrequest);
qtvrequest = NULL; qtvrequest = NULL;
unreadbytes(qtvrequestsize - (e-qtvrequestbuffer), e); demo_resetcache(qtvrequestsize - (e-qtvrequestbuffer), e);
return; return;
} }