summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/cl_demo.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/cl_demo.c')
-rw-r--r--apps/plugins/sdl/progs/quake/cl_demo.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/cl_demo.c b/apps/plugins/sdl/progs/quake/cl_demo.c
new file mode 100644
index 0000000000..45ddef3139
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/cl_demo.c
@@ -0,0 +1,367 @@
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20
21#include "quakedef.h"
22
23void CL_FinishTimeDemo (void);
24
25/*
26==============================================================================
27
28DEMO CODE
29
30When a demo is playing back, all NET_SendMessages are skipped, and
31NET_GetMessages are read from the demo file.
32
33Whenever cl.time gets past the last received message, another message is
34read from the demo file.
35==============================================================================
36*/
37
38/*
39==============
40CL_StopPlayback
41
42Called when a demo file runs out, or the user starts a game
43==============
44*/
45void CL_StopPlayback (void)
46{
47 if (!cls.demoplayback)
48 return;
49
50 fclose (cls.demofile);
51 cls.demoplayback = false;
52 cls.demofile = NULL;
53 cls.state = ca_disconnected;
54
55 if (cls.timedemo)
56 CL_FinishTimeDemo ();
57}
58
59/*
60====================
61CL_WriteDemoMessage
62
63Dumps the current net message, prefixed by the length and view angles
64====================
65*/
66void CL_WriteDemoMessage (void)
67{
68 int len;
69 int i;
70 float f;
71
72 len = LittleLong (net_message.cursize);
73 fwrite (&len, 4, 1, cls.demofile);
74 for (i=0 ; i<3 ; i++)
75 {
76 f = LittleFloat (cl.viewangles[i]);
77 fwrite (&f, 4, 1, cls.demofile);
78 }
79 fwrite (net_message.data, net_message.cursize, 1, cls.demofile);
80 fflush (cls.demofile);
81}
82
83/*
84====================
85CL_GetMessage
86
87Handles recording and playback of demos, on top of NET_ code
88====================
89*/
90int CL_GetMessage (void)
91{
92 int r, i;
93 float f;
94
95 if (cls.demoplayback)
96 {
97 // decide if it is time to grab the next message
98 if (cls.signon == SIGNONS) // allways grab until fully connected
99 {
100 if (cls.timedemo)
101 {
102 if (host_framecount == cls.td_lastframe)
103 return 0; // allready read this frame's message
104 cls.td_lastframe = host_framecount;
105 // if this is the second frame, grab the real td_starttime
106 // so the bogus time on the first frame doesn't count
107 if (host_framecount == cls.td_startframe + 1)
108 cls.td_starttime = realtime;
109 }
110 else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0])
111 {
112 return 0; // don't need another message yet
113 }
114 }
115
116 // get the next message
117 fread (&net_message.cursize, 4, 1, cls.demofile);
118 VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
119 for (i=0 ; i<3 ; i++)
120 {
121 r = fread (&f, 4, 1, cls.demofile);
122 cl.mviewangles[0][i] = LittleFloat (f);
123 }
124
125 net_message.cursize = LittleLong (net_message.cursize);
126 if (net_message.cursize > MAX_MSGLEN)
127 Sys_Error ("Demo message > MAX_MSGLEN");
128 r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
129 if (r != 1)
130 {
131 CL_StopPlayback ();
132 return 0;
133 }
134
135 return 1;
136 }
137
138 while (1)
139 {
140 r = NET_GetMessage (cls.netcon);
141
142 if (r != 1 && r != 2)
143 return r;
144
145 // discard nop keepalive message
146 if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
147 Con_Printf ("<-- server to client keepalive\n");
148 else
149 break;
150 }
151
152 if (cls.demorecording)
153 CL_WriteDemoMessage ();
154
155 return r;
156}
157
158
159/*
160====================
161CL_Stop_f
162
163stop recording a demo
164====================
165*/
166void CL_Stop_f (void)
167{
168 if (cmd_source != src_command)
169 return;
170
171 if (!cls.demorecording)
172 {
173 Con_Printf ("Not recording a demo.\n");
174 return;
175 }
176
177// write a disconnect message to the demo file
178 SZ_Clear (&net_message);
179 MSG_WriteByte (&net_message, svc_disconnect);
180 CL_WriteDemoMessage ();
181
182// finish up
183 fclose (cls.demofile);
184 cls.demofile = NULL;
185 cls.demorecording = false;
186 Con_Printf ("Completed demo\n");
187}
188
189/*
190====================
191CL_Record_f
192
193record <demoname> <map> [cd track]
194====================
195*/
196void CL_Record_f (void)
197{
198 int c;
199 char name[MAX_OSPATH];
200 int track;
201
202 if (cmd_source != src_command)
203 return;
204
205 c = Cmd_Argc();
206 if (c != 2 && c != 3 && c != 4)
207 {
208 Con_Printf ("record <demoname> [<map> [cd track]]\n");
209 return;
210 }
211
212 if (strstr(Cmd_Argv(1), ".."))
213 {
214 Con_Printf ("Relative pathnames are not allowed.\n");
215 return;
216 }
217
218 if (c == 2 && cls.state == ca_connected)
219 {
220 Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
221 return;
222 }
223
224// write the forced cd track number, or -1
225 if (c == 4)
226 {
227 track = atoi(Cmd_Argv(3));
228 Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
229 }
230 else
231 track = -1;
232
233 sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
234
235//
236// start the map up
237//
238 if (c > 2)
239 Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
240
241//
242// open the demo file
243//
244 COM_DefaultExtension (name, ".dem");
245
246 Con_Printf ("recording to %s.\n", name);
247 cls.demofile = fopen (name, "wb");
248 if (!cls.demofile)
249 {
250 Con_Printf ("ERROR: couldn't open.\n");
251 return;
252 }
253
254 cls.forcetrack = track;
255 fprintf (cls.demofile, "%i\n", cls.forcetrack);
256
257 cls.demorecording = true;
258}
259
260
261/*
262====================
263CL_PlayDemo_f
264
265play [demoname]
266====================
267*/
268void CL_PlayDemo_f (void)
269{
270 char name[256];
271 int c;
272 qboolean neg = false;
273
274 if (cmd_source != src_command)
275 return;
276
277 if (Cmd_Argc() != 2)
278 {
279 Con_Printf ("play <demoname> : plays a demo\n");
280 return;
281 }
282
283//
284// disconnect from server
285//
286 CL_Disconnect ();
287
288//
289// open the demo file
290//
291 strcpy (name, Cmd_Argv(1));
292 COM_DefaultExtension (name, ".dem");
293
294 Con_Printf ("Playing demo from %s.\n", name);
295 COM_FOpenFile (name, &cls.demofile);
296 if (!cls.demofile)
297 {
298 Con_Printf ("ERROR: couldn't open.\n");
299 cls.demonum = -1; // stop demo loop
300 return;
301 }
302
303 cls.demoplayback = true;
304 cls.state = ca_connected;
305 cls.forcetrack = 0;
306
307 while ((c = getc(cls.demofile)) != '\n')
308 if (c == '-')
309 neg = true;
310 else
311 cls.forcetrack = cls.forcetrack * 10 + (c - '0');
312
313 if (neg)
314 cls.forcetrack = -cls.forcetrack;
315// ZOID, fscanf is evil
316 //fscanf (cls.demofile, "%i\n", &cls.forcetrack);
317}
318
319/*
320====================
321CL_FinishTimeDemo
322
323====================
324*/
325void CL_FinishTimeDemo (void)
326{
327 int frames;
328 float time;
329
330 cls.timedemo = false;
331
332// the first frame didn't count
333 frames = (host_framecount - cls.td_startframe) - 1;
334 time = realtime - cls.td_starttime;
335 if (!time)
336 time = 1;
337 Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time);
338}
339
340/*
341====================
342CL_TimeDemo_f
343
344timedemo [demoname]
345====================
346*/
347void CL_TimeDemo_f (void)
348{
349 if (cmd_source != src_command)
350 return;
351
352 if (Cmd_Argc() != 2)
353 {
354 Con_Printf ("timedemo <demoname> : gets demo speeds\n");
355 return;
356 }
357
358 CL_PlayDemo_f ();
359
360// cls.td_starttime will be grabbed at the second frame of the demo, so
361// all the loading time doesn't get counted
362
363 cls.timedemo = true;
364 cls.td_startframe = host_framecount;
365 cls.td_lastframe = -1; // get a new message this frame
366}
367