3
|
1 /* $Id: recorder.c,v 1.1.1.1 1997/12/06 05:41:30 darius Exp $ */
|
|
2
|
|
3 #ifdef RECORDER
|
|
4
|
|
5 #include <stdio.h>
|
|
6 #include <sys/types.h>
|
|
7 #include <sys/file.h>
|
|
8 #include <sys/stat.h>
|
|
9 #include <sys/select.h>
|
|
10 #include <fcntl.h>
|
|
11
|
|
12 #include "Wlib.h"
|
|
13 #include "defs.h"
|
|
14 #include "struct.h"
|
|
15 #include "data.h"
|
|
16 #include "proto.h"
|
|
17 #include "packets.h"
|
|
18
|
|
19 int record_total;
|
|
20 int lastTeamReq = -1;
|
|
21 int recfp = -1, playfp = -1;
|
|
22
|
|
23 void pb_skip P((int frames));
|
|
24
|
|
25 void
|
|
26 startRecorder()
|
|
27 {
|
|
28 if (recordGame = booleanDefault("recordGame", recordGame)) {
|
|
29 recordFile = stringDefault("recordFile", "/tmp/netrek.record");
|
|
30 recordFile = expandFilename(recordFile);
|
|
31 maxRecord = intDefault("maxRecord", maxRecord);
|
|
32 recfp = open(recordFile, O_WRONLY | O_TRUNC | O_APPEND | O_CREAT, S_IRWXU);
|
|
33 if (recfp >= 0)
|
|
34 printf("Game being recorded to %s. Max size is %d\n", recordFile, maxRecord);
|
|
35 else {
|
|
36 perror("startRecorder");
|
|
37 printf("Can't open file %s for recording\n", recordFile);
|
|
38 recordGame = 0;
|
|
39 }
|
|
40 }
|
|
41 }
|
|
42
|
|
43 void
|
|
44 stopRecorder()
|
|
45 {
|
|
46 char buf[80];
|
|
47
|
|
48 close(recfp);
|
|
49 recfp = -1;
|
|
50 recordGame = 0;
|
|
51 sprintf(buf, "Recording stopped, %d bytes (%d updates) written to %s\n",
|
|
52 record_total, udcounter, (recordFile==NULL) ? "Nothing" : recordFile);
|
|
53 warning(buf);
|
|
54 }
|
|
55
|
|
56 void
|
|
57 recordPacket(data, len)
|
|
58 char *data;
|
|
59 int len;
|
|
60 {
|
|
61 int res;
|
|
62
|
|
63 if (recfp >= 0 && len > 0) {
|
|
64 switch (*data) {
|
|
65 case SP_PICKOK: /* playback needs to know what team! */
|
|
66 data[2] = (char) lastTeamReq;
|
|
67 break;
|
|
68 case SP_RSA_KEY:
|
|
69 case SP_MOTD:
|
|
70 case SP_MOTD_PIC:
|
|
71 case SP_NEW_MOTD:
|
|
72 return;
|
|
73 default:
|
|
74 break;
|
|
75 }
|
|
76 res = write(recfp, data, len);
|
|
77 record_total += res;
|
|
78 if ((maxRecord && (record_total > maxRecord)) || (res <= 0))
|
|
79 stopRecorder();
|
|
80 }
|
|
81 }
|
|
82
|
|
83 void
|
|
84 writeUpdateMarker()
|
|
85 {
|
|
86 unsigned char update_buf[4];
|
|
87
|
|
88 update_buf[0] = REC_UPDATE;
|
|
89 /*
|
|
90 record stuff not normally sent by server. Otherwise tractors and lock
|
|
91 markers don't work during playback
|
|
92 */
|
|
93 update_buf[1] = (unsigned char) me->p_tractor;
|
|
94 update_buf[2] = (unsigned char) ((me->p_flags & PFPLOCK) ? me->p_playerl : me->p_planet);
|
|
95 /* one more byte here, any ideas? */
|
|
96 record_total += write(recfp, update_buf, 4);
|
|
97 }
|
|
98
|
|
99 int
|
|
100 startPlayback()
|
|
101 {
|
|
102 if (playback || (playback = booleanDefault("playback", 0))) {
|
|
103 if (!playFile)
|
|
104 playFile = stringDefault("playFile", "/tmp/netrek.record");
|
|
105 playFile = expandFilename(playFile);
|
|
106
|
|
107 playfp = open(playFile, O_RDONLY, 0);
|
|
108 if (playfp < 0) {
|
|
109 perror("startPlayback");
|
|
110 printf("Couldn't open playback file %s\n", playFile);
|
|
111 exit(0);
|
|
112 }
|
|
113 printf("Replaying %s\n", playFile);
|
|
114 return 1;
|
|
115 }
|
|
116 return 0;
|
|
117 }
|
|
118
|
|
119 int
|
|
120 readRecorded(fp, data, len)
|
|
121 int fp, len;
|
|
122 char *data;
|
|
123 {
|
|
124 int ret;
|
|
125
|
|
126 if (!playback || len < 0 || playfp < 0)
|
|
127 return -1;
|
|
128 if (len > 4) /* make sure we don't skip updates */
|
|
129 len = 4;
|
|
130 ret = read(playfp, data, len);
|
|
131 if (ret <= 0)
|
|
132 EXIT(0);
|
|
133 return ret;
|
|
134 }
|
|
135
|
|
136 void
|
|
137 pb_dokey(event)
|
|
138 W_Event *event;
|
|
139 {
|
|
140 switch (event->key&0xff) {
|
|
141 case 'p':
|
|
142 case 'P':
|
|
143 paused = !paused;
|
|
144 pb_scan=0;
|
|
145 if (paused)
|
|
146 pb_advance = 0;
|
|
147 break;
|
|
148 case 'r':
|
|
149 case 'R':
|
|
150 pb_advance = PB_REDALERT;
|
|
151 paused = 0;
|
|
152 break;
|
|
153 case 'y':
|
|
154 case 'Y':
|
|
155 pb_advance = PB_YELLOWALERT;
|
|
156 paused = 0;
|
|
157 break;
|
|
158 case 'd':
|
|
159 case 'D':
|
|
160 pb_advance = PB_DEATH;
|
|
161 paused = 0;
|
|
162 break;
|
|
163 case ' ':
|
|
164 if(paused) {
|
|
165 if(pb_scan)
|
|
166 pb_skip(pb_advance);
|
|
167 else {
|
|
168 pb_advance=1;
|
|
169 paused=0;
|
|
170 }
|
|
171 } else {
|
|
172 paused = 1;
|
|
173 pb_advance=0;
|
|
174 }
|
|
175 break;
|
|
176 case 'f':
|
|
177 case 'F': /* fast forward */
|
|
178 pb_scan=!pb_scan;
|
|
179 if(pb_scan) {
|
|
180 pb_advance=10;
|
|
181 pb_slow=0;
|
|
182 paused=0;
|
|
183 warning("1-9: set speed. P-Pause, F-Fast Fwd off");
|
|
184 } else {
|
|
185 pb_advance=0;
|
|
186 pb_slow=0;
|
|
187 paused=0;
|
|
188 warning("Playback mode, keys: P)ause R)ed Y)ellow D)eath F)ast Q)uit");
|
|
189 }
|
|
190 break;
|
|
191 case 's': /* Slow mode */
|
|
192 case 'S':
|
|
193 if(pb_scan || paused || !pb_slow)
|
|
194 pb_slow=1;
|
|
195 else
|
|
196 pb_slow=0;
|
|
197 pb_scan=0;
|
|
198 paused=0;
|
|
199 pb_advance=0;
|
|
200 break;
|
|
201 case '1':
|
|
202 case '2':
|
|
203 case '3':
|
|
204 case '4':
|
|
205 case '5':
|
|
206 case '6':
|
|
207 case '7':
|
|
208 case '8':
|
|
209 case '9':
|
|
210 if(!pb_scan)
|
|
211 pb_advance += (event->key - '0') * 10;
|
|
212 else
|
|
213 pb_advance = (event->key - '0') * 10;
|
|
214 paused = 0;
|
|
215 break;
|
|
216 case 'q':
|
|
217 case 'Q':
|
|
218 exit(0);
|
|
219 default:
|
|
220 warning("Playback mode, keys: P)ause R)ed Y)ellow D)eath F)ast Q)uit");
|
|
221 }
|
|
222 }
|
|
223
|
|
224 void
|
|
225 pb_skip(frames)
|
|
226 int frames;
|
|
227 {
|
|
228 while(frames) {
|
|
229 pb_update=0;
|
|
230 readFromServer();
|
|
231 frames-=pb_update;
|
|
232 udcounter+=pb_update;
|
|
233 }
|
|
234 }
|
|
235
|
|
236 void
|
|
237 pb_framectr(xloc, yloc)
|
|
238 int xloc, yloc;
|
|
239 {
|
|
240 char buf[20];
|
|
241
|
|
242 if(paused)
|
|
243 strcpy(buf,"PAU");
|
|
244 else if(pb_scan)
|
|
245 strcpy(buf,"FFW");
|
|
246 else if(pb_advance) {
|
|
247 switch(pb_advance) {
|
|
248 case PB_REDALERT:
|
|
249 strcpy(buf,"RED");
|
|
250 break;
|
|
251 case PB_YELLOWALERT:
|
|
252 strcpy(buf,"YLW");
|
|
253 break;
|
|
254 case PB_DEATH:
|
|
255 strcpy(buf,"DTH");
|
|
256 break;
|
|
257 default:
|
|
258 buf[0]='+';
|
|
259 buf[1]=(pb_advance / 10) + '0';
|
|
260 buf[2]=(pb_advance % 10) + '0';
|
|
261 break;
|
|
262 }
|
|
263 } else if(pb_slow)
|
|
264 strcpy(buf,"SLW");
|
|
265 else
|
|
266 strcpy(buf,"NRM");
|
|
267
|
|
268 sprintf((buf+3),":%8d",udcounter);
|
|
269
|
|
270 W_WriteText(tstatw, xloc, yloc, textColor, buf, 12, W_RegularFont);
|
|
271 }
|
|
272
|
|
273 void
|
|
274 pb_input()
|
|
275 {
|
|
276 W_Event data;
|
|
277 fd_set readfds;
|
|
278 int wsock = W_Socket();
|
|
279
|
|
280 struct timeval timeout;
|
|
281
|
|
282 timeout.tv_sec = 0;
|
|
283 timeout.tv_usec = 200000;
|
|
284
|
|
285 intrupt(); /* draws the first frame */
|
|
286
|
|
287 while (me->p_status == PALIVE ||
|
|
288 me->p_status == PEXPLODE ||
|
|
289 me->p_status == PDEAD ||
|
|
290 me->p_status == POBSERVE) {
|
|
291
|
|
292 if (keepInfo > 0) {
|
|
293 if (infowin_up >= 0 &&
|
|
294 --infowin_up == -1 &&
|
|
295 infomapped) {
|
|
296 destroyInfo();
|
|
297 infowin_up = -2;
|
|
298 }
|
|
299 }
|
|
300 exitInputLoop = 0;
|
|
301 while (W_EventsPending() && !exitInputLoop) {
|
|
302 fastQuit = 0; /* any event cancel fastquit */
|
|
303 W_NextEvent(&data);
|
|
304 dispatch_W_event(&data);
|
|
305 }
|
|
306 if (!paradise) /* stars are ok, it's just a recording.
|
|
307 zoom doesn't make sense. */
|
|
308 blk_zoom = 0;
|
|
309
|
|
310 #ifndef AMIGA
|
|
311 FD_ZERO(&readfds);
|
|
312 FD_SET(wsock, &readfds);
|
|
313 if (paused) {
|
|
314 select(32, &readfds, (fd_set *) 0, (fd_set *) 0, 0);
|
|
315 continue;
|
|
316 } else if(pb_slow && !pb_scan)
|
|
317 select(32, &readfds, (fd_set *) 0, (fd_set *) 0,&timeout);
|
|
318
|
|
319 /* otherwise, in full blast mode, don't wait on anything. */
|
|
320
|
|
321 #else /* AMIGA */
|
|
322 if (paused) {
|
|
323 sigsPending = Wait(wsock | SIGBREAKF_CTRL_C);
|
|
324 continue;
|
|
325 } else if(pb_slow && !pb_scan) {
|
|
326 StartTimer(0,200000);
|
|
327 while(1) {
|
|
328 sigsPending = Wait(wsock | portmask | SIGBREAKF_CTRL_C);
|
|
329 if((sigsPending & (wsock | SIGBREAKF_CTRL_C)) ||
|
|
330 CheckIO(&(ior->tr_node)))
|
|
331 break;
|
|
332 }
|
|
333
|
|
334 StopTimer();
|
|
335 }
|
|
336
|
|
337 if (sigsPending & SIGBREAKF_CTRL_C) {
|
|
338 printf("User break, Ctrl-C, exiting!\n");
|
|
339 exit(0);
|
|
340 }
|
|
341 #endif /* AMIGA */
|
|
342 /* at this point, we're sure it's time for at least one frame. */
|
|
343 intrupt();
|
|
344 }
|
|
345 }
|
|
346
|
|
347 #endif
|