Reduce the diffs in cl_demo.c.

Starting to look like a change in protocol rather than a complete rewrite.
This commit is contained in:
Bill Currie 2011-08-24 20:33:05 +09:00
parent d508da3cf0
commit 514f085e88
5 changed files with 402 additions and 308 deletions

View file

@ -348,6 +348,7 @@ float CL_KeyState (kbutton_t *key);
// cl_demo.c
void CL_StopPlayback (void);
void CL_StopRecording (void);
void CL_Record (const char *argv1, int track);
int CL_GetMessage (void);
void CL_Demo_Init (void);

View file

@ -1,7 +1,7 @@
/*
cl_demo.c
@description@
demo playback support
Copyright (C) 1996-1997 Id Software, Inc.
@ -56,50 +56,59 @@ typedef struct {
double fps;
} td_stats_t;
int demo_timeframes_isactive;
int demo_timeframes_index;
char demoname[1024];
double *demo_timeframes_array;
#define CL_TIMEFRAMES_ARRAYBLOCK 4096
int timedemo_count;
int timedemo_runs;
td_stats_t *timedemo_data;
static void CL_FinishTimeDemo (void);
static void CL_FinishTimeDemo (void);
static void CL_TimeFrames_DumpLog (void);
static void CL_TimeFrames_AddTimestamp (void);
static void CL_TimeFrames_Reset (void);
cvar_t *demo_gzip;
cvar_t *demo_speed;
cvar_t *demo_quit;
cvar_t *demo_timeframes;
#define MAX_DEMMSG (MAX_MSGLEN)
/*
DEMO CODE
DEMO CODE
When a demo is playing back, all NET_SendMessages are skipped, and
NET_GetMessages are read from the demo file.
When a demo is playing back, all NET_SendMessages are skipped, and
NET_GetMessages are read from the demo file.
Whenever cl.time gets past the last received message, another message is
read from the demo file.
Whenever cl.time gets past the last received message, another message is
read from the demo file.
*/
/*
CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
*/
static void
CL_WriteDemoMessage (void)
CL_WriteDemoMessage (sizebuf_t *msg)
{
float f;
int len;
int i;
float f;
len = LittleLong (net_message->message->cursize);
len = LittleLong (msg->cursize);
Qwrite (cls.demofile, &len, 4);
for (i = 0; i < 3; i++) {
f = LittleFloat (cl.viewangles[i]);
Qwrite (cls.demofile, &f, 4);
}
Qwrite (cls.demofile, net_message->message->data,
net_message->message->cursize);
Qwrite (cls.demofile, msg->data, msg->cursize);
Qflush (cls.demofile);
}
@ -115,78 +124,75 @@ CL_StopPlayback (void)
return;
Qclose (cls.demofile);
cls.demoplayback = false;
cls.demofile = NULL;
CL_SetState (ca_disconnected);
cls.demoplayback = 0;
if (cls.timedemo)
CL_FinishTimeDemo ();
}
void
CL_StopRecording (void)
{
// write a disconnect message to the demo file
// write a disconnect message to the demo file
SZ_Clear (net_message->message);
MSG_WriteByte (net_message->message, svc_disconnect);
CL_WriteDemoMessage ();
CL_WriteDemoMessage (net_message->message);
// finish up
// finish up
Qclose (cls.demofile);
cls.demofile = NULL;
cls.demorecording = false;
Sys_Printf ("Completed demo\n");
}
/*
CL_GetMessage
Handles recording and playback of demos, on top of NET_ code
*/
int
CL_GetMessage (void)
static int
CL_GetDemoMessage (void)
{
int r, i;
int i, r;
float f;
if (cls.demoplayback) {
// decide if it is time to grab the next message
if (cls.signon == SIGNONS) { // always grab until fully connected
if (cls.timedemo) {
if (host_framecount == cls.td_lastframe)
return 0; // already read this frame's message
cls.td_lastframe = host_framecount;
// if this is the second frame, grab the real td_starttime
// so the bogus time on the first frame doesn't count
if (host_framecount == cls.td_startframe + 1)
cls.td_starttime = realtime;
} else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0]) {
return 0; // don't need another message yet
}
// decide if it is time to grab the next message
if (cls.signon == SIGNONS) { // always grab until fully connected
if (cls.timedemo) {
if (host_framecount == cls.td_lastframe)
return 0; // already read this frame's message
cls.td_lastframe = host_framecount;
// if this is the second frame, grab the real td_starttime
// so the bogus time on the first frame doesn't count
if (host_framecount == cls.td_startframe + 1)
cls.td_starttime = realtime;
} else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0]) {
return 0; // don't need another message yet
}
// get the next message
Qread (cls.demofile, &net_message->message->cursize, 4);
VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
for (i = 0; i < 3; i++) {
r = Qread (cls.demofile, &f, 4);
cl.mviewangles[0][i] = LittleFloat (f);
}
net_message->message->cursize =
LittleLong (net_message->message->cursize);
if (net_message->message->cursize > MAX_MSGLEN)
Sys_Error ("Demo message > MAX_MSGLEN");
r = Qread (cls.demofile, net_message->message->data,
net_message->message->cursize);
if (r != net_message->message->cursize) {
CL_StopPlayback ();
return 0;
}
return 1;
}
// get the next message
Qread (cls.demofile, &net_message->message->cursize, 4);
net_message->message->cursize =
LittleLong (net_message->message->cursize);
if (net_message->message->cursize > MAX_DEMMSG)
Host_Error ("Demo message > MAX_DEMMSG: %d/%d",
net_message->message->cursize, MAX_DEMMSG);
VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
for (i = 0; i < 3; i++) {
r = Qread (cls.demofile, &f, 4);
cl.mviewangles[0][i] = LittleFloat (f);
}
r = Qread (cls.demofile, net_message->message->data,
net_message->message->cursize);
if (r != net_message->message->cursize) {
CL_StopPlayback ();
return 0;
}
return 1;
}
static int
CL_GetPacket (void)
{
int r;
while (1) {
r = NET_GetMessage (cls.netcon);
@ -201,13 +207,34 @@ CL_GetMessage (void)
else
break;
}
if (cls.demorecording)
CL_WriteDemoMessage ();
return r;
}
/*
CL_GetMessage
Handles recording and playback of demos, on top of NET_ code
*/
int
CL_GetMessage (void)
{
if (cls.demoplayback) {
int ret = CL_GetDemoMessage ();
if (!ret && demo_timeframes_isactive && cls.td_starttime) {
CL_TimeFrames_AddTimestamp ();
}
return ret;
}
if (!CL_GetPacket ())
return 0;
if (cls.demorecording)
CL_WriteDemoMessage (net_message->message);
return 1;
}
/*
CL_Stop_f
@ -227,7 +254,6 @@ CL_Stop_f (void)
CL_StopRecording ();
}
/*
CL_Record_f
@ -237,7 +263,6 @@ static void
CL_Record_f (void)
{
int c;
dstring_t *name;
int track;
if (cmd_source != src_command)
@ -266,16 +291,23 @@ CL_Record_f (void)
} else
track = -1;
name = dstring_new ();
dsprintf (name, "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1));
// start the map up
//
if (c > 2)
Cmd_ExecuteString (va ("map %s", Cmd_Argv (2)), src_command);
// open the demo file
//
CL_Record (Cmd_Argv (1), track);
}
void
CL_Record (const char *argv1, int track)
{
dstring_t *name;
name = dstring_new ();
dsprintf (name, "%s/%s", qfs_gamedir->dir.def, argv1);
// open the demo file
#ifdef HAVE_ZLIB
if (demo_gzip->int_val) {
QFS_DefaultExtension (name, ".dem.gz");
@ -299,7 +331,6 @@ CL_Record_f (void)
dstring_delete (name);
}
static void
CL_StartDemo (void)
{
@ -307,12 +338,10 @@ CL_StartDemo (void)
int c;
qboolean neg = false;
// disconnect from server
//
// disconnect from server
CL_Disconnect ();
// open the demo file
//
// open the demo file
name = dstring_strdup (demoname);
QFS_DefaultExtension (name, ".dem");
@ -356,7 +385,7 @@ CL_PlayDemo_f (void)
Sys_Printf ("play <demoname> : plays a demo\n");
return;
}
timedemo_runs = timedemo_count = 1; // make sure looped timedemos stop
timedemo_runs = timedemo_count = 1; // make sure looped timedemos stop
strncpy (demoname, Cmd_Argv (1), sizeof (demoname));
CL_StartDemo ();
}
@ -373,6 +402,10 @@ CL_StartTimeDemo (void)
cls.td_starttime = 0;
cls.td_startframe = host_framecount;
cls.td_lastframe = -1; // get a new message this frame
CL_TimeFrames_Reset ();
if (demo_timeframes->int_val)
demo_timeframes_isactive = 1;
}
static inline double
@ -397,6 +430,9 @@ CL_FinishTimeDemo (void)
Sys_Printf ("%i frame%s %.4g seconds %.4g fps\n", frames,
frames == 1 ? "" : "s", time, frames / time);
CL_TimeFrames_DumpLog ();
demo_timeframes_isactive = 0;
timedemo_count--;
if (timedemo_data) {
timedemo_data[timedemo_count].frames = frames;
@ -432,7 +468,6 @@ CL_FinishTimeDemo (void)
}
}
/*
CL_TimeDemo_f
@ -450,15 +485,15 @@ CL_TimeDemo_f (void)
Sys_Printf ("timedemo <demoname> [count]: gets demo speeds\n");
return;
}
timedemo_runs = timedemo_count = 1; // make sure looped timedemos stop
timedemo_runs = timedemo_count = 1; // make sure looped timedemos stop
if (Cmd_Argc () == 3)
count = atoi (Cmd_Argv (2));
timedemo_runs = timedemo_count = 1;
if (timedemo_data) {
free (timedemo_data);
timedemo_data = 0;
}
timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t));
strncpy (demoname, Cmd_Argv (1), sizeof (demoname));
CL_StartTimeDemo ();
timedemo_runs = timedemo_count = max (count, 1);
@ -468,6 +503,10 @@ CL_TimeDemo_f (void)
void
CL_Demo_Init (void)
{
demo_timeframes_isactive = 0;
demo_timeframes_index = 0;
demo_timeframes_array = NULL;
demo_gzip = Cvar_Get ("demo_gzip", "0", CVAR_ARCHIVE, NULL,
"Compress demos using gzip. 0 = none, 1 = least "
"compression, 9 = most compression. Compressed "
@ -477,8 +516,60 @@ CL_Demo_Init (void)
"< 1 slow-mo, > 1 timelapse");
demo_quit = Cvar_Get ("demo_quit", "0", CVAR_NONE, NULL,
"automaticly quit after a timedemo has finished");
Cmd_AddCommand ("record", CL_Record_f, "No Description");
Cmd_AddCommand ("stop", CL_Stop_f, "No Description");
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "No Description");
Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "No Description");
demo_timeframes = Cvar_Get ("demo_timeframes", "0", CVAR_NONE, NULL,
"write timestamps for every frame");
Cmd_AddCommand ("record", CL_Record_f, "Record a demo, if no filename "
"argument is given\n"
"the demo will be called Year-Month-Day-Hour-Minute-"
"Mapname");
Cmd_AddCommand ("stop", CL_Stop_f, "Stop recording a demo");
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "Play a recorded demo");
Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "Play a demo as fast as your "
"hardware can. Useful for benchmarking.");
}
static void
CL_TimeFrames_Reset (void)
{
demo_timeframes_index = 0;
free (demo_timeframes_array);
demo_timeframes_array = NULL;
}
static void
CL_TimeFrames_AddTimestamp (void)
{
if (!(demo_timeframes_index % CL_TIMEFRAMES_ARRAYBLOCK))
demo_timeframes_array = realloc
(demo_timeframes_array, sizeof (demo_timeframes_array[0]) *
((demo_timeframes_index / CL_TIMEFRAMES_ARRAYBLOCK) + 1) *
CL_TIMEFRAMES_ARRAYBLOCK);
if (demo_timeframes_array == NULL)
Sys_Error ("Unable to allocate timeframes buffer");
demo_timeframes_array[demo_timeframes_index] = Sys_DoubleTime ();
demo_timeframes_index++;
}
static void
CL_TimeFrames_DumpLog (void)
{
const char *filename = "timeframes.txt";
int i;
long frame;
QFile *outputfile;
if (demo_timeframes_isactive == 0)
return;
Sys_Printf ("Dumping Timed Frames log: %s\n", filename);
outputfile = QFS_Open (filename, "w");
if (!outputfile) {
Sys_Printf ("Could not open: %s\n", filename);
return;
}
for (i = 1; i < demo_timeframes_index; i++) {
frame = (demo_timeframes_array[i] - demo_timeframes_array[i - 1]) * 1e6;
Qprintf (outputfile, "%09ld\n", frame);
}
Qclose (outputfile);
}

View file

@ -33,15 +33,11 @@
#include "qw/protocol.h"
void CL_StopPlayback (void);
qboolean CL_GetMessage (void);
int CL_GetMessage (void);
void CL_WriteDemoCmd (usercmd_t *pcmd);
void CL_Stop_f (void);
void CL_Record_f (void);
void CL_Record (const char *argv1);
void CL_ReRecord_f (void);
void CL_PlayDemo_f (void);
void CL_TimeDemo_f (void);
void CL_StopRecording (void);
void CL_Record (const char *argv1, int track); // track ignored
void CL_Demo_Init (void);

View file

@ -1,7 +1,7 @@
/*
cl_demo.c
(description)
demo playback support
Copyright (C) 1996-1997 Id Software, Inc.
@ -28,8 +28,7 @@
# include "config.h"
#endif
static __attribute__ ((used)) const char rcsid[] =
"$Id$";
static __attribute__ ((used)) const char rcsid[] = "$Id$";
#ifdef HAVE_STRING_H
# include <string.h>
@ -70,29 +69,30 @@ typedef struct {
double fps;
} td_stats_t;
int demo_timeframes_isactive;
int demo_timeframes_index;
int demotime_cached;
float nextdemotime;
char demoname[1024];
double *demo_timeframes_array;
int demo_timeframes_isactive;
int demo_timeframes_index;
int demotime_cached;
float nextdemotime;
char demoname[1024];
double *demo_timeframes_array;
#define CL_TIMEFRAMES_ARRAYBLOCK 4096
int timedemo_count;
int timedemo_runs;
int timedemo_count;
int timedemo_runs;
td_stats_t *timedemo_data;
static void CL_FinishTimeDemo (void);
static void CL_TimeFrames_DumpLog (void);
static void CL_TimeFrames_AddTimestamp (void);
static void CL_TimeFrames_Reset (void);
cvar_t *demo_speed;
cvar_t *demo_gzip;
cvar_t *demo_speed;
cvar_t *demo_quit;
cvar_t *demo_timeframes;
#define MAX_DEMMSG (MAX_MSGLEN + 8) //+8 for header
/*
DEMO CODE
@ -104,6 +104,31 @@ cvar_t *demo_timeframes;
*/
/*
CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
*/
static void
CL_WriteDemoMessage (sizebuf_t *msg)
{
byte c;
float f;
int len;
f = LittleFloat ((float) realtime);
Qwrite (cls.demofile, &f, sizeof (f));
c = dem_read;
Qwrite (cls.demofile, &c, sizeof (c));
len = LittleLong (msg->cursize);
Qwrite (cls.demofile, &len, 4);
Qwrite (cls.demofile, msg->data, msg->cursize);
Qflush (cls.demofile);
}
/*
CL_StopPlayback
@ -127,70 +152,21 @@ CL_StopPlayback (void)
CL_FinishTimeDemo ();
}
/*
CL_WriteDemoCmd
Writes the current user cmd
*/
void
CL_WriteDemoCmd (usercmd_t *pcmd)
CL_StopRecording (void)
{
byte c;
float fl;
int i;
usercmd_t cmd;
// write a disconnect message to the demo file
SZ_Clear (net_message->message);
MSG_WriteLong (net_message->message, -1); // -1 sequence means out of band
MSG_WriteByte (net_message->message, svc_disconnect);
MSG_WriteString (net_message->message, "EndOfDemo");
CL_WriteDemoMessage (net_message->message);
fl = LittleFloat ((float) realtime);
Qwrite (cls.demofile, &fl, sizeof (fl));
c = dem_cmd;
Qwrite (cls.demofile, &c, sizeof (c));
// correct for byte order, bytes don't matter
cmd = *pcmd;
for (i = 0; i < 3; i++)
cmd.angles[i] = LittleFloat (cmd.angles[i]);
cmd.forwardmove = LittleShort (cmd.forwardmove);
cmd.sidemove = LittleShort (cmd.sidemove);
cmd.upmove = LittleShort (cmd.upmove);
Qwrite (cls.demofile, &cmd, sizeof (cmd));
for (i = 0; i < 3; i++) {
fl = LittleFloat (cl.viewangles[i]);
Qwrite (cls.demofile, &fl, 4);
}
Qflush (cls.demofile);
}
/*
CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
*/
static void
CL_WriteDemoMessage (sizebuf_t *msg)
{
byte c;
float fl;
int len;
if (!cls.demorecording)
return;
fl = LittleFloat ((float) realtime);
Qwrite (cls.demofile, &fl, sizeof (fl));
c = dem_read;
Qwrite (cls.demofile, &c, sizeof (c));
len = LittleLong (msg->cursize);
Qwrite (cls.demofile, &len, 4);
Qwrite (cls.demofile, msg->data, msg->cursize);
Qflush (cls.demofile);
// finish up
Qclose (cls.demofile);
cls.demofile = NULL;
cls.demorecording = false;
Sys_Printf ("Completed demo\n");
}
#if 0
@ -206,7 +182,7 @@ static const char *dem_names[] = {
};
#endif
static qboolean
static int
CL_GetDemoMessage (void)
{
byte c, newtime;
@ -326,11 +302,11 @@ nextdemomessage:
readit:
// get the next message
Qread (cls.demofile, &net_message->message->cursize, 4);
net_message->message->cursize = LittleLong
(net_message->message->cursize);
if (net_message->message->cursize > MAX_MSGLEN + 8) //+8 for header
Host_Error ("Demo message > MAX_MSGLEN + 8: %d/%d",
net_message->message->cursize, MAX_MSGLEN + 8);
net_message->message->cursize =
LittleLong (net_message->message->cursize);
if (net_message->message->cursize > MAX_DEMMSG)
Host_Error ("Demo message > MAX_DEMMSG: %d/%d",
net_message->message->cursize, MAX_DEMMSG);
r = Qread (cls.demofile, net_message->message->data,
net_message->message->cursize);
if (r != net_message->message->cursize) {
@ -352,7 +328,6 @@ readit:
}
}
break;
case dem_set:
Qread (cls.demofile, &i, 4);
cls.netchan.outgoing_sequence = LittleLong (i);
@ -364,7 +339,6 @@ readit:
goto nextdemomessage;
}
break;
case dem_multiple:
r = Qread (cls.demofile, &i, 4);
if (r != 4) {
@ -374,41 +348,42 @@ readit:
cls.lastto = LittleLong (i);
cls.lasttype = dem_multiple;
goto readit;
case dem_single:
cls.lastto = c >> 3;
cls.lasttype = dem_single;
goto readit;
case dem_stats:
cls.lastto = c >> 3;
cls.lasttype = dem_stats;
goto readit;
case dem_all:
cls.lastto = 0;
cls.lasttype = dem_all;
goto readit;
default:
Sys_Printf ("Corrupted demo.\n");
CL_StopPlayback ();
return 0;
}
return 1;
}
static int
CL_GetPacket (void)
{
return NET_GetPacket ();
}
/*
CL_GetMessage
Handles recording and playback of demos, on top of NET_ code
*/
qboolean
int
CL_GetMessage (void)
{
if (cls.demoplayback) {
qboolean ret = CL_GetDemoMessage ();
int ret = CL_GetDemoMessage ();
if (!ret && demo_timeframes_isactive && cls.td_starttime) {
CL_TimeFrames_AddTimestamp ();
@ -416,16 +391,56 @@ CL_GetMessage (void)
return ret;
}
if (!NET_GetPacket ())
return false;
if (!CL_GetPacket ())
return 0;
if (net_packetlog->int_val)
Log_Incoming_Packet (net_message->message->data,
net_message->message->cursize, 1);
CL_WriteDemoMessage (net_message->message);
return true;
if (cls.demorecording)
CL_WriteDemoMessage (net_message->message);
return 1;
}
/*
CL_WriteDemoCmd
Writes the current user cmd
*/
void
CL_WriteDemoCmd (usercmd_t *pcmd)
{
byte c;
float fl;
int i;
usercmd_t cmd;
fl = LittleFloat ((float) realtime);
Qwrite (cls.demofile, &fl, sizeof (fl));
c = dem_cmd;
Qwrite (cls.demofile, &c, sizeof (c));
// correct for byte order, bytes don't matter
cmd = *pcmd;
for (i = 0; i < 3; i++)
cmd.angles[i] = LittleFloat (cmd.angles[i]);
cmd.forwardmove = LittleShort (cmd.forwardmove);
cmd.sidemove = LittleShort (cmd.sidemove);
cmd.upmove = LittleShort (cmd.upmove);
Qwrite (cls.demofile, &cmd, sizeof (cmd));
for (i = 0; i < 3; i++) {
fl = LittleFloat (cl.viewangles[i]);
Qwrite (cls.demofile, &fl, 4);
}
Qflush (cls.demofile);
}
/*
@ -433,29 +448,90 @@ CL_GetMessage (void)
stop recording a demo
*/
void
static void
CL_Stop_f (void)
{
if (!cls.demorecording) {
Sys_Printf ("Not recording a demo.\n");
return;
}
// write a disconnect message to the demo file
SZ_Clear (net_message->message);
MSG_WriteLong (net_message->message, -1); // -1 sequence means out of band
MSG_WriteByte (net_message->message, svc_disconnect);
MSG_WriteString (net_message->message, "EndOfDemo");
CL_WriteDemoMessage (net_message->message);
// finish up
Qclose (cls.demofile);
cls.demofile = NULL;
cls.demorecording = false;
Sys_Printf ("Completed demo\n");
CL_StopRecording ();
}
/*
CL_WriteDemoMessage
CL_Record_f
record <demoname> <server>
*/
static void
CL_Record_f (void)
{
if (Cmd_Argc () > 2) {
// we use a demo name like year-month-day-hours-minutes-mapname.qwd
// if there is no argument
Sys_Printf ("record [demoname]\n");
return;
}
if (cls.demoplayback || cls.state != ca_active) {
Sys_Printf ("You must be connected to record.\n");
return;
}
if (cls.demorecording)
CL_Stop_f ();
if (Cmd_Argc () == 2)
CL_Record (Cmd_Argv (1), -1);
else
CL_Record (0, -1);
}
/*
CL_ReRecord_f
record <demoname>
*/
static void
CL_ReRecord_f (void)
{
dstring_t *name;
int c;
c = Cmd_Argc ();
if (c != 2) {
Sys_Printf ("rerecord <demoname>\n");
return;
}
if (!cls.servername || !cls.servername->str) {
Sys_Printf ("No server to which to reconnect...\n");
return;
}
if (cls.demorecording)
CL_Stop_f ();
name = dstring_newstr ();
dsprintf (name, "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1));
// open the demo file
QFS_DefaultExtension (name, ".qwd");
cls.demofile = QFS_WOpen (name->str, 0);
if (!cls.demofile) {
Sys_Printf ("ERROR: couldn't open.\n");
} else {
Sys_Printf ("recording to %s.\n", name->str);
cls.demorecording = true;
CL_Disconnect ();
CL_BeginServerConnect ();
}
dstring_delete (name);
}
/*
CL_WriteRecordDemoMessage
Dumps the current net message, prefixed by the length and view angles
*/
@ -512,7 +588,7 @@ CL_WriteSetDemoMessage (void)
}
void
CL_Record (const char *argv1)
CL_Record (const char *argv1, int track)
{
byte buf_data[MAX_MSGLEN + 10]; // + 10 for header
dstring_t *name;
@ -803,93 +879,21 @@ CL_Record (const char *argv1)
// done
}
/*
CL_Record_f
record <demoname> <server>
*/
void
CL_Record_f (void)
{
if (Cmd_Argc () > 2) {
// we use a demo name like year-month-day-hours-minutes-mapname.qwd
// if there is no argument
Sys_Printf ("record [demoname]\n");
return;
}
if (cls.demoplayback || cls.state != ca_active) {
Sys_Printf ("You must be connected to record.\n");
return;
}
if (cls.demorecording)
CL_Stop_f ();
if (Cmd_Argc () == 2)
CL_Record (Cmd_Argv (1));
else
CL_Record (0);
}
/*
CL_ReRecord_f
record <demoname>
*/
void
CL_ReRecord_f (void)
{
dstring_t *name;
int c;
c = Cmd_Argc ();
if (c != 2) {
Sys_Printf ("rerecord <demoname>\n");
return;
}
if (!cls.servername || !cls.servername->str) {
Sys_Printf ("No server to which to reconnect...\n");
return;
}
if (cls.demorecording)
CL_Stop_f ();
name = dstring_newstr ();
dsprintf (name, "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1));
// open the demo file
QFS_DefaultExtension (name, ".qwd");
cls.demofile = QFS_WOpen (name->str, 0);
if (!cls.demofile) {
Sys_Printf ("ERROR: couldn't open.\n");
} else {
Sys_Printf ("recording to %s.\n", name->str);
cls.demorecording = true;
CL_Disconnect ();
CL_BeginServerConnect ();
}
dstring_delete (name);
}
static void
CL_StartDemo (void)
{
dstring_t *name = dstring_newstr ();
dstring_t *name;
// open the demo file
dstring_copystr (name, demoname);
name = dstring_strdup (demoname);
QFS_DefaultExtension (name, ".qwd");
Sys_Printf ("Playing demo from %s.\n", name->str);
QFS_FOpenFile (name->str, &cls.demofile);
dstring_delete (name);
if (!cls.demofile) {
Sys_Printf ("ERROR: couldn't open.\n");
cls.demonum = -1; // stop demo loop
dstring_delete (name);
return;
}
@ -921,7 +925,7 @@ CL_StartDemo (void)
play [demoname]
*/
void
static void
CL_PlayDemo_f (void)
{
if (Cmd_Argc () != 2) {
@ -966,8 +970,8 @@ sqr (double x)
static void
CL_FinishTimeDemo (void)
{
float time;
int frames;
int frames;
float time;
cls.timedemo = false;
@ -983,13 +987,15 @@ CL_FinishTimeDemo (void)
demo_timeframes_isactive = 0;
timedemo_count--;
timedemo_data[timedemo_count].frames = frames;
timedemo_data[timedemo_count].time = time;
timedemo_data[timedemo_count].fps = frames / time;
if (timedemo_data) {
timedemo_data[timedemo_count].frames = frames;
timedemo_data[timedemo_count].time = time;
timedemo_data[timedemo_count].fps = frames / time;
}
if (timedemo_count > 0) {
CL_StartTimeDemo ();
} else {
if (--timedemo_runs > 0) {
if (--timedemo_runs > 0 && timedemo_data) {
double average = 0;
double variance = 0;
double min, max;
@ -1010,8 +1016,6 @@ CL_FinishTimeDemo (void)
Sys_Printf (" min/max fps: %.3f/%.3f\n", min, max);
Sys_Printf ("std deviation: %.3f fps\n", sqrt (variance));
}
free (timedemo_data);
timedemo_data = 0;
if (demo_quit->int_val)
Cbuf_InsertText (cl_cbuf, "quit\n");
}
@ -1022,9 +1026,11 @@ CL_FinishTimeDemo (void)
timedemo [demoname]
*/
void
static void
CL_TimeDemo_f (void)
{
int count = 1;
if (Cmd_Argc () < 2 || Cmd_Argc () > 3) {
Sys_Printf ("timedemo <demoname> [count]: gets demo speeds\n");
return;
@ -1033,17 +1039,17 @@ CL_TimeDemo_f (void)
// disconnect from server
CL_Disconnect ();
if (Cmd_Argc () == 3) {
timedemo_count = atoi (Cmd_Argv (2));
} else {
timedemo_count = 1;
}
timedemo_runs = timedemo_count = max (timedemo_count, 1);
if (timedemo_data)
if (Cmd_Argc () == 3)
count = atoi (Cmd_Argv (2));
if (timedemo_data) {
free (timedemo_data);
timedemo_data = 0;
}
timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t));
strncpy (demoname, Cmd_Argv (1), sizeof (demoname));
CL_StartTimeDemo ();
timedemo_runs = timedemo_count = max (count, 1);
timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t));
}
void
@ -1064,6 +1070,16 @@ CL_Demo_Init (void)
"automaticly quit after a timedemo has finished");
demo_timeframes = Cvar_Get ("demo_timeframes", "0", CVAR_NONE, NULL,
"write timestamps for every frame");
Cmd_AddCommand ("record", CL_Record_f, "Record a demo, if no filename "
"argument is given\n"
"the demo will be called Year-Month-Day-Hour-Minute-"
"Mapname");
Cmd_AddCommand ("rerecord", CL_ReRecord_f, "Rerecord a demo on the same "
"server");
Cmd_AddCommand ("stop", CL_Stop_f, "Stop recording a demo");
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "Play a recorded demo");
Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "Play a demo as fast as your "
"hardware can. Useful for benchmarking.");
}
static void
@ -1092,9 +1108,9 @@ static void
CL_TimeFrames_DumpLog (void)
{
const char *filename = "timeframes.txt";
int i;
long frame;
QFile *outputfile;
int i;
long frame;
QFile *outputfile;
if (demo_timeframes_isactive == 0)
return;

View file

@ -486,7 +486,7 @@ CL_Disconnect (void)
CL_StopPlayback ();
else if (cls.state != ca_disconnected) {
if (cls.demorecording)
CL_Stop_f ();
CL_StopRecording ();
final[0] = clc_stringcmd;
strcpy ((char *) final + 1, "drop");
@ -1155,7 +1155,7 @@ CL_SetState (cactive_t state)
// Auto demo recorder stops here
if (cl_autorecord->int_val && cls.demorecording)
CL_Stop_f ();
CL_StopRecording ();
} else if (state == ca_active) {
// entering active state
VID_SetCaption (cls.servername->str);
@ -1167,7 +1167,7 @@ CL_SetState (cactive_t state)
// Auto demo recorder starts here
if (cl_autorecord->int_val && !cls.demoplayback
&& !cls.demorecording)
CL_Record (0);
CL_Record (0, -1);
}
}
if (con_module)
@ -1192,18 +1192,8 @@ CL_Init (void)
Cmd_AddCommand ("version", CL_Version_f, "Report version information");
Cmd_AddCommand ("changing", CL_Changing_f, "Used when maps are changing");
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "Disconnect from server");
Cmd_AddCommand ("record", CL_Record_f, "Record a demo, if no filename "
"argument is given\n"
"the demo will be called Year-Month-Day-Hour-Minute-"
"Mapname");
Cmd_AddCommand ("rerecord", CL_ReRecord_f, "Rerecord a demo on the same "
"server");
Cmd_AddCommand ("snap", CL_RSShot_f, "Take a screenshot and upload it to "
"the server");
Cmd_AddCommand ("stop", CL_Stop_f, "Stop recording a demo");
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "Play a recorded demo");
Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "Play a demo as fast as your "
"hardware can. Useful for benchmarking.");
Cmd_AddCommand ("maplist", Con_Maplist_f, "List maps available");
Cmd_AddCommand ("skinlist", Con_Skinlist_f, "List skins available");
Cmd_AddCommand ("skyboxlist", Con_Skyboxlist_f, "List skyboxes available");