|
|
1.1 root 1: // common.c -- misc functions used in client and server
2: #include "qcommon.h"
3: #include <setjmp.h>
4: #define MAXPRINTMSG 4096
5: #define MAX_NUM_ARGVS 50
6: int com_argc;
7: char *com_argv[MAX_NUM_ARGVS+1];
8: int realtime;
9: jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame
10:
11: FILE *log_stats_file;
12: cvar_t *host_speeds;
13: cvar_t *log_stats;
14: cvar_t *developer;
15: cvar_t *timescale;
16: cvar_t *fixedtime;
17: cvar_t *logfile_active; // 1 = buffer log, 2 = flush after each print
18: cvar_t *showtrace;
19: cvar_t *dedicated;
20: FILE *logfile;
21: int server_state;
22: // host_speeds times
23: int time_before_game;
24: int time_after_game;
25: int time_before_ref;
26: int time_after_ref;
27: /*
28: ============================================================================
29: CLIENT / SERVER interactions
30: ============================================================================
31: */
32: static int rd_target;
33: static char *rd_buffer;
34: static int rd_buffersize;
35: static void (*rd_flush)(int target, char *buffer);
36: void Com_BeginRedirect (int target, char *buffer, int buffersize, void (*flush))
37: {
38: if (!target || !buffer || !buffersize || !flush)
39: return;
40: rd_target = target;
41: rd_buffer = buffer;
42: rd_buffersize = buffersize;
43: rd_flush = flush;
44:
45: *rd_buffer = 0;
46: }
47:
48: void Com_EndRedirect (void)
49: {
50: rd_flush(rd_target, rd_buffer);
51:
52: rd_target = 0;
53: rd_buffer = NULL;
54: rd_buffersize = 0;
55: rd_flush = NULL;
56: }
57:
58: /*
59: =============
60: Com_Printf
61: Both client and server can use this, and it will output
62: to the apropriate place.
63: =============
64: */
65: void Com_Printf (char *fmt, ...)
66: {
67: va_list argptr;
68: char msg[MAXPRINTMSG];
69: va_start (argptr,fmt);
70: vsprintf (msg,fmt,argptr);
71: va_end (argptr);
72: if (rd_target)
73: {
74: if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1))
75: {
76: rd_flush(rd_target, rd_buffer);
77: *rd_buffer = 0;
78: }
79: strcat (rd_buffer, msg);
80: return;
81: }
82:
83: Con_Print (msg);
84:
85: // also echo to debugging console
86: Sys_ConsoleOutput (msg);
87: // logfile
88: if (logfile_active && logfile_active->value)
89: {
90: char name[MAX_QPATH];
91:
92: if (!logfile)
93: {
94: Com_sprintf (name, sizeof(name), "%s/qconsole.log", FS_Gamedir ());
95: logfile = fopen (name, "w");
96: }
97: if (logfile)
98: fprintf (logfile, "%s", msg);
99: if (logfile_active->value > 1)
100: fflush (logfile); // force it to save every time
101: }
102: }
103: /*
104: ================
105: Com_DPrintf
106: A Com_Printf that only shows up if the "developer" cvar is set
107: ================
108: */
109: void Com_DPrintf (char *fmt, ...)
110: {
111: va_list argptr;
112: char msg[MAXPRINTMSG];
113:
114: if (!developer || !developer->value)
115: return; // don't confuse non-developers with techie stuff...
116: va_start (argptr,fmt);
117: vsprintf (msg,fmt,argptr);
118: va_end (argptr);
119:
120: Com_Printf ("%s", msg);
121: }
122: /*
123: =============
124: Com_Error
125: Both client and server can use this, and it will
126: do the apropriate things.
127: =============
128: */
129: void Com_Error (int code, char *fmt, ...)
130: {
131: va_list argptr;
132: static char msg[MAXPRINTMSG];
133: static qboolean recursive;
134: if (recursive)
135: Sys_Error ("recursive error after: %s", msg);
136: recursive = true;
137: va_start (argptr,fmt);
138: vsprintf (msg,fmt,argptr);
139: va_end (argptr);
140:
141: if (code == ERR_DISCONNECT)
142: {
143: CL_Drop ();
144: recursive = false;
145: longjmp (abortframe, -1);
146: }
147: else if (code == ERR_DROP)
148: {
149: Com_Printf ("********************\nERROR: %s\n********************\n", msg);
150: SV_Shutdown (va("Server crashed: %s\n", msg), false);
151: CL_Drop ();
152: recursive = false;
153: longjmp (abortframe, -1);
154: }
155: else
156: {
157: SV_Shutdown (va("Server fatal crashed: %s\n", msg), false);
158: CL_Shutdown ();
159: }
160: if (logfile)
161: {
162: fclose (logfile);
163: logfile = NULL;
164: }
165: Sys_Error ("%s", msg);
166: }
167: /*
168: =============
169: Com_Quit
170: Both client and server can use this, and it will
171: do the apropriate things.
172: =============
173: */
174: void Com_Quit (void)
175: {
176: SV_Shutdown ("Server quit\n", false);
177: CL_Shutdown ();
178: if (logfile)
179: {
180: fclose (logfile);
181: logfile = NULL;
182: }
183: Sys_Quit ();
184: }
185: /*
186: ==================
187: Com_ServerState
188: ==================
189: */
190: int Com_ServerState (void)
191: {
192: return server_state;
193: }
194: /*
195: ==================
196: Com_SetServerState
197: ==================
198: */
199: void Com_SetServerState (int state)
200: {
201: server_state = state;
202: }
203: /*
204: ==============================================================================
205: MESSAGE IO FUNCTIONS
206: Handles byte ordering and avoids alignment errors
207: ==============================================================================
208: */
209: vec3_t bytedirs[NUMVERTEXNORMALS] =
210: {
211: #include "../client/anorms.h"
212: };
213: //
214: // writing functions
215: //
216: void MSG_WriteChar (sizebuf_t *sb, int c)
217: {
218: byte *buf;
219:
220: #ifdef PARANOID
221: if (c < -128 || c > 127)
222: Com_Error (ERR_FATAL, "MSG_WriteChar: range error");
223: #endif
224: buf = SZ_GetSpace (sb, 1);
225: buf[0] = c;
226: }
227: void MSG_WriteByte (sizebuf_t *sb, int c)
228: {
229: byte *buf;
230:
231: #ifdef PARANOID
232: if (c < 0 || c > 255)
233: Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
234: #endif
235: buf = SZ_GetSpace (sb, 1);
236: buf[0] = c;
237: }
238: void MSG_WriteShort (sizebuf_t *sb, int c)
239: {
240: byte *buf;
241:
242: #ifdef PARANOID
243: if (c < ((short)0x8000) || c > (short)0x7fff)
244: Com_Error (ERR_FATAL, "MSG_WriteShort: range error");
245: #endif
246: buf = SZ_GetSpace (sb, 2);
247: buf[0] = c&0xff;
248: buf[1] = c>>8;
249: }
250: void MSG_WriteLong (sizebuf_t *sb, int c)
251: {
252: byte *buf;
253:
254: buf = SZ_GetSpace (sb, 4);
255: buf[0] = c&0xff;
256: buf[1] = (c>>8)&0xff;
257: buf[2] = (c>>16)&0xff;
258: buf[3] = c>>24;
259: }
260: void MSG_WriteFloat (sizebuf_t *sb, float f)
261: {
262: union
263: {
264: float f;
265: int l;
266: } dat;
267:
268:
269: dat.f = f;
270: dat.l = LittleLong (dat.l);
271:
272: SZ_Write (sb, &dat.l, 4);
273: }
274: void MSG_WriteString (sizebuf_t *sb, char *s)
275: {
276: if (!s)
277: SZ_Write (sb, "", 1);
278: else
279: SZ_Write (sb, s, strlen(s)+1);
280: }
281: void MSG_WriteCoord (sizebuf_t *sb, float f)
282: {
283: MSG_WriteShort (sb, (int)(f*8));
284: }
285: void MSG_WritePos (sizebuf_t *sb, vec3_t pos)
286: {
287: MSG_WriteShort (sb, (int)(pos[0]*8));
288: MSG_WriteShort (sb, (int)(pos[1]*8));
289: MSG_WriteShort (sb, (int)(pos[2]*8));
290: }
291: void MSG_WriteAngle (sizebuf_t *sb, float f)
292: {
293: MSG_WriteByte (sb, (int)(f*256/360) & 255);
294: }
295: void MSG_WriteAngle16 (sizebuf_t *sb, float f)
296: {
297: MSG_WriteShort (sb, ANGLE2SHORT(f));
298: }
299:
300: void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
301: {
302: int bits;
303: //
304: // send the movement message
305: //
306: bits = 0;
307: if (cmd->angles[0] != from->angles[0])
308: bits |= CM_ANGLE1;
309: if (cmd->angles[1] != from->angles[1])
310: bits |= CM_ANGLE2;
311: if (cmd->angles[2] != from->angles[2])
312: bits |= CM_ANGLE3;
313: if (cmd->forwardmove != from->forwardmove)
314: bits |= CM_FORWARD;
315: if (cmd->sidemove != from->sidemove)
316: bits |= CM_SIDE;
317: if (cmd->upmove != from->upmove)
318: bits |= CM_UP;
319: if (cmd->buttons != from->buttons)
320: bits |= CM_BUTTONS;
321: if (cmd->impulse != from->impulse)
322: bits |= CM_IMPULSE;
323: MSG_WriteByte (buf, bits);
324: if (bits & CM_ANGLE1)
325: MSG_WriteShort (buf, cmd->angles[0]);
326: if (bits & CM_ANGLE2)
327: MSG_WriteShort (buf, cmd->angles[1]);
328: if (bits & CM_ANGLE3)
329: MSG_WriteShort (buf, cmd->angles[2]);
330:
331: if (bits & CM_FORWARD)
332: MSG_WriteShort (buf, cmd->forwardmove);
333: if (bits & CM_SIDE)
334: MSG_WriteShort (buf, cmd->sidemove);
335: if (bits & CM_UP)
336: MSG_WriteShort (buf, cmd->upmove);
337: if (bits & CM_BUTTONS)
338: MSG_WriteByte (buf, cmd->buttons);
339: if (bits & CM_IMPULSE)
340: MSG_WriteByte (buf, cmd->impulse);
341: MSG_WriteByte (buf, cmd->msec);
342: MSG_WriteByte (buf, cmd->lightlevel);
343: }
344: void MSG_WriteDir (sizebuf_t *sb, vec3_t dir)
345: {
346: int i, best;
347: float d, bestd;
348:
349: if (!dir)
350: {
351: MSG_WriteByte (sb, 0);
352: return;
353: }
354: bestd = 0;
355: best = 0;
356: for (i=0 ; i<NUMVERTEXNORMALS ; i++)
357: {
358: d = DotProduct (dir, bytedirs[i]);
359: if (d > bestd)
360: {
361: bestd = d;
362: best = i;
363: }
364: }
365: MSG_WriteByte (sb, best);
366: }
367: void MSG_ReadDir (sizebuf_t *sb, vec3_t dir)
368: {
369: int b;
370: b = MSG_ReadByte (sb);
371: if (b >= NUMVERTEXNORMALS)
372: Com_Error (ERR_DROP, "MSF_ReadDir: out of range");
373: VectorCopy (bytedirs[b], dir);
374: }
375: /*
376: ==================
377: MSG_WriteDeltaEntity
378: Writes part of a packetentities message.
379: Can delta from either a baseline or a previous packet_entity
380: ==================
381: */
382: void MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force)
383: {
384: int bits;
385:
386: if (!to->number)
387: Com_Error (ERR_FATAL, "Unset entity number");
388: if (to->number >= MAX_EDICTS)
389: Com_Error (ERR_FATAL, "Entity number >= MAX_EDICTS");
390: // send an update
391: bits = 0;
392:
393: if (to->number >= 256)
394: bits |= U_NUMBER16; // number8 is implicit otherwise
395:
396: if (to->origin[0] != from->origin[0])
397: bits |= U_ORIGIN1;
398: if (to->origin[1] != from->origin[1])
399: bits |= U_ORIGIN2;
400: if (to->origin[2] != from->origin[2])
401: bits |= U_ORIGIN3;
402: if ( to->angles[0] != from->angles[0] )
403: bits |= U_ANGLE1;
404: if ( to->angles[1] != from->angles[1] )
405: bits |= U_ANGLE2;
406: if ( to->angles[2] != from->angles[2] )
407: bits |= U_ANGLE3;
408:
409: if ( to->skinnum != from->skinnum )
410: {
411: if ((unsigned)to->skinnum < 256)
412: bits |= U_SKIN8;
413: else if ((unsigned)to->skinnum < 0x10000)
414: bits |= U_SKIN16;
415: else
416: bits |= (U_SKIN8|U_SKIN16);
417: }
418:
419: if ( to->frame != from->frame )
420: {
421: if (to->frame < 256)
422: bits |= U_FRAME8;
423: else
424: bits |= U_FRAME16;
425: }
426: if ( to->effects != from->effects )
427: {
428: if (to->effects < 256)
429: bits |= U_EFFECTS8;
430: else if (to->effects < 0x8000)
431: bits |= U_EFFECTS16;
432: else
433: bits |= U_EFFECTS8|U_EFFECTS16;
434: }
435:
436: if ( to->renderfx != from->renderfx )
437: {
438: if (to->renderfx < 256)
439: bits |= U_RENDERFX8;
440: else if (to->renderfx < 0x8000)
441: bits |= U_RENDERFX16;
442: else
443: bits |= U_RENDERFX8|U_RENDERFX16;
444: }
445:
446: if ( to->solid != from->solid )
447: bits |= U_SOLID;
448:
449: // event is not delta compressed, just 0 compressed
450: if ( to->event )
451: bits |= U_EVENT;
452:
453: if ( to->modelindex != from->modelindex )
454: bits |= U_MODEL;
455: if ( to->modelindex2 != from->modelindex2 )
456: bits |= U_MODEL2;
457: if ( to->modelindex3 != from->modelindex3 )
458: bits |= U_MODEL3;
459: if ( to->modelindex4 != from->modelindex4 )
460: bits |= U_MODEL4;
461: if ( to->sound != from->sound )
462: bits |= U_SOUND;
463:
464: if (to->old_origin[0] != from->old_origin[0]
465: || to->old_origin[1] != from->old_origin[1]
466: || to->old_origin[2] != from->old_origin[2] )
467: bits |= U_OLDORIGIN; // FIXME: only when newly seen!!!
468: //
469: // write the message
470: //
471: if (!bits && !force)
472: return; // nothing to send!
473: //----------
474:
475: if (bits & 0xff000000)
476: bits |= U_MOREBITS3 | U_MOREBITS2 | U_MOREBITS1;
477: else if (bits & 0x00ff0000)
478: bits |= U_MOREBITS2 | U_MOREBITS1;
479: else if (bits & 0x0000ff00)
480: bits |= U_MOREBITS1;
481: MSG_WriteByte (msg, bits&255 );
482: if (bits & 0xff000000)
483: {
484: MSG_WriteByte (msg, (bits>>8)&255 );
485: MSG_WriteByte (msg, (bits>>16)&255 );
486: MSG_WriteByte (msg, (bits>>24)&255 );
487: }
488: else if (bits & 0x00ff0000)
489: {
490: MSG_WriteByte (msg, (bits>>8)&255 );
491: MSG_WriteByte (msg, (bits>>16)&255 );
492: }
493: else if (bits & 0x0000ff00)
494: {
495: MSG_WriteByte (msg, (bits>>8)&255 );
496: }
497: //----------
498:
499: if (bits & U_NUMBER16)
500: MSG_WriteShort (msg, to->number);
501: else
502: MSG_WriteByte (msg, to->number);
503: if (bits & U_MODEL)
504: MSG_WriteByte (msg, to->modelindex);
505: if (bits & U_MODEL2)
506: MSG_WriteByte (msg, to->modelindex2);
507: if (bits & U_MODEL3)
508: MSG_WriteByte (msg, to->modelindex3);
509: if (bits & U_MODEL4)
510: MSG_WriteByte (msg, to->modelindex4);
511: if (bits & U_FRAME8)
512: MSG_WriteByte (msg, to->frame);
513: if (bits & U_FRAME16)
514: MSG_WriteShort (msg, to->frame);
515: if ((bits & U_SKIN8) && (bits & U_SKIN16)) //used for laser colors
516: MSG_WriteLong (msg, to->skinnum);
517: else if (bits & U_SKIN8)
518: MSG_WriteByte (msg, to->skinnum);
519: else if (bits & U_SKIN16)
520: MSG_WriteShort (msg, to->skinnum);
521:
522: if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
523: MSG_WriteLong (msg, to->effects);
524: else if (bits & U_EFFECTS8)
525: MSG_WriteByte (msg, to->effects);
526: else if (bits & U_EFFECTS16)
527: MSG_WriteShort (msg, to->effects);
528: if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
529: MSG_WriteLong (msg, to->renderfx);
530: else if (bits & U_RENDERFX8)
531: MSG_WriteByte (msg, to->renderfx);
532: else if (bits & U_RENDERFX16)
533: MSG_WriteShort (msg, to->renderfx);
534: if (bits & U_ORIGIN1)
535: MSG_WriteCoord (msg, to->origin[0]);
536: if (bits & U_ORIGIN2)
537: MSG_WriteCoord (msg, to->origin[1]);
538: if (bits & U_ORIGIN3)
539: MSG_WriteCoord (msg, to->origin[2]);
540: if (bits & U_ANGLE1)
541: MSG_WriteAngle(msg, to->angles[0]);
542: if (bits & U_ANGLE2)
543: MSG_WriteAngle(msg, to->angles[1]);
544: if (bits & U_ANGLE3)
545: MSG_WriteAngle(msg, to->angles[2]);
546: if (bits & U_OLDORIGIN)
547: {
548: MSG_WriteCoord (msg, to->old_origin[0]);
549: MSG_WriteCoord (msg, to->old_origin[1]);
550: MSG_WriteCoord (msg, to->old_origin[2]);
551: }
552: if (bits & U_SOUND)
553: MSG_WriteByte (msg, to->sound);
554: if (bits & U_EVENT)
555: MSG_WriteByte (msg, to->event);
556: if (bits & U_SOLID)
557: MSG_WriteShort (msg, to->solid);
558: }
559: //============================================================
560: //
561: // reading functions
562: //
563: void MSG_BeginReading (sizebuf_t *msg)
564: {
565: msg->readcount = 0;
566: }
567: // returns -1 if no more characters are available
568: int MSG_ReadChar (sizebuf_t *msg_read)
569: {
570: int c;
571:
572: if (msg_read->readcount+1 > msg_read->cursize)
573: c = -1;
574: else
575: c = (signed char)msg_read->data[msg_read->readcount];
576: msg_read->readcount++;
577:
578: return c;
579: }
580: int MSG_ReadByte (sizebuf_t *msg_read)
581: {
582: int c;
583:
584: if (msg_read->readcount+1 > msg_read->cursize)
585: c = -1;
586: else
587: c = (unsigned char)msg_read->data[msg_read->readcount];
588: msg_read->readcount++;
589:
590: return c;
591: }
592: int MSG_ReadShort (sizebuf_t *msg_read)
593: {
594: int c;
595:
596: if (msg_read->readcount+2 > msg_read->cursize)
597: c = -1;
598: else
599: c = (short)(msg_read->data[msg_read->readcount]
600: + (msg_read->data[msg_read->readcount+1]<<8));
601:
602: msg_read->readcount += 2;
603:
604: return c;
605: }
606: int MSG_ReadLong (sizebuf_t *msg_read)
607: {
608: int c;
609:
610: if (msg_read->readcount+4 > msg_read->cursize)
611: c = -1;
612: else
613: c = msg_read->data[msg_read->readcount]
614: + (msg_read->data[msg_read->readcount+1]<<8)
615: + (msg_read->data[msg_read->readcount+2]<<16)
616: + (msg_read->data[msg_read->readcount+3]<<24);
617:
618: msg_read->readcount += 4;
619:
620: return c;
621: }
622: float MSG_ReadFloat (sizebuf_t *msg_read)
623: {
624: union
625: {
626: byte b[4];
627: float f;
628: int l;
629: } dat;
630:
631: if (msg_read->readcount+4 > msg_read->cursize)
632: dat.f = -1;
633: else
634: {
635: dat.b[0] = msg_read->data[msg_read->readcount];
636: dat.b[1] = msg_read->data[msg_read->readcount+1];
637: dat.b[2] = msg_read->data[msg_read->readcount+2];
638: dat.b[3] = msg_read->data[msg_read->readcount+3];
639: }
640: msg_read->readcount += 4;
641:
642: dat.l = LittleLong (dat.l);
643: return dat.f;
644: }
645: char *MSG_ReadString (sizebuf_t *msg_read)
646: {
647: static char string[2048];
648: int l,c;
649:
650: l = 0;
651: do
652: {
653: c = MSG_ReadChar (msg_read);
654: if (c == -1 || c == 0)
655: break;
656: string[l] = c;
657: l++;
658: } while (l < sizeof(string)-1);
659:
660: string[l] = 0;
661:
662: return string;
663: }
664: char *MSG_ReadStringLine (sizebuf_t *msg_read)
665: {
666: static char string[2048];
667: int l,c;
668:
669: l = 0;
670: do
671: {
672: c = MSG_ReadChar (msg_read);
673: if (c == -1 || c == 0 || c == '\n')
674: break;
675: string[l] = c;
676: l++;
677: } while (l < sizeof(string)-1);
678:
679: string[l] = 0;
680:
681: return string;
682: }
683: float MSG_ReadCoord (sizebuf_t *msg_read)
684: {
685: return MSG_ReadShort(msg_read) * (1.0/8);
686: }
687: void MSG_ReadPos (sizebuf_t *msg_read, vec3_t pos)
688: {
689: pos[0] = MSG_ReadShort(msg_read) * (1.0/8);
690: pos[1] = MSG_ReadShort(msg_read) * (1.0/8);
691: pos[2] = MSG_ReadShort(msg_read) * (1.0/8);
692: }
693: float MSG_ReadAngle (sizebuf_t *msg_read)
694: {
695: return MSG_ReadChar(msg_read) * (360.0/256);
696: }
697: float MSG_ReadAngle16 (sizebuf_t *msg_read)
698: {
699: return SHORT2ANGLE(MSG_ReadShort(msg_read));
700: }
701: void MSG_ReadDeltaUsercmd (sizebuf_t *msg_read, usercmd_t *from, usercmd_t *move)
702: {
703: int bits;
704: memcpy (move, from, sizeof(*move));
705: bits = MSG_ReadByte (msg_read);
706:
707: // read current angles
708: if (bits & CM_ANGLE1)
709: move->angles[0] = MSG_ReadShort (msg_read);
710: if (bits & CM_ANGLE2)
711: move->angles[1] = MSG_ReadShort (msg_read);
712: if (bits & CM_ANGLE3)
713: move->angles[2] = MSG_ReadShort (msg_read);
714:
715: // read movement
716: if (bits & CM_FORWARD)
717: move->forwardmove = MSG_ReadShort (msg_read);
718: if (bits & CM_SIDE)
719: move->sidemove = MSG_ReadShort (msg_read);
720: if (bits & CM_UP)
721: move->upmove = MSG_ReadShort (msg_read);
722:
723: // read buttons
724: if (bits & CM_BUTTONS)
725: move->buttons = MSG_ReadByte (msg_read);
726: if (bits & CM_IMPULSE)
727: move->impulse = MSG_ReadByte (msg_read);
728: // read time to run command
729: move->msec = MSG_ReadByte (msg_read);
730: // read the light level
731: move->lightlevel = MSG_ReadByte (msg_read);
732: }
733: void MSG_ReadData (sizebuf_t *msg_read, void *data, int len)
734: {
735: int i;
736: for (i=0 ; i<len ; i++)
737: ((byte *)data)[i] = MSG_ReadByte (msg_read);
738: }
739: //===========================================================================
740: void SZ_Init (sizebuf_t *buf, byte *data, int length)
741: {
742: memset (buf, 0, sizeof(*buf));
743: buf->data = data;
744: buf->maxsize = length;
745: }
746: void SZ_Clear (sizebuf_t *buf)
747: {
748: buf->cursize = 0;
749: buf->overflowed = false;
750: }
751: void *SZ_GetSpace (sizebuf_t *buf, int length)
752: {
753: void *data;
754:
755: if (buf->cursize + length > buf->maxsize)
756: {
757: if (!buf->allowoverflow)
758: Com_Error (ERR_FATAL, "SZ_GetSpace: overflow without allowoverflow set");
759:
760: if (length > buf->maxsize)
761: Com_Error (ERR_FATAL, "SZ_GetSpace: %i is > full buffer size", length);
762:
763: Com_Printf ("SZ_GetSpace: overflow\n");
764: SZ_Clear (buf);
765: buf->overflowed = true;
766: }
767: data = buf->data + buf->cursize;
768: buf->cursize += length;
769:
770: return data;
771: }
772: void SZ_Write (sizebuf_t *buf, void *data, int length)
773: {
774: memcpy (SZ_GetSpace(buf,length),data,length);
775: }
776: void SZ_Print (sizebuf_t *buf, char *data)
777: {
778: int len;
779:
780: len = strlen(data)+1;
781: if (buf->cursize)
782: {
783: if (buf->data[buf->cursize-1])
784: memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
785: else
786: memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
787: }
788: else
789: memcpy ((byte *)SZ_GetSpace(buf, len),data,len);
790: }
791: //============================================================================
792: /*
793: ================
794: COM_CheckParm
795: Returns the position (1 to argc-1) in the program's argument list
796: where the given parameter apears, or 0 if not present
797: ================
798: */
799: int COM_CheckParm (char *parm)
800: {
801: int i;
802:
803: for (i=1 ; i<com_argc ; i++)
804: {
805: if (!strcmp (parm,com_argv[i]))
806: return i;
807: }
808:
809: return 0;
810: }
811: int COM_Argc (void)
812: {
813: return com_argc;
814: }
815: char *COM_Argv (int arg)
816: {
817: if (arg < 0 || arg >= com_argc || !com_argv[arg])
818: return "";
819: return com_argv[arg];
820: }
821: void COM_ClearArgv (int arg)
822: {
823: if (arg < 0 || arg >= com_argc || !com_argv[arg])
824: return;
825: com_argv[arg] = "";
826: }
827: /*
828: ================
829: COM_InitArgv
830: ================
831: */
832: void COM_InitArgv (int argc, char **argv)
833: {
834: int i;
835: if (argc > MAX_NUM_ARGVS)
836: Com_Error (ERR_FATAL, "argc > MAX_NUM_ARGVS");
837: com_argc = argc;
838: for (i=0 ; i<argc ; i++)
839: {
840: if (!argv[i] || strlen(argv[i]) >= MAX_TOKEN_CHARS )
841: com_argv[i] = "";
842: else
843: com_argv[i] = argv[i];
844: }
845: }
846: /*
847: ================
848: COM_AddParm
849: Adds the given string at the end of the current argument list
850: ================
851: */
852: void COM_AddParm (char *parm)
853: {
854: if (com_argc == MAX_NUM_ARGVS)
855: Com_Error (ERR_FATAL, "COM_AddParm: MAX_NUM)ARGS");
856: com_argv[com_argc++] = parm;
857: }
858: /// just for debugging
859: int memsearch (byte *start, int count, int search)
860: {
861: int i;
862:
863: for (i=0 ; i<count ; i++)
864: if (start[i] == search)
865: return i;
866: return -1;
867: }
868: char *CopyString (char *in)
869: {
870: char *out;
871:
872: out = Z_Malloc (strlen(in)+1);
873: strcpy (out, in);
874: return out;
875: }
876: void Info_Print (char *s)
877: {
878: char key[512];
879: char value[512];
880: char *o;
881: int l;
882: if (*s == '\\')
883: s++;
884: while (*s)
885: {
886: o = key;
887: while (*s && *s != '\\')
888: *o++ = *s++;
889: l = o - key;
890: if (l < 20)
891: {
892: memset (o, ' ', 20-l);
893: key[20] = 0;
894: }
895: else
896: *o = 0;
897: Com_Printf ("%s", key);
898: if (!*s)
899: {
900: Com_Printf ("MISSING VALUE\n");
901: return;
902: }
903: o = value;
904: s++;
905: while (*s && *s != '\\')
906: *o++ = *s++;
907: *o = 0;
908: if (*s)
909: s++;
910: Com_Printf ("%s\n", value);
911: }
912: }
913: /*
914: ==============================================================================
915: ZONE MEMORY ALLOCATION
916: just cleared malloc with counters now...
917: ==============================================================================
918: */
919: #define Z_MAGIC 0x1d1d
920: typedef struct zhead_s
921: {
922: struct zhead_s *prev, *next;
923: short magic;
924: short tag; // for group free
925: int size;
926: } zhead_t;
927: zhead_t z_chain;
928: int z_count, z_bytes;
929: /*
930: ========================
931: Z_Free
932: ========================
933: */
934: void Z_Free (void *ptr)
935: {
936: zhead_t *z;
937: z = ((zhead_t *)ptr) - 1;
938: if (z->magic != Z_MAGIC)
939: Com_Error (ERR_FATAL, "Z_Free: bad magic");
940: z->prev->next = z->next;
941: z->next->prev = z->prev;
942: z_count--;
943: z_bytes -= z->size;
944: free (z);
945: }
946: /*
947: ========================
948: Z_Stats_f
949: ========================
950: */
951: void Z_Stats_f (void)
952: {
953: Com_Printf ("%i bytes in %i blocks\n", z_bytes, z_count);
954: }
955: /*
956: ========================
957: Z_FreeTags
958: ========================
959: */
960: void Z_FreeTags (int tag)
961: {
962: zhead_t *z, *next;
963: for (z=z_chain.next ; z != &z_chain ; z=next)
964: {
965: next = z->next;
966: if (z->tag == tag)
967: Z_Free ((void *)(z+1));
968: }
969: }
970: /*
971: ========================
972: Z_TagMalloc
973: ========================
974: */
975: void *Z_TagMalloc (int size, int tag)
976: {
977: zhead_t *z;
978:
979: size = size + sizeof(zhead_t);
980: z = malloc(size);
981: if (!z)
982: Com_Error (ERR_FATAL, "Z_Malloc: failed on allocation of %i bytes",size);
983: memset (z, 0, size);
984: z_count++;
985: z_bytes += size;
986: z->magic = Z_MAGIC;
987: z->tag = tag;
988: z->size = size;
989: z->next = z_chain.next;
990: z->prev = &z_chain;
991: z_chain.next->prev = z;
992: z_chain.next = z;
993: return (void *)(z+1);
994: }
995: /*
996: ========================
997: Z_Malloc
998: ========================
999: */
1000: void *Z_Malloc (int size)
1001: {
1002: return Z_TagMalloc (size, 0);
1003: }
1004: //============================================================================
1005:
1006:
1007: /*
1008: ====================
1009: COM_BlockSequenceCheckByte
1010:
1011: For proxy protecting
1012: ====================
1013: */
1014: byte COM_BlockSequenceCheckByte (byte *base, int length, int sequence)
1015: {
1016: int checksum;
1017: byte buf[64];
1018: int n;
1019: byte *p;
1020:
1021: n = sequence % (NUMVERTEXNORMALS * sizeof(vec3_t));
1022: p = ((byte *)bytedirs)+n;
1023: if (length > 60)
1024: length = 60;
1025: memcpy (buf, base, length);
1026: buf[length] = (sequence & 0xff) ^ *p++;
1027: buf[length+1] = *p++;
1028: buf[length+2] = ((sequence>>8) & 0xff) ^ *p++;
1029: buf[length+3] = *p;
1030: length += 4;
1031:
1032: checksum = Com_BlockChecksum (buf, length);
1033:
1034: checksum &= 0xff;
1035:
1036: return checksum;
1037: }
1038:
1039: //========================================================
1040: float frand(void)
1041: {
1042: return (rand()&32767)* (1.0/32767);
1043: }
1044: float crand(void)
1045: {
1046: return (rand()&32767)* (2.0/32767) - 1;
1047: }
1048: void Key_Init (void);
1049: void SCR_EndLoadingPlaque (void);
1050: /*
1051: =============
1052: Com_Error_f
1053: Just throw a fatal error to
1054: test error shutdown procedures
1055: =============
1056: */
1057: void Com_Error_f (void)
1058: {
1059: Com_Error (ERR_FATAL, "%s", Cmd_Argv(1));
1060: }
1061:
1062:
1063: /*
1064: =================
1065: Qcommon_Init
1066: =================
1067: */
1068: void Qcommon_Init (int argc, char **argv)
1069: {
1070: char *s;
1071: if (setjmp (abortframe) )
1072: Sys_Error ("Error during initialization");
1073: z_chain.next = z_chain.prev = &z_chain;
1074: // prepare enough of the subsystems to handle
1075: // cvar and command buffer management
1076: COM_InitArgv (argc, argv);
1077: Swap_Init ();
1078: Cbuf_Init ();
1079: Cmd_Init ();
1080: Cvar_Init ();
1081: Key_Init ();
1082: // we need to add the early commands twice, because
1083: // a basedir or cddir needs to be set before execing
1084: // config files, but we want other parms to override
1085: // the settings of the config files
1086: Cbuf_AddEarlyCommands (false);
1087: Cbuf_Execute ();
1088: FS_InitFilesystem ();
1089: Cbuf_AddText ("exec default.cfg\n");
1090: Cbuf_AddText ("exec config.cfg\n");
1091: Cbuf_AddEarlyCommands (true);
1092: Cbuf_Execute ();
1093: //
1094: // init commands and vars
1095: //
1096: Cmd_AddCommand ("z_stats", Z_Stats_f);
1097: Cmd_AddCommand ("error", Com_Error_f);
1098: host_speeds = Cvar_Get ("host_speeds", "0", 0);
1099: log_stats = Cvar_Get ("log_stats", "0", 0);
1100: developer = Cvar_Get ("developer", "0", 0);
1101: timescale = Cvar_Get ("timescale", "1", 0);
1102: fixedtime = Cvar_Get ("fixedtime", "0", 0);
1103: logfile_active = Cvar_Get ("logfile", "0", 0);
1104: showtrace = Cvar_Get ("showtrace", "0", 0);
1105: dedicated = Cvar_Get ("dedicated", "0", CVAR_NOSET);
1106: s = va("%4.2f %s %s %s", VERSION, CPUSTRING, __DATE__, BUILDSTRING);
1107: Cvar_Get ("version", s, CVAR_SERVERINFO|CVAR_NOSET);
1108: if (dedicated->value)
1109: Cmd_AddCommand ("quit", Com_Quit);
1110: Sys_Init ();
1111: NET_Init ();
1112: Netchan_Init ();
1113: SV_Init ();
1114: CL_Init ();
1115: // add + commands from command line
1116: if (!Cbuf_AddLateCommands ())
1117: { // if the user didn't give any commands, run default action
1118: if (!dedicated->value)
1119: Cbuf_AddText ("d1\n");
1120: else
1121: Cbuf_AddText ("dedicated_start\n");
1122: Cbuf_Execute ();
1123: }
1124: else
1125: { // the user asked for something explicit
1126: // so drop the loading plaque
1127: SCR_EndLoadingPlaque ();
1128: }
1129: Com_Printf ("====== Quake2 Initialized ======\n\n");
1130: }
1131: /*
1132: =================
1133: Qcommon_Frame
1134: =================
1135: */
1136: void Qcommon_Frame (int msec)
1137: {
1138: char *s;
1139: int time_before, time_between, time_after;
1140: if (setjmp (abortframe) )
1141: return; // an ERR_DROP was thrown
1142:
1143: if ( log_stats->modified )
1144: {
1145: log_stats->modified = false;
1146: if ( log_stats->value )
1147: {
1148: if ( log_stats_file )
1149: {
1150: fclose( log_stats_file );
1151: log_stats_file = 0;
1152: }
1153: log_stats_file = fopen( "stats.log", "w" );
1154: if ( log_stats_file )
1155: fprintf( log_stats_file, "entities,dlights,parts,frame time\n" );
1156: }
1157: else
1158: {
1159: if ( log_stats_file )
1160: {
1161: fclose( log_stats_file );
1162: log_stats_file = 0;
1163: }
1164: }
1165: }
1166: if (fixedtime->value)
1167: msec = fixedtime->value;
1168: else if (timescale->value)
1169: {
1170: msec *= timescale->value;
1171: if (msec < 1)
1172: msec = 1;
1173: }
1174:
1175: if (showtrace->value)
1176: {
1177: extern int c_traces, c_brush_traces;
1178: extern int c_pointcontents;
1179: Com_Printf ("%4i traces %4i points\n", c_traces, c_pointcontents);
1180: c_traces = 0;
1181: c_brush_traces = 0;
1182: c_pointcontents = 0;
1183: }
1184: do
1185: {
1186: s = Sys_ConsoleInput ();
1187: if (s)
1188: Cbuf_AddText (va("%s\n",s));
1189: } while (s);
1190: Cbuf_Execute ();
1191: if (host_speeds->value)
1192: time_before = Sys_Milliseconds ();
1193: SV_Frame (msec);
1194: if (host_speeds->value)
1195: time_between = Sys_Milliseconds ();
1196: CL_Frame (msec);
1197: if (host_speeds->value)
1198: time_after = Sys_Milliseconds ();
1199: if (host_speeds->value)
1200: {
1201: int all, sv, gm, cl, rf;
1202: all = time_after - time_before;
1203: sv = time_between - time_before;
1204: cl = time_after - time_between;
1205: gm = time_after_game - time_before_game;
1206: rf = time_after_ref - time_before_ref;
1207: sv -= gm;
1208: cl -= rf;
1209: Com_Printf ("all:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n",
1210: all, sv, gm, cl, rf);
1211: }
1212: }
1213: /*
1214: =================
1215: Qcommon_Shutdown
1216: =================
1217: */
1218: void Qcommon_Shutdown (void)
1219: {
1220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.