File: qcommon\common.c
1 /*
2 Copyright (C) 1997-2001 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 // common.c -- misc functions used in client and server
21 #include "qcommon.h"
22 #include <setjmp.h>
23
24 #define MAXPRINTMSG 4096
25
26 #define MAX_NUM_ARGVS 50
27
28
29 int com_argc;
30 char *com_argv[MAX_NUM_ARGVS+1];
31
32 int realtime;
33
34 jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame
35
36
37 FILE *log_stats_file;
38
39 cvar_t *host_speeds;
40 cvar_t *log_stats;
41 cvar_t *developer;
42 cvar_t *timescale;
43 cvar_t *fixedtime;
44 cvar_t *logfile_active; // 1 = buffer log, 2 = flush after each print
45 cvar_t *showtrace;
46 cvar_t *dedicated;
47
48 FILE *logfile;
49
50 int server_state;
51
52 // host_speeds times
53 int time_before_game;
54 int time_after_game;
55 int time_before_ref;
56 int time_after_ref;
57
58 /*
59 ============================================================================
60
61 CLIENT / SERVER interactions
62
63 ============================================================================
64 */
65
66 static int rd_target;
67 static char *rd_buffer;
68 static int rd_buffersize;
69 static void (*rd_flush)(int target, char *buffer);
70
71 void Com_BeginRedirect (int target, char *buffer, int buffersize, void (*flush))
72 {
73 if (!target || !buffer || !buffersize || !flush)
74 return;
75 rd_target = target;
76 rd_buffer = buffer;
77 rd_buffersize = buffersize;
78 rd_flush = flush;
79
80 *rd_buffer = 0;
81 }
82
83 void Com_EndRedirect (void)
84 {
85 rd_flush(rd_target, rd_buffer);
86
87 rd_target = 0;
88 rd_buffer = NULL;
89 rd_buffersize = 0;
90 rd_flush = NULL;
91 }
92
93 /*
94 =============
95 Com_Printf
96
97 Both client and server can use this, and it will output
98 to the apropriate place.
99 =============
100 */
101 void Com_Printf (char *fmt, ...)
102 {
103 va_list argptr;
104 char msg[MAXPRINTMSG];
105
106 va_start (argptr,fmt);
107 vsprintf (msg,fmt,argptr);
108 va_end (argptr);
109
110 if (rd_target)
111 {
112 if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1))
113 {
114 rd_flush(rd_target, rd_buffer);
115 *rd_buffer = 0;
116 }
117 strcat (rd_buffer, msg);
118 return;
119 }
120
121 Con_Print (msg);
122
123 // also echo to debugging console
124 Sys_ConsoleOutput (msg);
125
126 // logfile
127 if (logfile_active && logfile_active->value)
128 {
129 char name[MAX_QPATH];
130
131 if (!logfile)
132 {
133 Com_sprintf (name, sizeof(name), "%s/qconsole.log", FS_Gamedir ());
134 if (logfile_active->value > 2)
135 logfile = fopen (name, "a");
136 else
137 logfile = fopen (name, "w");
138 }
139 if (logfile)
140 fprintf (logfile, "%s", msg);
141 if (logfile_active->value > 1)
142 fflush (logfile); // force it to save every time
143 }
144 }
145
146
147 /*
148 ================
149 Com_DPrintf
150
151 A Com_Printf that only shows up if the "developer" cvar is set
152 ================
153 */
154 void Com_DPrintf (char *fmt, ...)
155 {
156 va_list argptr;
157 char msg[MAXPRINTMSG];
158
159 if (!developer || !developer->value)
160 return; // don't confuse non-developers with techie stuff...
161
162 va_start (argptr,fmt);
163 vsprintf (msg,fmt,argptr);
164 va_end (argptr);
165
166 Com_Printf ("%s", msg);
167 }
168
169
170 /*
171 =============
172 Com_Error
173
174 Both client and server can use this, and it will
175 do the apropriate things.
176 =============
177 */
178 void Com_Error (int code, char *fmt, ...)
179 {
180 va_list argptr;
181 static char msg[MAXPRINTMSG];
182 static qboolean recursive;
183
184 if (recursive)
185 Sys_Error ("recursive error after: %s", msg);
186 recursive = true;
187
188 va_start (argptr,fmt);
189 vsprintf (msg,fmt,argptr);
190 va_end (argptr);
191
192 if (code == ERR_DISCONNECT)
193 {
194 CL_Drop ();
195 recursive = false;
196 longjmp (abortframe, -1);
197 }
198 else if (code == ERR_DROP)
199 {
200 Com_Printf ("********************\nERROR: %s\n********************\n", msg);
201 SV_Shutdown (va("Server crashed: %s\n", msg), false);
202 CL_Drop ();
203 recursive = false;
204 longjmp (abortframe, -1);
205 }
206 else
207 {
208 SV_Shutdown (va("Server fatal crashed: %s\n", msg), false);
209 CL_Shutdown ();
210 }
211
212 if (logfile)
213 {
214 fclose (logfile);
215 logfile = NULL;
216 }
217
218 Sys_Error ("%s", msg);
219 }
220
221
222 /*
223 =============
224 Com_Quit
225
226 Both client and server can use this, and it will
227 do the apropriate things.
228 =============
229 */
230 void Com_Quit (void)
231 {
232 SV_Shutdown ("Server quit\n", false);
233 CL_Shutdown ();
234
235 if (logfile)
236 {
237 fclose (logfile);
238 logfile = NULL;
239 }
240
241 Sys_Quit ();
242 }
243
244
245 /*
246 ==================
247 Com_ServerState
248 ==================
249 */
250 int Com_ServerState (void)
251 {
252 return server_state;
253 }
254
255 /*
256 ==================
257 Com_SetServerState
258 ==================
259 */
260 void Com_SetServerState (int state)
261 {
262 server_state = state;
263 }
264
265
266 /*
267 ==============================================================================
268
269 MESSAGE IO FUNCTIONS
270
271 Handles byte ordering and avoids alignment errors
272 ==============================================================================
273 */
274
275 vec3_t bytedirs[NUMVERTEXNORMALS] =
276 {
277 #include "../client/anorms.h"
278 };
279
280 //
281 // writing functions
282 //
283
284 void MSG_WriteChar (sizebuf_t *sb, int c)
285 {
286 byte *buf;
287
288 #ifdef PARANOID
291 #endif
292
293 buf = SZ_GetSpace (sb, 1);
294 buf[0] = c;
295 }
296
297 void MSG_WriteByte (sizebuf_t *sb, int c)
298 {
299 byte *buf;
300
301 #ifdef PARANOID
304 #endif
305
306 buf = SZ_GetSpace (sb, 1);
307 buf[0] = c;
308 }
309
310 void MSG_WriteShort (sizebuf_t *sb, int c)
311 {
312 byte *buf;
313
314 #ifdef PARANOID
317 #endif
318
319 buf = SZ_GetSpace (sb, 2);
320 buf[0] = c&0xff;
321 buf[1] = c>>8;
322 }
323
324 void MSG_WriteLong (sizebuf_t *sb, int c)
325 {
326 byte *buf;
327
328 buf = SZ_GetSpace (sb, 4);
329 buf[0] = c&0xff;
330 buf[1] = (c>>8)&0xff;
331 buf[2] = (c>>16)&0xff;
332 buf[3] = c>>24;
333 }
334
335 void MSG_WriteFloat (sizebuf_t *sb, float f)
336 {
337 union
338 {
339 float f;
340 int l;
341 } dat;
342
343
344 dat.f = f;
345 dat.l = LittleLong (dat.l);
346
347 SZ_Write (sb, &dat.l, 4);
348 }
349
350 void MSG_WriteString (sizebuf_t *sb, char *s)
351 {
352 if (!s)
353 SZ_Write (sb, "", 1);
354 else
355 SZ_Write (sb, s, strlen(s)+1);
356 }
357
358 void MSG_WriteCoord (sizebuf_t *sb, float f)
359 {
360 MSG_WriteShort (sb, (int)(f*8));
361 }
362
363 void MSG_WritePos (sizebuf_t *sb, vec3_t pos)
364 {
365 MSG_WriteShort (sb, (int)(pos[0]*8));
366 MSG_WriteShort (sb, (int)(pos[1]*8));
367 MSG_WriteShort (sb, (int)(pos[2]*8));
368 }
369
370 void MSG_WriteAngle (sizebuf_t *sb, float f)
371 {
372 MSG_WriteByte (sb, (int)(f*256/360) & 255);
373 }
374
375 void MSG_WriteAngle16 (sizebuf_t *sb, float f)
376 {
377 MSG_WriteShort (sb, ANGLE2SHORT(f));
378 }
379
380
381 void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
382 {
383 int bits;
384
385 //
386 // send the movement message
387 //
388 bits = 0;
389 if (cmd->angles[0] != from->angles[0])
390 bits |= CM_ANGLE1;
391 if (cmd->angles[1] != from->angles[1])
392 bits |= CM_ANGLE2;
393 if (cmd->angles[2] != from->angles[2])
394 bits |= CM_ANGLE3;
395 if (cmd->forwardmove != from->forwardmove)
396 bits |= CM_FORWARD;
397 if (cmd->sidemove != from->sidemove)
398 bits |= CM_SIDE;
399 if (cmd->upmove != from->upmove)
400 bits |= CM_UP;
401 if (cmd->buttons != from->buttons)
402 bits |= CM_BUTTONS;
403 if (cmd->impulse != from->impulse)
404 bits |= CM_IMPULSE;
405
406 MSG_WriteByte (buf, bits);
407
408 if (bits & CM_ANGLE1)
409 MSG_WriteShort (buf, cmd->angles[0]);
410 if (bits & CM_ANGLE2)
411 MSG_WriteShort (buf, cmd->angles[1]);
412 if (bits & CM_ANGLE3)
413 MSG_WriteShort (buf, cmd->angles[2]);
414
415 if (bits & CM_FORWARD)
416 MSG_WriteShort (buf, cmd->forwardmove);
417 if (bits & CM_SIDE)
418 MSG_WriteShort (buf, cmd->sidemove);
419 if (bits & CM_UP)
420 MSG_WriteShort (buf, cmd->upmove);
421
422 if (bits & CM_BUTTONS)
423 MSG_WriteByte (buf, cmd->buttons);
424 if (bits & CM_IMPULSE)
425 MSG_WriteByte (buf, cmd->impulse);
426
427 MSG_WriteByte (buf, cmd->msec);
428 MSG_WriteByte (buf, cmd->lightlevel);
429 }
430
431
432 void MSG_WriteDir (sizebuf_t *sb, vec3_t dir)
433 {
434 int i, best;
435 float d, bestd;
436
437 if (!dir)
438 {
439 MSG_WriteByte (sb, 0);
440 return;
441 }
442
443 bestd = 0;
444 best = 0;
445 for (i=0 ; i<NUMVERTEXNORMALS ; i++)
446 {
447 d = DotProduct (dir, bytedirs[i]);
448 if (d > bestd)
449 {
450 bestd = d;
451 best = i;
452 }
453 }
454 MSG_WriteByte (sb, best);
455 }
456
457
458 void MSG_ReadDir (sizebuf_t *sb, vec3_t dir)
459 {
460 int b;
461
462 b = MSG_ReadByte (sb);
463 if (b >= NUMVERTEXNORMALS)
464 Com_Error (ERR_DROP, "MSF_ReadDir: out of range");
465 VectorCopy (bytedirs[b], dir);
466 }
467
468
469 /*
470 ==================
471 MSG_WriteDeltaEntity
472
473 Writes part of a packetentities message.
474 Can delta from either a baseline or a previous packet_entity
475 ==================
476 */
477 void MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity)
478 {
479 int bits;
480
481 if (!to->number)
482 Com_Error (ERR_FATAL, "Unset entity number");
483 if (to->number >= MAX_EDICTS)
484 Com_Error (ERR_FATAL, "Entity number >= MAX_EDICTS");
485
486 // send an update
487 bits = 0;
488
489 if (to->number >= 256)
490 bits |= U_NUMBER16; // number8 is implicit otherwise
491
492 if (to->origin[0] != from->origin[0])
493 bits |= U_ORIGIN1;
494 if (to->origin[1] != from->origin[1])
495 bits |= U_ORIGIN2;
496 if (to->origin[2] != from->origin[2])
497 bits |= U_ORIGIN3;
498
499 if ( to->angles[0] != from->angles[0] )
500 bits |= U_ANGLE1;
501 if ( to->angles[1] != from->angles[1] )
502 bits |= U_ANGLE2;
503 if ( to->angles[2] != from->angles[2] )
504 bits |= U_ANGLE3;
505
506 if ( to->skinnum != from->skinnum )
507 {
508 if ((unsigned)to->skinnum < 256)
509 bits |= U_SKIN8;
510 else if ((unsigned)to->skinnum < 0x10000)
511 bits |= U_SKIN16;
512 else
513 bits |= (U_SKIN8|U_SKIN16);
514 }
515
516 if ( to->frame != from->frame )
517 {
518 if (to->frame < 256)
519 bits |= U_FRAME8;
520 else
521 bits |= U_FRAME16;
522 }
523
524 if ( to->effects != from->effects )
525 {
526 if (to->effects < 256)
527 bits |= U_EFFECTS8;
528 else if (to->effects < 0x8000)
529 bits |= U_EFFECTS16;
530 else
531 bits |= U_EFFECTS8|U_EFFECTS16;
532 }
533
534 if ( to->renderfx != from->renderfx )
535 {
536 if (to->renderfx < 256)
537 bits |= U_RENDERFX8;
538 else if (to->renderfx < 0x8000)
539 bits |= U_RENDERFX16;
540 else
541 bits |= U_RENDERFX8|U_RENDERFX16;
542 }
543
544 if ( to->solid != from->solid )
545 bits |= U_SOLID;
546
547 // event is not delta compressed, just 0 compressed
548 if ( to->event )
549 bits |= U_EVENT;
550
551 if ( to->modelindex != from->modelindex )
552 bits |= U_MODEL;
553 if ( to->modelindex2 != from->modelindex2 )
554 bits |= U_MODEL2;
555 if ( to->modelindex3 != from->modelindex3 )
556 bits |= U_MODEL3;
557 if ( to->modelindex4 != from->modelindex4 )
558 bits |= U_MODEL4;
559
560 if ( to->sound != from->sound )
561 bits |= U_SOUND;
562
563 if (newentity || (to->renderfx & RF_BEAM))
564 bits |= U_OLDORIGIN;
565
566 //
567 // write the message
568 //
569 if (!bits && !force)
570 return; // nothing to send!
571
572 //----------
573
574 if (bits & 0xff000000)
575 bits |= U_MOREBITS3 | U_MOREBITS2 | U_MOREBITS1;
576 else if (bits & 0x00ff0000)
577 bits |= U_MOREBITS2 | U_MOREBITS1;
578 else if (bits & 0x0000ff00)
579 bits |= U_MOREBITS1;
580
581 MSG_WriteByte (msg, bits&255 );
582
583 if (bits & 0xff000000)
584 {
585 MSG_WriteByte (msg, (bits>>8)&255 );
586 MSG_WriteByte (msg, (bits>>16)&255 );
587 MSG_WriteByte (msg, (bits>>24)&255 );
588 }
589 else if (bits & 0x00ff0000)
590 {
591 MSG_WriteByte (msg, (bits>>8)&255 );
592 MSG_WriteByte (msg, (bits>>16)&255 );
593 }
594 else if (bits & 0x0000ff00)
595 {
596 MSG_WriteByte (msg, (bits>>8)&255 );
597 }
598
599 //----------
600
601 if (bits & U_NUMBER16)
602 MSG_WriteShort (msg, to->number);
603 else
604 MSG_WriteByte (msg, to->number);
605
606 if (bits & U_MODEL)
607 MSG_WriteByte (msg, to->modelindex);
608 if (bits & U_MODEL2)
609 MSG_WriteByte (msg, to->modelindex2);
610 if (bits & U_MODEL3)
611 MSG_WriteByte (msg, to->modelindex3);
612 if (bits & U_MODEL4)
613 MSG_WriteByte (msg, to->modelindex4);
614
615 if (bits & U_FRAME8)
616 MSG_WriteByte (msg, to->frame);
617 if (bits & U_FRAME16)
618 MSG_WriteShort (msg, to->frame);
619
620 if ((bits & U_SKIN8) && (bits & U_SKIN16)) //used for laser colors
621 MSG_WriteLong (msg, to->skinnum);
622 else if (bits & U_SKIN8)
623 MSG_WriteByte (msg, to->skinnum);
624 else if (bits & U_SKIN16)
625 MSG_WriteShort (msg, to->skinnum);
626
627
628 if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
629 MSG_WriteLong (msg, to->effects);
630 else if (bits & U_EFFECTS8)
631 MSG_WriteByte (msg, to->effects);
632 else if (bits & U_EFFECTS16)
633 MSG_WriteShort (msg, to->effects);
634
635 if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
636 MSG_WriteLong (msg, to->renderfx);
637 else if (bits & U_RENDERFX8)
638 MSG_WriteByte (msg, to->renderfx);
639 else if (bits & U_RENDERFX16)
640 MSG_WriteShort (msg, to->renderfx);
641
642 if (bits & U_ORIGIN1)
643 MSG_WriteCoord (msg, to->origin[0]);
644 if (bits & U_ORIGIN2)
645 MSG_WriteCoord (msg, to->origin[1]);
646 if (bits & U_ORIGIN3)
647 MSG_WriteCoord (msg, to->origin[2]);
648
649 if (bits & U_ANGLE1)
650 MSG_WriteAngle(msg, to->angles[0]);
651 if (bits & U_ANGLE2)
652 MSG_WriteAngle(msg, to->angles[1]);
653 if (bits & U_ANGLE3)
654 MSG_WriteAngle(msg, to->angles[2]);
655
656 if (bits & U_OLDORIGIN)
657 {
658 MSG_WriteCoord (msg, to->old_origin[0]);
659 MSG_WriteCoord (msg, to->old_origin[1]);
660 MSG_WriteCoord (msg, to->old_origin[2]);
661 }
662
663 if (bits & U_SOUND)
664 MSG_WriteByte (msg, to->sound);
665 if (bits & U_EVENT)
666 MSG_WriteByte (msg, to->event);
667 if (bits & U_SOLID)
668 MSG_WriteShort (msg, to->solid);
669 }
670
671
672 //============================================================
673
674 //
675 // reading functions
676 //
677
678 void MSG_BeginReading (sizebuf_t *msg)
679 {
680 msg->readcount = 0;
681 }
682
683 // returns -1 if no more characters are available
684 int MSG_ReadChar (sizebuf_t *msg_read)
685 {
686 int c;
687
688 if (msg_read->readcount+1 > msg_read->cursize)
689 c = -1;
690 else
691 c = (signed char)msg_read->data[msg_read->readcount];
692 msg_read->readcount++;
693
694 return c;
695 }
696
697 int MSG_ReadByte (sizebuf_t *msg_read)
698 {
699 int c;
700
701 if (msg_read->readcount+1 > msg_read->cursize)
702 c = -1;
703 else
704 c = (unsigned char)msg_read->data[msg_read->readcount];
705 msg_read->readcount++;
706
707 return c;
708 }
709
710 int MSG_ReadShort (sizebuf_t *msg_read)
711 {
712 int c;
713
714 if (msg_read->readcount+2 > msg_read->cursize)
715 c = -1;
716 else
717 c = (short)(msg_read->data[msg_read->readcount]
718 + (msg_read->data[msg_read->readcount+1]<<8));
719
720 msg_read->readcount += 2;
721
722 return c;
723 }
724
725 int MSG_ReadLong (sizebuf_t *msg_read)
726 {
727 int c;
728
729 if (msg_read->readcount+4 > msg_read->cursize)
730 c = -1;
731 else
732 c = msg_read->data[msg_read->readcount]
733 + (msg_read->data[msg_read->readcount+1]<<8)
734 + (msg_read->data[msg_read->readcount+2]<<16)
735 + (msg_read->data[msg_read->readcount+3]<<24);
736
737 msg_read->readcount += 4;
738
739 return c;
740 }
741
742 float MSG_ReadFloat (sizebuf_t *msg_read)
743 {
744 union
745 {
746 byte b[4];
747 float f;
748 int l;
749 } dat;
750
751 if (msg_read->readcount+4 > msg_read->cursize)
752 dat.f = -1;
753 else
754 {
755 dat.b[0] = msg_read->data[msg_read->readcount];
756 dat.b[1] = msg_read->data[msg_read->readcount+1];
757 dat.b[2] = msg_read->data[msg_read->readcount+2];
758 dat.b[3] = msg_read->data[msg_read->readcount+3];
759 }
760 msg_read->readcount += 4;
761
762 dat.l = LittleLong (dat.l);
763
764 return dat.f;
765 }
766
767 char *MSG_ReadString (sizebuf_t *msg_read)
768 {
769 static char string[2048];
770 int l,c;
771
772 l = 0;
773 do
774 {
775 c = MSG_ReadChar (msg_read);
776 if (c == -1 || c == 0)
777 break;
778 string[l] = c;
779 l++;
780 } while (l < sizeof(string)-1);
781
782 string[l] = 0;
783
784 return string;
785 }
786
787 char *MSG_ReadStringLine (sizebuf_t *msg_read)
788 {
789 static char string[2048];
790 int l,c;
791
792 l = 0;
793 do
794 {
795 c = MSG_ReadChar (msg_read);
796 if (c == -1 || c == 0 || c == '\n')
797 break;
798 string[l] = c;
799 l++;
800 } while (l < sizeof(string)-1);
801
802 string[l] = 0;
803
804 return string;
805 }
806
807 float MSG_ReadCoord (sizebuf_t *msg_read)
808 {
809 return MSG_ReadShort(msg_read) * (1.0/8);
810 }
811
812 void MSG_ReadPos (sizebuf_t *msg_read, vec3_t pos)
813 {
814 pos[0] = MSG_ReadShort(msg_read) * (1.0/8);
815 pos[1] = MSG_ReadShort(msg_read) * (1.0/8);
816 pos[2] = MSG_ReadShort(msg_read) * (1.0/8);
817 }
818
819 float MSG_ReadAngle (sizebuf_t *msg_read)
820 {
821 return MSG_ReadChar(msg_read) * (360.0/256);
822 }
823
824 float MSG_ReadAngle16 (sizebuf_t *msg_read)
825 {
826 return SHORT2ANGLE(MSG_ReadShort(msg_read));
827 }
828
829 void MSG_ReadDeltaUsercmd (sizebuf_t *msg_read, usercmd_t *from, usercmd_t *move)
830 {
831 int bits;
832
833 memcpy (move, from, sizeof(*move));
834
835 bits = MSG_ReadByte (msg_read);
836
837 // read current angles
838 if (bits & CM_ANGLE1)
839 move->angles[0] = MSG_ReadShort (msg_read);
840 if (bits & CM_ANGLE2)
841 move->angles[1] = MSG_ReadShort (msg_read);
842 if (bits & CM_ANGLE3)
843 move->angles[2] = MSG_ReadShort (msg_read);
844
845 // read movement
846 if (bits & CM_FORWARD)
847 move->forwardmove = MSG_ReadShort (msg_read);
848 if (bits & CM_SIDE)
849 move->sidemove = MSG_ReadShort (msg_read);
850 if (bits & CM_UP)
851 move->upmove = MSG_ReadShort (msg_read);
852
853 // read buttons
854 if (bits & CM_BUTTONS)
855 move->buttons = MSG_ReadByte (msg_read);
856
857 if (bits & CM_IMPULSE)
858 move->impulse = MSG_ReadByte (msg_read);
859
860 // read time to run command
861 move->msec = MSG_ReadByte (msg_read);
862
863 // read the light level
864 move->lightlevel = MSG_ReadByte (msg_read);
865 }
866
867
868 void MSG_ReadData (sizebuf_t *msg_read, void *data, int len)
869 {
870 int i;
871
872 for (i=0 ; i<len ; i++)
873 ((byte *)data)[i] = MSG_ReadByte (msg_read);
874 }
875
876
877 //===========================================================================
878
879 void SZ_Init (sizebuf_t *buf, byte *data, int length)
880 {
881 memset (buf, 0, sizeof(*buf));
882 buf->data = data;
883 buf->maxsize = length;
884 }
885
886 void SZ_Clear (sizebuf_t *buf)
887 {
888 buf->cursize = 0;
889 buf->overflowed = false;
890 }
891
892 void *SZ_GetSpace (sizebuf_t *buf, int length)
893 {
894 void *data;
895
896 if (buf->cursize + length > buf->maxsize)
897 {
898 if (!buf->allowoverflow)
899 Com_Error (ERR_FATAL, "SZ_GetSpace: overflow without allowoverflow set");
900
901 if (length > buf->maxsize)
902 Com_Error (ERR_FATAL, "SZ_GetSpace: %i is > full buffer size", length);
903
904 Com_Printf ("SZ_GetSpace: overflow\n");
905 SZ_Clear (buf);
906 buf->overflowed = true;
907 }
908
909 data = buf->data + buf->cursize;
910 buf->cursize += length;
911
912 return data;
913 }
914
915 void SZ_Write (sizebuf_t *buf, void *data, int length)
916 {
917 memcpy (SZ_GetSpace(buf,length),data,length);
918 }
919
920 void SZ_Print (sizebuf_t *buf, char *data)
921 {
922 int len;
923
924 len = strlen(data)+1;
925
926 if (buf->cursize)
927 {
928 if (buf->data[buf->cursize-1])
929 memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
930 else
931 memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
932 }
933 else
934 memcpy ((byte *)SZ_GetSpace(buf, len),data,len);
935 }
936
937
938 //============================================================================
939
940
941 /*
942 ================
943 COM_CheckParm
944
945 Returns the position (1 to argc-1) in the program's argument list
946 where the given parameter apears, or 0 if not present
947 ================
948 */
949 int COM_CheckParm (char *parm)
950 {
951 int i;
952
953 for (i=1 ; i<com_argc ; i++)
954 {
955 if (!strcmp (parm,com_argv[i]))
956 return i;
957 }
958
959 return 0;
960 }
961
962 int COM_Argc (void)
963 {
964 return com_argc;
965 }
966
967 char *COM_Argv (int arg)
968 {
969 if (arg < 0 || arg >= com_argc || !com_argv[arg])
970 return "";
971 return com_argv[arg];
972 }
973
974 void COM_ClearArgv (int arg)
975 {
976 if (arg < 0 || arg >= com_argc || !com_argv[arg])
977 return;
978 com_argv[arg] = "";
979 }
980
981
982 /*
983 ================
984 COM_InitArgv
985 ================
986 */
987 void COM_InitArgv (int argc, char **argv)
988 {
989 int i;
990
991 if (argc > MAX_NUM_ARGVS)
992 Com_Error (ERR_FATAL, "argc > MAX_NUM_ARGVS");
993 com_argc = argc;
994 for (i=0 ; i<argc ; i++)
995 {
996 if (!argv[i] || strlen(argv[i]) >= MAX_TOKEN_CHARS )
997 com_argv[i] = "";
998 else
999 com_argv[i] = argv[i];
1000 }
1001 }
1002
1003 /*
1004 ================
1005 COM_AddParm
1006
1007 Adds the given string at the end of the current argument list
1008 ================
1009 */
1010 void COM_AddParm (char *parm)
1011 {
1012 if (com_argc == MAX_NUM_ARGVS)
1013 Com_Error (ERR_FATAL, "COM_AddParm: MAX_NUM)ARGS");
1014 com_argv[com_argc++] = parm;
1015 }
1016
1017
1018
1019
1020 /// just for debugging
1021 int memsearch (byte *start, int count, int search)
1022 {
1023 int i;
1024
1025 for (i=0 ; i<count ; i++)
1026 if (start[i] == search)
1027 return i;
1028 return -1;
1029 }
1030
1031
1032 char *CopyString (char *in)
1033 {
1034 char *out;
1035
1036 out = Z_Malloc (strlen(in)+1);
1037 strcpy (out, in);
1038 return out;
1039 }
1040
1041
1042
1043 void Info_Print (char *s)
1044 {
1045 char key[512];
1046 char value[512];
1047 char *o;
1048 int l;
1049
1050 if (*s == '\\')
1051 s++;
1052 while (*s)
1053 {
1054 o = key;
1055 while (*s && *s != '\\')
1056 *o++ = *s++;
1057
1058 l = o - key;
1059 if (l < 20)
1060 {
1061 memset (o, ' ', 20-l);
1062 key[20] = 0;
1063 }
1064 else
1065 *o = 0;
1066 Com_Printf ("%s", key);
1067
1068 if (!*s)
1069 {
1070 Com_Printf ("MISSING VALUE\n");
1071 return;
1072 }
1073
1074 o = value;
1075 s++;
1076 while (*s && *s != '\\')
1077 *o++ = *s++;
1078 *o = 0;
1079
1080 if (*s)
1081 s++;
1082 Com_Printf ("%s\n", value);
1083 }
1084 }
1085
1086
1087 /*
1088 ==============================================================================
1089
1090 ZONE MEMORY ALLOCATION
1091
1092 just cleared malloc with counters now...
1093
1094 ==============================================================================
1095 */
1096
1097 #define Z_MAGIC 0x1d1d
1098
1099
1100 typedef struct zhead_s
1101 {
1102 struct zhead_s *prev, *next;
1103 short magic;
1104 short tag; // for group free
1105 int size;
1106 } zhead_t;
1107
1108 zhead_t z_chain;
1109 int z_count, z_bytes;
1110
1111 /*
1112 ========================
1113 Z_Free
1114 ========================
1115 */
1116 void Z_Free (void *ptr)
1117 {
1118 zhead_t *z;
1119
1120 z = ((zhead_t *)ptr) - 1;
1121
1122 if (z->magic != Z_MAGIC)
1123 Com_Error (ERR_FATAL, "Z_Free: bad magic");
1124
1125 z->prev->next = z->next;
1126 z->next->prev = z->prev;
1127
1128 z_count--;
1129 z_bytes -= z->size;
1130 free (z);
1131 }
1132
1133
1134 /*
1135 ========================
1136 Z_Stats_f
1137 ========================
1138 */
1139 void Z_Stats_f (void)
1140 {
1141 Com_Printf ("%i bytes in %i blocks\n", z_bytes, z_count);
1142 }
1143
1144 /*
1145 ========================
1146 Z_FreeTags
1147 ========================
1148 */
1149 void Z_FreeTags (int tag)
1150 {
1151 zhead_t *z, *next;
1152
1153 for (z=z_chain.next ; z != &z_chain ; z=next)
1154 {
1155 next = z->next;
1156 if (z->tag == tag)
1157 Z_Free ((void *)(z+1));
1158 }
1159 }
1160
1161 /*
1162 ========================
1163 Z_TagMalloc
1164 ========================
1165 */
1166 void *Z_TagMalloc (int size, int tag)
1167 {
1168 zhead_t *z;
1169
1170 size = size + sizeof(zhead_t);
1171 z = malloc(size);
1172 if (!z)
1173 Com_Error (ERR_FATAL, "Z_Malloc: failed on allocation of %i bytes",size);
1174 memset (z, 0, size);
1175 z_count++;
1176 z_bytes += size;
1177 z->magic = Z_MAGIC;
1178 z->tag = tag;
1179 z->size = size;
1180
1181 z->next = z_chain.next;
1182 z->prev = &z_chain;
1183 z_chain.next->prev = z;
1184 z_chain.next = z;
1185
1186 return (void *)(z+1);
1187 }
1188
1189 /*
1190 ========================
1191 Z_Malloc
1192 ========================
1193 */
1194 void *Z_Malloc (int size)
1195 {
1196 return Z_TagMalloc (size, 0);
1197 }
1198
1199
1200 //============================================================================
1201
1202
1203 /*
1204 ====================
1205 COM_BlockSequenceCheckByte
1206
1207 For proxy protecting
1208
1209 // THIS IS MASSIVELY BROKEN! CHALLENGE MAY BE NEGATIVE
1210 // DON'T USE THIS FUNCTION!!!!!
1211
1212 ====================
1213 */
1214 byte COM_BlockSequenceCheckByte (byte *base, int length, int sequence, int challenge)
1215 {
1216 Sys_Error("COM_BlockSequenceCheckByte called\n");
1217
1218 #if 0
1254 #endif
1255 return 0;
1256 }
1257
1258 static byte chktbl[1024] = {
1259 0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda,
1260 0x88, 0x54, 0x15, 0x2b, 0xc6, 0x6c, 0x89, 0xc5, 0x9d, 0x48, 0xee, 0xe6, 0x8a, 0xb5, 0xf4,
1261 0xcb, 0xfb, 0xf1, 0x0c, 0x2e, 0xa0, 0xd7, 0xc9, 0x1f, 0xd6, 0x06, 0x9a, 0x09, 0x41, 0x54,
1262 0x67, 0x46, 0xc7, 0x74, 0xe3, 0xc8, 0xb6, 0x5d, 0xa6, 0x36, 0xc4, 0xab, 0x2c, 0x7e, 0x85,
1263 0xa8, 0xa4, 0xa6, 0x4d, 0x96, 0x19, 0x19, 0x9a, 0xcc, 0xd8, 0xac, 0x39, 0x5e, 0x3c, 0xf2,
1264 0xf5, 0x5a, 0x72, 0xe5, 0xa9, 0xd1, 0xb3, 0x23, 0x82, 0x6f, 0x29, 0xcb, 0xd1, 0xcc, 0x71,
1265 0xfb, 0xea, 0x92, 0xeb, 0x1c, 0xca, 0x4c, 0x70, 0xfe, 0x4d, 0xc9, 0x67, 0x43, 0x47, 0x94,
1266 0xb9, 0x47, 0xbc, 0x3f, 0x01, 0xab, 0x7b, 0xa6, 0xe2, 0x76, 0xef, 0x5a, 0x7a, 0x29, 0x0b,
1267 0x51, 0x54, 0x67, 0xd8, 0x1c, 0x14, 0x3e, 0x29, 0xec, 0xe9, 0x2d, 0x48, 0x67, 0xff, 0xed,
1268 0x54, 0x4f, 0x48, 0xc0, 0xaa, 0x61, 0xf7, 0x78, 0x12, 0x03, 0x7a, 0x9e, 0x8b, 0xcf, 0x83,
1269 0x7b, 0xae, 0xca, 0x7b, 0xd9, 0xe9, 0x53, 0x2a, 0xeb, 0xd2, 0xd8, 0xcd, 0xa3, 0x10, 0x25,
1270 0x78, 0x5a, 0xb5, 0x23, 0x06, 0x93, 0xb7, 0x84, 0xd2, 0xbd, 0x96, 0x75, 0xa5, 0x5e, 0xcf,
1271 0x4e, 0xe9, 0x50, 0xa1, 0xe6, 0x9d, 0xb1, 0xe3, 0x85, 0x66, 0x28, 0x4e, 0x43, 0xdc, 0x6e,
1272 0xbb, 0x33, 0x9e, 0xf3, 0x0d, 0x00, 0xc1, 0xcf, 0x67, 0x34, 0x06, 0x7c, 0x71, 0xe3, 0x63,
1273 0xb7, 0xb7, 0xdf, 0x92, 0xc4, 0xc2, 0x25, 0x5c, 0xff, 0xc3, 0x6e, 0xfc, 0xaa, 0x1e, 0x2a,
1274 0x48, 0x11, 0x1c, 0x36, 0x68, 0x78, 0x86, 0x79, 0x30, 0xc3, 0xd6, 0xde, 0xbc, 0x3a, 0x2a,
1275 0x6d, 0x1e, 0x46, 0xdd, 0xe0, 0x80, 0x1e, 0x44, 0x3b, 0x6f, 0xaf, 0x31, 0xda, 0xa2, 0xbd,
1276 0x77, 0x06, 0x56, 0xc0, 0xb7, 0x92, 0x4b, 0x37, 0xc0, 0xfc, 0xc2, 0xd5, 0xfb, 0xa8, 0xda,
1277 0xf5, 0x57, 0xa8, 0x18, 0xc0, 0xdf, 0xe7, 0xaa, 0x2a, 0xe0, 0x7c, 0x6f, 0x77, 0xb1, 0x26,
1278 0xba, 0xf9, 0x2e, 0x1d, 0x16, 0xcb, 0xb8, 0xa2, 0x44, 0xd5, 0x2f, 0x1a, 0x79, 0x74, 0x87,
1279 0x4b, 0x00, 0xc9, 0x4a, 0x3a, 0x65, 0x8f, 0xe6, 0x5d, 0xe5, 0x0a, 0x77, 0xd8, 0x1a, 0x14,
1280 0x41, 0x75, 0xb1, 0xe2, 0x50, 0x2c, 0x93, 0x38, 0x2b, 0x6d, 0xf3, 0xf6, 0xdb, 0x1f, 0xcd,
1281 0xff, 0x14, 0x70, 0xe7, 0x16, 0xe8, 0x3d, 0xf0, 0xe3, 0xbc, 0x5e, 0xb6, 0x3f, 0xcc, 0x81,
1282 0x24, 0x67, 0xf3, 0x97, 0x3b, 0xfe, 0x3a, 0x96, 0x85, 0xdf, 0xe4, 0x6e, 0x3c, 0x85, 0x05,
1283 0x0e, 0xa3, 0x2b, 0x07, 0xc8, 0xbf, 0xe5, 0x13, 0x82, 0x62, 0x08, 0x61, 0x69, 0x4b, 0x47,
1284 0x62, 0x73, 0x44, 0x64, 0x8e, 0xe2, 0x91, 0xa6, 0x9a, 0xb7, 0xe9, 0x04, 0xb6, 0x54, 0x0c,
1285 0xc5, 0xa9, 0x47, 0xa6, 0xc9, 0x08, 0xfe, 0x4e, 0xa6, 0xcc, 0x8a, 0x5b, 0x90, 0x6f, 0x2b,
1286 0x3f, 0xb6, 0x0a, 0x96, 0xc0, 0x78, 0x58, 0x3c, 0x76, 0x6d, 0x94, 0x1a, 0xe4, 0x4e, 0xb8,
1287 0x38, 0xbb, 0xf5, 0xeb, 0x29, 0xd8, 0xb0, 0xf3, 0x15, 0x1e, 0x99, 0x96, 0x3c, 0x5d, 0x63,
1288 0xd5, 0xb1, 0xad, 0x52, 0xb8, 0x55, 0x70, 0x75, 0x3e, 0x1a, 0xd5, 0xda, 0xf6, 0x7a, 0x48,
1289 0x7d, 0x44, 0x41, 0xf9, 0x11, 0xce, 0xd7, 0xca, 0xa5, 0x3d, 0x7a, 0x79, 0x7e, 0x7d, 0x25,
1290 0x1b, 0x77, 0xbc, 0xf7, 0xc7, 0x0f, 0x84, 0x95, 0x10, 0x92, 0x67, 0x15, 0x11, 0x5a, 0x5e,
1291 0x41, 0x66, 0x0f, 0x38, 0x03, 0xb2, 0xf1, 0x5d, 0xf8, 0xab, 0xc0, 0x02, 0x76, 0x84, 0x28,
1292 0xf4, 0x9d, 0x56, 0x46, 0x60, 0x20, 0xdb, 0x68, 0xa7, 0xbb, 0xee, 0xac, 0x15, 0x01, 0x2f,
1293 0x20, 0x09, 0xdb, 0xc0, 0x16, 0xa1, 0x89, 0xf9, 0x94, 0x59, 0x00, 0xc1, 0x76, 0xbf, 0xc1,
1294 0x4d, 0x5d, 0x2d, 0xa9, 0x85, 0x2c, 0xd6, 0xd3, 0x14, 0xcc, 0x02, 0xc3, 0xc2, 0xfa, 0x6b,
1295 0xb7, 0xa6, 0xef, 0xdd, 0x12, 0x26, 0xa4, 0x63, 0xe3, 0x62, 0xbd, 0x56, 0x8a, 0x52, 0x2b,
1296 0xb9, 0xdf, 0x09, 0xbc, 0x0e, 0x97, 0xa9, 0xb0, 0x82, 0x46, 0x08, 0xd5, 0x1a, 0x8e, 0x1b,
1297 0xa7, 0x90, 0x98, 0xb9, 0xbb, 0x3c, 0x17, 0x9a, 0xf2, 0x82, 0xba, 0x64, 0x0a, 0x7f, 0xca,
1298 0x5a, 0x8c, 0x7c, 0xd3, 0x79, 0x09, 0x5b, 0x26, 0xbb, 0xbd, 0x25, 0xdf, 0x3d, 0x6f, 0x9a,
1299 0x8f, 0xee, 0x21, 0x66, 0xb0, 0x8d, 0x84, 0x4c, 0x91, 0x45, 0xd4, 0x77, 0x4f, 0xb3, 0x8c,
1300 0xbc, 0xa8, 0x99, 0xaa, 0x19, 0x53, 0x7c, 0x02, 0x87, 0xbb, 0x0b, 0x7c, 0x1a, 0x2d, 0xdf,
1301 0x48, 0x44, 0x06, 0xd6, 0x7d, 0x0c, 0x2d, 0x35, 0x76, 0xae, 0xc4, 0x5f, 0x71, 0x85, 0x97,
1302 0xc4, 0x3d, 0xef, 0x52, 0xbe, 0x00, 0xe4, 0xcd, 0x49, 0xd1, 0xd1, 0x1c, 0x3c, 0xd0, 0x1c,
1303 0x42, 0xaf, 0xd4, 0xbd, 0x58, 0x34, 0x07, 0x32, 0xee, 0xb9, 0xb5, 0xea, 0xff, 0xd7, 0x8c,
1304 0x0d, 0x2e, 0x2f, 0xaf, 0x87, 0xbb, 0xe6, 0x52, 0x71, 0x22, 0xf5, 0x25, 0x17, 0xa1, 0x82,
1305 0x04, 0xc2, 0x4a, 0xbd, 0x57, 0xc6, 0xab, 0xc8, 0x35, 0x0c, 0x3c, 0xd9, 0xc2, 0x43, 0xdb,
1306 0x27, 0x92, 0xcf, 0xb8, 0x25, 0x60, 0xfa, 0x21, 0x3b, 0x04, 0x52, 0xc8, 0x96, 0xba, 0x74,
1307 0xe3, 0x67, 0x3e, 0x8e, 0x8d, 0x61, 0x90, 0x92, 0x59, 0xb6, 0x1a, 0x1c, 0x5e, 0x21, 0xc1,
1308 0x65, 0xe5, 0xa6, 0x34, 0x05, 0x6f, 0xc5, 0x60, 0xb1, 0x83, 0xc1, 0xd5, 0xd5, 0xed, 0xd9,
1309 0xc7, 0x11, 0x7b, 0x49, 0x7a, 0xf9, 0xf9, 0x84, 0x47, 0x9b, 0xe2, 0xa5, 0x82, 0xe0, 0xc2,
1310 0x88, 0xd0, 0xb2, 0x58, 0x88, 0x7f, 0x45, 0x09, 0x67, 0x74, 0x61, 0xbf, 0xe6, 0x40, 0xe2,
1311 0x9d, 0xc2, 0x47, 0x05, 0x89, 0xed, 0xcb, 0xbb, 0xb7, 0x27, 0xe7, 0xdc, 0x7a, 0xfd, 0xbf,
1312 0xa8, 0xd0, 0xaa, 0x10, 0x39, 0x3c, 0x20, 0xf0, 0xd3, 0x6e, 0xb1, 0x72, 0xf8, 0xe6, 0x0f,
1313 0xef, 0x37, 0xe5, 0x09, 0x33, 0x5a, 0x83, 0x43, 0x80, 0x4f, 0x65, 0x2f, 0x7c, 0x8c, 0x6a,
1314 0xa0, 0x82, 0x0c, 0xd4, 0xd4, 0xfa, 0x81, 0x60, 0x3d, 0xdf, 0x06, 0xf1, 0x5f, 0x08, 0x0d,
1315 0x6d, 0x43, 0xf2, 0xe3, 0x11, 0x7d, 0x80, 0x32, 0xc5, 0xfb, 0xc5, 0xd9, 0x27, 0xec, 0xc6,
1316 0x4e, 0x65, 0x27, 0x76, 0x87, 0xa6, 0xee, 0xee, 0xd7, 0x8b, 0xd1, 0xa0, 0x5c, 0xb0, 0x42,
1317 0x13, 0x0e, 0x95, 0x4a, 0xf2, 0x06, 0xc6, 0x43, 0x33, 0xf4, 0xc7, 0xf8, 0xe7, 0x1f, 0xdd,
1318 0xe4, 0x46, 0x4a, 0x70, 0x39, 0x6c, 0xd0, 0xed, 0xca, 0xbe, 0x60, 0x3b, 0xd1, 0x7b, 0x57,
1319 0x48, 0xe5, 0x3a, 0x79, 0xc1, 0x69, 0x33, 0x53, 0x1b, 0x80, 0xb8, 0x91, 0x7d, 0xb4, 0xf6,
1320 0x17, 0x1a, 0x1d, 0x5a, 0x32, 0xd6, 0xcc, 0x71, 0x29, 0x3f, 0x28, 0xbb, 0xf3, 0x5e, 0x71,
1321 0xb8, 0x43, 0xaf, 0xf8, 0xb9, 0x64, 0xef, 0xc4, 0xa5, 0x6c, 0x08, 0x53, 0xc7, 0x00, 0x10,
1322 0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32
1323 };
1324
1325 /*
1326 ====================
1327 COM_BlockSequenceCRCByte
1328
1329 For proxy protecting
1330 ====================
1331 */
1332 byte COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
1333 {
1334 int n;
1335 byte *p;
1336 int x;
1337 byte chkb[60 + 4];
1338 unsigned short crc;
1339
1340
1341 if (sequence < 0)
1342 Sys_Error("sequence < 0, this shouldn't happen\n");
1343
1344 p = chktbl + (sequence % (sizeof(chktbl) - 4));
1345
1346 if (length > 60)
1347 length = 60;
1348 memcpy (chkb, base, length);
1349
1350 chkb[length] = p[0];
1351 chkb[length+1] = p[1];
1352 chkb[length+2] = p[2];
1353 chkb[length+3] = p[3];
1354
1355 length += 4;
1356
1357 crc = CRC_Block(chkb, length);
1358
1359 for (x=0, n=0; n<length; n++)
1360 x += chkb[n];
1361
1362 crc = (crc ^ x) & 0xff;
1363
1364 return crc;
1365 }
1366
1367 //========================================================
1368
1369 float frand(void)
1370 {
1371 return (rand()&32767)* (1.0/32767);
1372 }
1373
1374 float crand(void)
1375 {
1376 return (rand()&32767)* (2.0/32767) - 1;
1377 }
1378
1379 void Key_Init (void);
1380 void SCR_EndLoadingPlaque (void);
1381
1382 /*
1383 =============
1384 Com_Error_f
1385
1386 Just throw a fatal error to
1387 test error shutdown procedures
1388 =============
1389 */
1390 void Com_Error_f (void)
1391 {
1392 Com_Error (ERR_FATAL, "%s", Cmd_Argv(1));
1393 }
1394
1395
1396 /*
1397 =================
1398 Qcommon_Init
1399 =================
1400 */
1401 void Qcommon_Init (int argc, char **argv)
1402 {
1403 char *s;
1404
1405 if (setjmp (abortframe) )
1406 Sys_Error ("Error during initialization");
1407
1408 z_chain.next = z_chain.prev = &z_chain;
1409
1410 // prepare enough of the subsystems to handle
1411 // cvar and command buffer management
1412 COM_InitArgv (argc, argv);
1413
1414 Swap_Init ();
1415 Cbuf_Init ();
1416
1417 Cmd_Init ();
1418 Cvar_Init ();
1419
1420 Key_Init ();
1421
1422 // we need to add the early commands twice, because
1423 // a basedir or cddir needs to be set before execing
1424 // config files, but we want other parms to override
1425 // the settings of the config files
1426 Cbuf_AddEarlyCommands (false);
1427 Cbuf_Execute ();
1428
1429 FS_InitFilesystem ();
1430
1431 Cbuf_AddText ("exec default.cfg\n");
1432 Cbuf_AddText ("exec config.cfg\n");
1433
1434 Cbuf_AddEarlyCommands (true);
1435 Cbuf_Execute ();
1436
1437 //
1438 // init commands and vars
1439 //
1440 Cmd_AddCommand ("z_stats", Z_Stats_f);
1441 Cmd_AddCommand ("error", Com_Error_f);
1442
1443 host_speeds = Cvar_Get ("host_speeds", "0", 0);
1444 log_stats = Cvar_Get ("log_stats", "0", 0);
1445 developer = Cvar_Get ("developer", "0", 0);
1446 timescale = Cvar_Get ("timescale", "1", 0);
1447 fixedtime = Cvar_Get ("fixedtime", "0", 0);
1448 logfile_active = Cvar_Get ("logfile", "0", 0);
1449 showtrace = Cvar_Get ("showtrace", "0", 0);
1450 #ifdef DEDICATED_ONLY
1452 #else
1453 dedicated = Cvar_Get ("dedicated", "0", CVAR_NOSET);
1454 #endif
1455
1456 s = va("%4.2f %s %s %s", VERSION, CPUSTRING, __DATE__, BUILDSTRING);
1457 Cvar_Get ("version", s, CVAR_SERVERINFO|CVAR_NOSET);
1458
1459
1460 if (dedicated->value)
1461 Cmd_AddCommand ("quit", Com_Quit);
1462
1463 Sys_Init ();
1464
1465 NET_Init ();
1466 Netchan_Init ();
1467
1468 SV_Init ();
1469 CL_Init ();
1470
1471 // add + commands from command line
1472 if (!Cbuf_AddLateCommands ())
1473 { // if the user didn't give any commands, run default action
1474 if (!dedicated->value)
1475 Cbuf_AddText ("d1\n");
1476 else
1477 Cbuf_AddText ("dedicated_start\n");
1478 Cbuf_Execute ();
1479 }
1480 else
1481 { // the user asked for something explicit
1482 // so drop the loading plaque
1483 SCR_EndLoadingPlaque ();
1484 }
1485
1486 Com_Printf ("====== Quake2 Initialized ======\n\n");
1487 }
1488
1489 /*
1490 =================
1491 Qcommon_Frame
1492 =================
1493 */
1494 void Qcommon_Frame (int msec)
1495 {
1496 char *s;
1497 int time_before, time_between, time_after;
1498
1499 if (setjmp (abortframe) )
1500 return; // an ERR_DROP was thrown
1501
1502 if ( log_stats->modified )
1503 {
1504 log_stats->modified = false;
1505 if ( log_stats->value )
1506 {
1507 if ( log_stats_file )
1508 {
1509 fclose( log_stats_file );
1510 log_stats_file = 0;
1511 }
1512 log_stats_file = fopen( "stats.log", "w" );
1513 if ( log_stats_file )
1514 fprintf( log_stats_file, "entities,dlights,parts,frame time\n" );
1515 }
1516 else
1517 {
1518 if ( log_stats_file )
1519 {
1520 fclose( log_stats_file );
1521 log_stats_file = 0;
1522 }
1523 }
1524 }
1525
1526 if (fixedtime->value)
1527 msec = fixedtime->value;
1528 else if (timescale->value)
1529 {
1530 msec *= timescale->value;
1531 if (msec < 1)
1532 msec = 1;
1533 }
1534
1535 if (showtrace->value)
1536 {
1537 extern int c_traces, c_brush_traces;
1538 extern int c_pointcontents;
1539
1540 Com_Printf ("%4i traces %4i points\n", c_traces, c_pointcontents);
1541 c_traces = 0;
1542 c_brush_traces = 0;
1543 c_pointcontents = 0;
1544 }
1545
1546 do
1547 {
1548 s = Sys_ConsoleInput ();
1549 if (s)
1550 Cbuf_AddText (va("%s\n",s));
1551 } while (s);
1552 Cbuf_Execute ();
1553
1554 if (host_speeds->value)
1555 time_before = Sys_Milliseconds ();
1556
1557 SV_Frame (msec);
1558
1559 if (host_speeds->value)
1560 time_between = Sys_Milliseconds ();
1561
1562 CL_Frame (msec);
1563
1564 if (host_speeds->value)
1565 time_after = Sys_Milliseconds ();
1566
1567
1568 if (host_speeds->value)
1569 {
1570 int all, sv, gm, cl, rf;
1571
1572 all = time_after - time_before;
1573 sv = time_between - time_before;
1574 cl = time_after - time_between;
1575 gm = time_after_game - time_before_game;
1576 rf = time_after_ref - time_before_ref;
1577 sv -= gm;
1578 cl -= rf;
1579 Com_Printf ("all:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n",
1580 all, sv, gm, cl, rf);
1581 }
1582 }
1583
1584 /*
1585 =================
1586 Qcommon_Shutdown
1587 =================
1588 */
1589 void Qcommon_Shutdown (void)
1590 {
1591 }
1592