diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/cl_demo.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/cl_demo.c | 367 |
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 | /* | ||
2 | Copyright (C) 1996-1997 Id Software, Inc. | ||
3 | |||
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. | ||
8 | |||
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. | ||
12 | |||
13 | See the GNU General Public License for more details. | ||
14 | |||
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. | ||
18 | |||
19 | */ | ||
20 | |||
21 | #include "quakedef.h" | ||
22 | |||
23 | void CL_FinishTimeDemo (void); | ||
24 | |||
25 | /* | ||
26 | ============================================================================== | ||
27 | |||
28 | DEMO CODE | ||
29 | |||
30 | When a demo is playing back, all NET_SendMessages are skipped, and | ||
31 | NET_GetMessages are read from the demo file. | ||
32 | |||
33 | Whenever cl.time gets past the last received message, another message is | ||
34 | read from the demo file. | ||
35 | ============================================================================== | ||
36 | */ | ||
37 | |||
38 | /* | ||
39 | ============== | ||
40 | CL_StopPlayback | ||
41 | |||
42 | Called when a demo file runs out, or the user starts a game | ||
43 | ============== | ||
44 | */ | ||
45 | void 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 | ==================== | ||
61 | CL_WriteDemoMessage | ||
62 | |||
63 | Dumps the current net message, prefixed by the length and view angles | ||
64 | ==================== | ||
65 | */ | ||
66 | void 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 | ==================== | ||
85 | CL_GetMessage | ||
86 | |||
87 | Handles recording and playback of demos, on top of NET_ code | ||
88 | ==================== | ||
89 | */ | ||
90 | int 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 | ==================== | ||
161 | CL_Stop_f | ||
162 | |||
163 | stop recording a demo | ||
164 | ==================== | ||
165 | */ | ||
166 | void 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 | ==================== | ||
191 | CL_Record_f | ||
192 | |||
193 | record <demoname> <map> [cd track] | ||
194 | ==================== | ||
195 | */ | ||
196 | void 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 | ==================== | ||
263 | CL_PlayDemo_f | ||
264 | |||
265 | play [demoname] | ||
266 | ==================== | ||
267 | */ | ||
268 | void 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 | ==================== | ||
321 | CL_FinishTimeDemo | ||
322 | |||
323 | ==================== | ||
324 | */ | ||
325 | void 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 | ==================== | ||
342 | CL_TimeDemo_f | ||
343 | |||
344 | timedemo [demoname] | ||
345 | ==================== | ||
346 | */ | ||
347 | void 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 | |||