disable the unrecognized nls flag
[AROS-Contrib.git] / Games / Quake / cl_demo.c
blob550368e07f7d67bdd109f2302d002e3748e1b2a2
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "quakedef.h"
23 void CL_FinishTimeDemo (void);
26 ==============================================================================
28 DEMO CODE
30 When a demo is playing back, all NET_SendMessages are skipped, and
31 NET_GetMessages are read from the demo file.
33 Whenever cl.time gets past the last received message, another message is
34 read from the demo file.
35 ==============================================================================
39 ==============
40 CL_StopPlayback
42 Called when a demo file runs out, or the user starts a game
43 ==============
45 void CL_StopPlayback (void)
47 if (!cls.demoplayback)
48 return;
50 fclose (cls.demofile);
51 cls.demoplayback = false;
52 cls.demofile = NULL;
53 cls.state = ca_disconnected;
55 if (cls.timedemo)
56 CL_FinishTimeDemo ();
60 ====================
61 CL_WriteDemoMessage
63 Dumps the current net message, prefixed by the length and view angles
64 ====================
66 void CL_WriteDemoMessage (void)
68 int len;
69 int i;
70 float f;
72 len = LittleLong (net_message.cursize);
73 fwrite (&len, 4, 1, cls.demofile);
74 for (i=0 ; i<3 ; i++)
76 f = LittleFloat (cl.viewangles[i]);
77 fwrite (&f, 4, 1, cls.demofile);
79 fwrite (net_message.data, net_message.cursize, 1, cls.demofile);
80 fflush (cls.demofile);
84 ====================
85 CL_GetMessage
87 Handles recording and playback of demos, on top of NET_ code
88 ====================
90 int CL_GetMessage (void)
92 int r, i;
93 float f;
95 if (cls.demoplayback)
97 // decide if it is time to grab the next message
98 if (cls.signon == SIGNONS) // allways grab until fully connected
100 if (cls.timedemo)
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;
110 else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0])
112 return 0; // don't need another message yet
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++)
121 r = fread (&f, 4, 1, cls.demofile);
122 cl.mviewangles[0][i] = LittleFloat (f);
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)
131 CL_StopPlayback ();
132 return 0;
135 return 1;
138 while (1)
140 r = NET_GetMessage (cls.netcon);
142 if (r != 1 && r != 2)
143 return r;
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;
152 if (cls.demorecording)
153 CL_WriteDemoMessage ();
155 return r;
160 ====================
161 CL_Stop_f
163 stop recording a demo
164 ====================
166 void CL_Stop_f (void)
168 if (cmd_source != src_command)
169 return;
171 if (!cls.demorecording)
173 Con_Printf ("Not recording a demo.\n");
174 return;
177 // write a disconnect message to the demo file
178 SZ_Clear (&net_message);
179 MSG_WriteByte (&net_message, svc_disconnect);
180 CL_WriteDemoMessage ();
182 // finish up
183 fclose (cls.demofile);
184 cls.demofile = NULL;
185 cls.demorecording = false;
186 Con_Printf ("Completed demo\n");
190 ====================
191 CL_Record_f
193 record <demoname> <map> [cd track]
194 ====================
196 void CL_Record_f (void)
198 int c;
199 char name[MAX_OSPATH];
200 int track;
202 if (cmd_source != src_command)
203 return;
205 c = Cmd_Argc();
206 if (c != 2 && c != 3 && c != 4)
208 Con_Printf ("record <demoname> [<map> [cd track]]\n");
209 return;
212 if (strstr(Cmd_Argv(1), ".."))
214 Con_Printf ("Relative pathnames are not allowed.\n");
215 return;
218 if (c == 2 && cls.state == ca_connected)
220 Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
221 return;
224 // write the forced cd track number, or -1
225 if (c == 4)
227 track = atoi(Cmd_Argv(3));
228 Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
230 else
231 track = -1;
233 sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
236 // start the map up
238 if (c > 2)
239 Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
242 // open the demo file
244 COM_DefaultExtension (name, ".dem");
246 Con_Printf ("recording to %s.\n", name);
247 cls.demofile = fopen (name, "wb");
248 if (!cls.demofile)
250 Con_Printf ("ERROR: couldn't open.\n");
251 return;
254 cls.forcetrack = track;
255 fprintf (cls.demofile, "%i\n", cls.forcetrack);
257 cls.demorecording = true;
262 ====================
263 CL_PlayDemo_f
265 play [demoname]
266 ====================
268 void CL_PlayDemo_f (void)
270 char name[256];
271 int c;
272 qboolean neg = false;
274 if (cmd_source != src_command)
275 return;
277 if (Cmd_Argc() != 2)
279 Con_Printf ("play <demoname> : plays a demo\n");
280 return;
284 // disconnect from server
286 CL_Disconnect ();
289 // open the demo file
291 strcpy (name, Cmd_Argv(1));
292 COM_DefaultExtension (name, ".dem");
294 Con_Printf ("Playing demo from %s.\n", name);
295 COM_FOpenFile (name, &cls.demofile);
296 if (!cls.demofile)
298 Con_Printf ("ERROR: couldn't open.\n");
299 cls.demonum = -1; // stop demo loop
300 return;
303 cls.demoplayback = true;
304 cls.state = ca_connected;
305 cls.forcetrack = 0;
307 while ((c = getc(cls.demofile)) != '\n')
308 if (c == '-')
309 neg = true;
310 else
311 cls.forcetrack = cls.forcetrack * 10 + (c - '0');
313 if (neg)
314 cls.forcetrack = -cls.forcetrack;
315 // ZOID, fscanf is evil
316 // fscanf (cls.demofile, "%i\n", &cls.forcetrack);
320 ====================
321 CL_FinishTimeDemo
323 ====================
325 void CL_FinishTimeDemo (void)
327 int frames;
328 float time;
330 cls.timedemo = false;
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);
341 ====================
342 CL_TimeDemo_f
344 timedemo [demoname]
345 ====================
347 void CL_TimeDemo_f (void)
349 if (cmd_source != src_command)
350 return;
352 if (Cmd_Argc() != 2)
354 Con_Printf ("timedemo <demoname> : gets demo speeds\n");
355 return;
358 CL_PlayDemo_f ();
360 // cls.td_starttime will be grabbed at the second frame of the demo, so
361 // all the loading time doesn't get counted
363 cls.timedemo = true;
364 cls.td_startframe = host_framecount;
365 cls.td_lastframe = -1; // get a new message this frame