From 514f085e8880a071cdc666b84e5b94ce5fba210d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Aug 2011 20:33:05 +0900 Subject: [PATCH] Reduce the diffs in cl_demo.c. Starting to look like a change in protocol rather than a complete rewrite. --- nq/include/client.h | 1 + nq/source/cl_demo.c | 261 +++++++++++++++++--------- qw/include/cl_demo.h | 10 +- qw/source/cl_demo.c | 422 ++++++++++++++++++++++--------------------- qw/source/cl_main.c | 16 +- 5 files changed, 402 insertions(+), 308 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index 41bdf561c..27ca00f17 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -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); diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 6ba232087..6b9d9968b 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -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 : 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 [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); } diff --git a/qw/include/cl_demo.h b/qw/include/cl_demo.h index 6a1cb32fb..8038f2d18 100644 --- a/qw/include/cl_demo.h +++ b/qw/include/cl_demo.h @@ -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); diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 5f2cb114c..a5d21b51c 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -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 @@ -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 +*/ +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 +*/ +static void +CL_ReRecord_f (void) +{ + dstring_t *name; + int c; + + c = Cmd_Argc (); + if (c != 2) { + Sys_Printf ("rerecord \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 -*/ -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 -*/ -void -CL_ReRecord_f (void) -{ - dstring_t *name; - int c; - - c = Cmd_Argc (); - if (c != 2) { - Sys_Printf ("rerecord \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 [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; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index ca0f31989..aba395fc5 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -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");