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
23 #ifdef _WIN32
24 #define OPENSSLEXPORT __cdecl
25 #endif
26 #ifdef USE_OPENSSL
27 #include <openssl/md4.h>
28 #endif
29
30 #include <setjmp.h>
31
32 #define MAXPRINTMSG 4096
33
34 #define MAX_NUM_ARGVS 50
35
36 qboolean q2_initialized = false;
37
38 entity_state_t null_entity_state;
39 usercmd_t null_usercmd;
40 cvar_t uninitialized_cvar;
41
42 cvar_t *z_debug;
43 cvar_t *z_buggygame;
44 cvar_t *z_allowcorruption;
45
46 cvar_t *cl_quietstartup;
47
48 static int com_argc;
49 static char *com_argv[MAX_NUM_ARGVS+1];
50
51 char *binary_name;
52
53 //int realtime;
54 jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame
55
56 //static FILE *log_stats_file;
57
58 cvar_t *host_speeds;
59 cvar_t *log_stats;
60 cvar_t *developer = &uninitialized_cvar;
61
62 static cvar_t *timescale;
63 static cvar_t *fixedtime;
64
65 static cvar_t *logfile_active; // 1 = buffer log, 2 = flush after each print
66 static cvar_t *logfile_timestamp;
67 static cvar_t *logfile_timestamp_format;
68 static cvar_t *logfile_name;
69 static cvar_t *logfile_filterlevel = &uninitialized_cvar;
70 static cvar_t *con_filterlevel = &uninitialized_cvar;
71
72 #ifndef DEDICATED_ONLY
73 cvar_t *showtrace;
74 #endif
75
76 #ifndef NO_SERVER
77 cvar_t *dedicated = &uninitialized_cvar;
78 #endif
79
80 cvar_t *sys_loopstyle = &uninitialized_cvar;
81
82 //r1: unload DLLs on crash?
83 cvar_t *dbg_unload = &uninitialized_cvar;
84
85 //r1: throw int3 on ERR_FATAL?
86 static cvar_t *dbg_crash_on_fatal_error = &uninitialized_cvar;
87
88 //r1: throw all err as fatal?
89 static cvar_t *err_fatal = &uninitialized_cvar;
90
91 static FILE *logfile;
92
93 int server_state;
94
95 // host_speeds times
96 unsigned int time_before_game;
97 unsigned int time_after_game;
98 unsigned int time_before_ref;
99 unsigned int time_after_ref;
100
101 // for profiling
102 #ifndef NPROFILE
103 static int msg_local_hits;
104 static int msg_malloc_hits;
105
106 static int messageSizes[1500];
107 #endif
108
109 char *svc_strings[256] =
110 {
111 "svc_bad",
112
113 "svc_muzzleflash",
114 "svc_muzzlflash2",
115 "svc_temp_entity",
116 "svc_layout",
117 "svc_inventory",
118
119 "svc_nop",
120 "svc_disconnect",
121 "svc_reconnect",
122 "svc_sound",
123 "svc_print",
124 "svc_stufftext",
125 "svc_serverdata",
126 "svc_configstring",
127 "svc_spawnbaseline",
128 "svc_centerprint",
129 "svc_download",
130 "svc_playerinfo",
131 "svc_packetentities",
132 "svc_deltapacketentities",
133 "svc_frame",
134 "svc_zpacket",
135 "svc_zdownload",
136 "svc_playerupdate",
137 "svc_setting",
138 };
139
140 tagmalloc_tag_t tagmalloc_tags[] =
141 {
142 {TAGMALLOC_NOT_TAGGED, "NOT_TAGGED", 0},
143 {TAGMALLOC_CMDBUFF, "CMDBUFF", 0},
144 {TAGMALLOC_CMDTOKEN, "CMDTOKEN", 0},
145 {TAGMALLOC_CMD, "CMD", 0},
146 {TAGMALLOC_LOADMAP, "LOADMAP", 0},
147 {TAGMALLOC_ALIAS, "ALIAS", 0},
148 {TAGMALLOC_TRIGGER, "TRIGGER", 0},
149 {TAGMALLOC_CVAR, "CVAR", 0},
150 {TAGMALLOC_FSCACHE, "FSCACHE", 0},
151 {TAGMALLOC_FSLOADFILE, "FSLOADFILE", 0},
152 {TAGMALLOC_FSLOADPAK, "FSLOADPAK", 0},
153 {TAGMALLOC_SEARCHPATH, "SEARCHPATH", 0},
154 {TAGMALLOC_LINK, "LINK", 0},
155 {TAGMALLOC_CLIENTS, "CLIENTS", 0},
156 {TAGMALLOC_CL_ENTS, "CL_ENTS", 0},
157 {TAGMALLOC_CL_BASELINES, "CL_BASELINES", 0},
158 {TAGMALLOC_CL_MESSAGES, "CL_MESSAGES", 0},
159 {TAGMALLOC_CL_PARTICLES, "CL_PARTICLES", 0},
160
161 {TAGMALLOC_CLIENT_DOWNLOAD, "CLIENT_DOWNLOAD", 0},
162 {TAGMALLOC_CLIENT_KEYBIND, "CLIENT_KEYBIND", 0},
163 {TAGMALLOC_CLIENT_SFX, "CLIENT_SFX", 0},
164 {TAGMALLOC_CLIENT_SOUNDCACHE, "CLIENT_SOUNDCACHE", 0},
165 {TAGMALLOC_CLIENT_DLL, "CLIENT_DLL", 0},
166 {TAGMALLOC_CLIENT_LOC, "CLIENT_LOC", 0},
167 {TAGMALLOC_CLIENT_IGNORE, "CLIENT_IGNORE", 0},
168 {TAGMALLOC_BLACKHOLE, "BLACKHOLE", 0},
169 {TAGMALLOC_CVARBANS, "CVARBANS", 0},
170 //{TAGMALLOC_MSG_QUEUE, "MSGQUEUE", 0},
171 {TAGMALLOC_CMDBANS, "CMDBANS", 0},
172 {TAGMALLOC_REDBLACK, "REDBLACK", 0},
173 {TAGMALLOC_LRCON, "LRCON", 0},
174 #ifdef ANTICHEAT
175 {TAGMALLOC_ANTICHEAT, "ANTICHEAT", 0},
176 #endif
177 {TAGMALLOC_MAX_TAGS, "*** UNDEFINED ***", 0}
178 };
179
180 void (EXPORT *Z_Free)(const void *buf);
181 void *(EXPORT *Z_TagMalloc)(int size, int tag);
182
183 /*
184 ============================================================================
185
186 CLIENT / SERVER interactions
187
188 ============================================================================
189 */
190
191 int rd_target;
192
193 static char *rd_buffer;
194 static int rd_buffersize;
195 static void (*rd_flush)(int target, char *buffer);
196
Com_BeginRedirect(int target,char * buffer,int buffersize,void * flush)197 void Com_BeginRedirect (int target, char *buffer, int buffersize, void *flush)
198 {
199 if (!target || !buffer || !buffersize || !flush)
200 return;
201 rd_target = target;
202 rd_buffer = buffer;
203 rd_buffersize = buffersize;
204 rd_flush = (void (*)(int, char *))flush;
205
206 *rd_buffer = 0;
207 }
208
Com_EndRedirect(qboolean flush)209 void Com_EndRedirect (qboolean flush)
210 {
211 if (!rd_target)
212 return;
213
214 if (flush)
215 rd_flush(rd_target, rd_buffer);
216
217 rd_target = 0;
218 rd_buffer = NULL;
219 rd_buffersize = 0;
220 rd_flush = NULL;
221 }
222
223 /*
224 =============
225 Com_Printf
226
227 Both client and server can use this, and it will output
228 to the apropriate place.
229 =============
230 */
Com_Printf(const char * fmt,int level,...)231 void Com_Printf (const char *fmt, int level, ...)
232 {
233 va_list argptr;
234 char msg[MAXPRINTMSG];
235
236 if ((level & con_filterlevel->intvalue) && (level & logfile_filterlevel->intvalue))
237 return;
238
239 va_start (argptr, level);
240 if (Q_vsnprintf (msg, sizeof(msg)-1, fmt, argptr) < 0)
241 Com_Printf ("WARNING: Com_Printf: message overflow.\n", LOG_GENERAL);
242 va_end (argptr);
243
244 msg[sizeof(msg)-1] = 0;
245
246 if (rd_target)
247 {
248 if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1))
249 {
250 rd_flush(rd_target, rd_buffer);
251 *rd_buffer = 0;
252 }
253 strcat (rd_buffer, msg);
254 return;
255 }
256
257 if (!(level & con_filterlevel->intvalue))
258 {
259 #ifndef DEDICATED_ONLY
260 Con_Print (msg);
261 #endif
262
263 // also echo to debugging console
264 #ifndef NO_SERVER
265 Sys_ConsoleOutput (msg);
266 #endif
267 }
268
269 // logfile
270 if (logfile_active && logfile_active->intvalue && !(level & logfile_filterlevel->intvalue))
271 {
272 char name[MAX_QPATH];
273 char timestamp[64];
274 char *p;
275
276 //r1: strip highbits and control chars
277 p = msg;
278 while (p[0])
279 {
280 p[0] &= ~128;
281 if (p[0] < 32 && !isspace(p[0]))
282 p[0] = '-';
283 p++;
284 }
285
286 if (!logfile)
287 {
288 //ensure someone malicious with rcon can't overwrite arbitrary files...
289 if (strstr (logfile_name->string, "..") || strchr (logfile_name->string, '/') || strchr (logfile_name->string, '\\'))
290 {
291 Cvar_ForceSet ("logfile", "0");
292 Com_Printf ("ALERT: Refusing to open logfile %s, illegal filename.\n", LOG_GENERAL|LOG_WARNING, logfile_name->string);
293 return;
294 }
295 Com_sprintf (name, sizeof(name), "%s/%s", FS_Gamedir (), logfile_name->string);
296
297 if (logfile_active->intvalue > 2)
298 logfile = fopen (name, "a");
299 else
300 logfile = fopen (name, "w");
301
302 if (!logfile)
303 {
304 Cvar_ForceSet ("logfile", "0");
305 Com_Printf ("ALERT: Couldn't open logfile %s for writing, logfile disabled.\n", LOG_GENERAL|LOG_WARNING, logfile_name->string);
306 return;
307 }
308 }
309
310 if (logfile)
311 {
312 if (logfile_timestamp->intvalue)
313 {
314 char *line;
315 char *msgptr;
316
317 static qboolean insert_timestamp = true;
318
319 time_t tm;
320 time(&tm);
321 strftime (timestamp, sizeof(timestamp)-1, logfile_timestamp_format->string, localtime(&tm));
322
323 msgptr = msg;
324 line = strchr (msgptr, '\n');
325 while (line)
326 {
327 if (insert_timestamp)
328 {
329 fprintf (logfile, "%s ", timestamp);
330 insert_timestamp = false;
331 }
332 *line = 0;
333
334 if (fprintf (logfile, "%s\n", msgptr) < 0)
335 {
336 fclose (logfile);
337 logfile = NULL;
338 Cvar_ForceSet ("logfile", "0");
339 Com_Printf ("ALERT: Error writing to logfile %s, file closed.\n", LOG_GENERAL|LOG_WARNING, logfile_name->string);
340 return;
341 }
342
343 insert_timestamp = true;
344 line++;
345 msgptr = line;
346
347 if (!*line)
348 break;
349
350 line = strchr (msgptr, '\n');
351 }
352
353 if (insert_timestamp)
354 {
355 fprintf (logfile, "%s ", timestamp);
356 insert_timestamp = false;
357 }
358
359 fprintf (logfile, "%s", msgptr);
360 }
361 else
362 {
363 fwrite (msg, strlen(msg), 1, logfile);
364 }
365 }
366
367 //r1: allow logging > 2 (append) but not forcing flushing.
368 if (logfile_active->intvalue & 1)
369 fflush (logfile);
370 }
371 }
372
373
374 /*
375 ================
376 Com_DPrintf
377
378 A Com_Printf that only shows up if the "developer" cvar is set
379 ================
380 */
_Com_DPrintf(char const * fmt,...)381 void _Com_DPrintf (char const *fmt, ...)
382 {
383 #if !(__STDC_VERSION__ == 199901L || _MSC_VER >= 1400 && !defined _M_AMD64)
384 if (!developer->intvalue)
385 {
386 return;
387 }
388 else
389 #endif
390 {
391 va_list argptr;
392 char msg[MAXPRINTMSG];
393
394 va_start (argptr,fmt);
395 if (Q_vsnprintf (msg, sizeof(msg)-1, fmt, argptr) < 0)
396 Com_Printf ("WARNING: Com_DPrintf: message overflow.\n", LOG_WARNING);
397 va_end (argptr);
398
399 msg[sizeof(msg)-1] = 0;
400
401 Com_Printf ("%s", LOG_DEBUG, msg);
402 }
403 }
404
405
406 /*
407 =============
408 Com_Error
409
410 Both client and server can use this, and it will
411 do the apropriate things.
412 =============
413 */
Com_Error(int code,const char * fmt,...)414 void Com_Error (int code, const char *fmt, ...)
415 {
416 va_list argptr;
417 static char msg[MAXPRINTMSG];
418 static qboolean recursive;
419
420 if (recursive && code != ERR_DIE)
421 Sys_Error ("recursive error after: %s", msg);
422 recursive = true;
423
424 va_start (argptr,fmt);
425 vsnprintf (msg, sizeof(msg)-1, fmt,argptr);
426 va_end (argptr);
427
428 Com_EndRedirect (false);
429
430 if (err_fatal->intvalue)
431 code = ERR_FATAL;
432
433 if (code == ERR_DISCONNECT)
434 {
435 Com_Printf ("Disconnected by server!\n", LOG_CLIENT);
436 #ifndef DEDICATED_ONLY
437 CL_Drop (false, true);
438 #endif
439 recursive = false;
440
441 longjmp (abortframe, -1);
442 }
443 else if (code == ERR_DROP || code == ERR_GAME || code == ERR_NET || code == ERR_HARD)
444 {
445 int state = Com_ServerState() == ss_dead ? 0 : 1;
446 Com_Printf ("********************\nERROR: %s\n********************\n", LOG_GENERAL, msg);
447 #ifndef NO_SERVER
448 SV_Shutdown (va("Server exited: %s\n", msg), false, false);
449 #endif
450 #ifndef DEDICATED_ONLY
451 CL_Drop (code == ERR_NET, false);
452 #endif
453 recursive = false;
454
455 //r1: auto-restart server code on game crash
456 if (state && (code == ERR_GAME || code == ERR_DROP))
457 {
458 const char *resmap;
459
460 resmap = Cvar_VariableString ("sv_restartmap");
461
462 if (resmap[0])
463 Cmd_ExecuteString (va ("map %s", resmap));
464 }
465
466 longjmp (abortframe, -1);
467 }
468 else
469 {
470 printf ("%s\n", msg);
471 if (dbg_crash_on_fatal_error->intvalue)
472 Sys_DebugBreak ();
473
474 //an err_die means the whole game is about to explode, avoid running any extra code if possible
475 if (code != ERR_DIE)
476 {
477 #ifndef NO_SERVER
478 SV_Shutdown (va("Server fatal crashed: %s\n", msg), false, true);
479 #endif
480 #ifndef DEDICATED_ONLY
481 if (dbg_unload->intvalue)
482 CL_Shutdown ();
483 #endif
484 }
485 }
486
487 if (logfile)
488 {
489 fprintf (logfile, "Fatal Error\n*****************************\n"
490 "Server fatal crashed: %s\n"
491 "*****************************\n", msg);
492 fclose (logfile);
493 logfile = NULL;
494 }
495
496 Sys_Error ("%s", msg);
497 recursive = false;
498 }
499
500
501 /*
502 =============
503 Com_Quit
504
505 Both client and server can use this, and it will
506 do the apropriate things.
507 =============
508 */
Com_Quit(void)509 void Com_Quit (void)
510 {
511 //r1: optional quit message, reworded "Server quit"
512 #ifndef NO_SERVER
513 if (Cmd_Argc() > 1)
514 SV_Shutdown (va("Server has shut down: %s\n", Cmd_Args()), false, false);
515 else
516 SV_Shutdown ("Server has shut down\n", false, false);
517 #endif
518 #ifndef DEDICATED_ONLY
519 CL_Shutdown ();
520 #endif
521
522 if (logfile)
523 {
524 fclose (logfile);
525 logfile = NULL;
526 }
527
528 Sys_Quit ();
529 }
530
531
532 /*
533 ==================
534 Com_ServerState
535 ==================
536 */
537 /*int Com_ServerState (void)
538 {
539 return server_state;
540 }*/
541
542 /*
543 ==================
544 Com_SetServerState
545 ==================
546 */
547 /*void Com_SetServerState (int state)
548 {
549 server_state = state;
550 }*/
551
552
553 /*
554 ==============================================================================
555
556 MESSAGE IO FUNCTIONS
557
558 Handles byte ordering and avoids alignment errors
559 ==============================================================================
560 */
561
562 vec3_t bytedirs[NUMVERTEXNORMALS] =
563 {
564 #include "../client/anorms.h"
565 };
566
567 //
568 // writing functions
569 //
570
571 byte message_buff[0x10000];
572 sizebuf_t msgbuff;
573
MSG_WriteChar(int c)574 void MSG_WriteChar (int c)
575 {
576 byte *buf;
577
578 /*#ifdef PARANOID
579 if (c < -128 || c > 127)
580 Com_Error (ERR_FATAL, "MSG_WriteChar: range error");
581 #endif*/
582 Q_assert (!(c < -128 || c > 127));
583
584 buf = SZ_GetSpace (&msgbuff, 1);
585 buf[0] = c;
586 }
587
MSG_BeginWriting(int c)588 void MSG_BeginWriting (int c)
589 {
590 byte *buf;
591
592 /*#ifdef PARANOID
593 if (c < 0 || c > 255)
594 Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
595 #endif*/
596 Q_assert (!(c < 0 || c > 255));
597 Q_assert (!msgbuff.cursize);
598
599 #ifdef _DEBUG
600 memset (message_buff, 0xcc, sizeof(message_buff));
601 #endif
602
603 buf = SZ_GetSpace (&msgbuff, 1);
604 buf[0] = c;
605 }
606
MSG_WriteByte(int c)607 void MSG_WriteByte (int c)
608 {
609 byte *buf;
610
611 /*#ifdef PARANOID
612 if (c < 0 || c > 255)
613 Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
614 #endif*/
615 Q_assert (!(c < 0 || c > 255));
616
617 buf = SZ_GetSpace (&msgbuff, 1);
618 buf[0] = c;
619 }
620
MSG_WriteShort(int c)621 void MSG_WriteShort (int c)
622 {
623 byte *buf;
624
625 /*#ifdef PARANOID
626 if (c < ((int16)0x8000) || c > (int16)0x7fff)
627 Com_Error (ERR_FATAL, "MSG_WriteShort: range error");
628 #endif*/
629 //XXX: unsigned shorts are written here too...
630 //Q_assert (!(c < ((int16)0x8000) || c > (int16)0x7fff));
631
632 buf = SZ_GetSpace (&msgbuff, 2);
633 buf[0] = c&0xff;
634 buf[1] = (c>>8) &0xff;
635 }
636
SZ_WriteShort(sizebuf_t * sbuf,int c)637 void SZ_WriteShort (sizebuf_t *sbuf, int c)
638 {
639 byte *buf;
640
641 buf = SZ_GetSpace (sbuf, 2);
642 buf[0] = c&0xff;
643 buf[1] = (c>>8) &0xff;
644 }
645
SZ_WriteLong(sizebuf_t * sbuf,int c)646 void SZ_WriteLong (sizebuf_t *sbuf, int c)
647 {
648 byte *buf;
649
650 buf = SZ_GetSpace (sbuf, 4);
651 buf[0] = c&0xff;
652 buf[1] = (c>>8)&0xff;
653 buf[2] = (c>>16)&0xff;
654 buf[3] = c>>24;
655 }
656
SZ_WriteByte(sizebuf_t * sbuf,int c)657 void SZ_WriteByte (sizebuf_t *sbuf, int c)
658 {
659 byte *buf;
660
661 Q_assert (!(c < 0 || c > 255));
662
663 buf = SZ_GetSpace (sbuf, 1);
664 buf[0] = c;
665 }
666
MSG_WriteLong(int c)667 void MSG_WriteLong (int c)
668 {
669 byte *buf;
670
671 buf = SZ_GetSpace (&msgbuff, 4);
672 buf[0] = c&0xff;
673 buf[1] = (c>>8)&0xff;
674 buf[2] = (c>>16)&0xff;
675 buf[3] = c>>24;
676 }
677
MSG_WriteFloat(float f)678 void MSG_WriteFloat (float f)
679 {
680 union
681 {
682 float f;
683 int l;
684 } dat;
685
686
687 dat.f = f;
688 dat.l = LittleLong (dat.l);
689
690 SZ_Write (&msgbuff, &dat.l, 4);
691 }
692
MSG_WriteString(const char * s)693 void MSG_WriteString (const char *s)
694 {
695 if (!s)
696 SZ_Write (&msgbuff, "", 1);
697 else
698 SZ_Write (&msgbuff, s, (int)strlen(s)+1);
699 }
700
MSG_Write(const void * data,int length)701 void MSG_Write (const void *data, int length)
702 {
703 memcpy (SZ_GetSpace(&msgbuff,length),data,length);
704 }
705
MSG_Print(const char * data)706 void MSG_Print (const char *data)
707 {
708 int len;
709
710 len = (int)strlen(data)+1;
711
712 Q_assert (len > 1);
713
714 if (msgbuff.cursize)
715 {
716 if (message_buff[msgbuff.cursize-1])
717 memcpy ((byte *)SZ_GetSpace(&msgbuff, len),data,len); // no trailing 0
718 else
719 memcpy ((byte *)SZ_GetSpace(&msgbuff, len-1)-1,data,len); // write over trailing 0
720 }
721 else
722 memcpy ((byte *)SZ_GetSpace(&msgbuff, len),data,len);
723 }
724
MSG_GetLength(void)725 int MSG_GetLength (void)
726 {
727 return msgbuff.cursize;
728 }
729
MSG_GetRawMsg(void)730 sizebuf_t *MSG_GetRawMsg (void)
731 {
732 return &msgbuff;
733 }
734
MSG_GetData(void)735 byte *MSG_GetData (void)
736 {
737 return message_buff;
738 }
739
MSG_GetType(void)740 byte MSG_GetType (void)
741 {
742 Q_assert (msgbuff.cursize > 0);
743
744 return message_buff[0];
745 }
746
MSG_FreeData(void)747 void MSG_FreeData (void)
748 {
749 Q_assert (msgbuff.cursize > 0);
750 SZ_Clear (&msgbuff);
751 #ifdef _DEBUG
752 memset (message_buff, 0xcc, sizeof(message_buff));
753 #endif
754 }
755
MSG_Clear(void)756 void MSG_Clear (void)
757 {
758 SZ_Clear (&msgbuff);
759 #ifdef _DEBUG
760 memset (message_buff, 0xcc, sizeof(message_buff));
761 #endif
762 }
763
MSG_EndWriting(sizebuf_t * out)764 void MSG_EndWriting (sizebuf_t *out)
765 {
766 Q_assert (msgbuff.cursize > 0);
767
768 //Q_assert (msgbuff.cursize < MAX_USABLEMSG);
769
770 if (out->cursize + msgbuff.cursize > out->maxsize)
771 {
772 Com_DPrintf ("MSG_EndWriting: overflow\n");
773 SZ_Clear (out);
774 out->overflowed = true;
775 }
776 else
777 {
778 SZ_Write (out, message_buff, msgbuff.cursize);
779 }
780
781 SZ_Clear (&msgbuff);
782 #ifdef _DEBUG
783 memset (message_buff, 0xcc, sizeof(message_buff));
784 #endif
785 }
786
MSG_EndWrite(messagelist_t * out)787 void MSG_EndWrite (messagelist_t *out)
788 {
789 Q_assert (msgbuff.cursize > 0);
790
791 //r1: use small local buffer if possible to avoid thousands of mallocs with tiny amounts
792 if (msgbuff.cursize > MSG_MAX_SIZE_BEFORE_MALLOC)
793 {
794 #ifndef NPROFILE
795 msg_malloc_hits++;
796 #endif
797 out->data = malloc (msgbuff.cursize);
798 }
799 else
800 {
801 #ifndef NPROFILE
802 msg_local_hits++;
803 #endif
804 out->data = out->localbuff;
805 }
806
807 #ifndef NPROFILE
808 if (msgbuff.cursize < sizeof(messageSizes) / sizeof(messageSizes[0]))
809 messageSizes[msgbuff.cursize]++;
810 #endif
811
812 memcpy (out->data, message_buff, msgbuff.cursize);
813 out->cursize = msgbuff.cursize;
814 }
815
MSG_WriteCoord(float f)816 void MSG_WriteCoord (float f)
817 {
818 MSG_WriteShort ((int)(f*8));
819 }
820
MSG_WritePos(vec3_t pos)821 void MSG_WritePos (vec3_t pos)
822 {
823 MSG_WriteShort ((int)(pos[0]*8));
824 MSG_WriteShort ((int)(pos[1]*8));
825 MSG_WriteShort ((int)(pos[2]*8));
826 }
827
MSG_WriteAngle(float f)828 void MSG_WriteAngle (float f)
829 {
830 MSG_WriteByte ((int)(f*256/360) & 255);
831 }
832
MSG_WriteAngle16(float f)833 void MSG_WriteAngle16 (float f)
834 {
835 MSG_WriteShort (ANGLE2SHORT(f));
836 }
837
838
MSG_WriteDeltaUsercmd(const usercmd_t * from,const usercmd_t * cmd,int protocol)839 void MSG_WriteDeltaUsercmd (const usercmd_t *from, const usercmd_t *cmd, int protocol)
840 {
841 int bits;
842 int buttons;
843
844 //
845 // send the movement message
846 //
847 bits = 0;
848 buttons = 0;
849
850 if (cmd->angles[0] != from->angles[0])
851 bits |= CM_ANGLE1;
852 if (cmd->angles[1] != from->angles[1])
853 bits |= CM_ANGLE2;
854
855 //FIXME: it's impossible for cl.viewangles roll to change,
856 //is this ever legitimately set?
857 if (cmd->angles[2] != from->angles[2])
858 bits |= CM_ANGLE3;
859
860 if (cmd->forwardmove != from->forwardmove)
861 bits |= CM_FORWARD;
862 if (cmd->sidemove != from->sidemove)
863 bits |= CM_SIDE;
864 if (cmd->upmove != from->upmove)
865 bits |= CM_UP;
866
867 if (cmd->buttons != from->buttons)
868 {
869 buttons = cmd->buttons;
870 bits |= CM_BUTTONS;
871 }
872
873 if (cmd->impulse != from->impulse)
874 bits |= CM_IMPULSE;
875
876 MSG_WriteByte (bits);
877
878 //waste not what precious bytes we have...
879 if (protocol >= MINOR_VERSION_R1Q2_UCMD_UPDATES)
880 {
881 if (bits & CM_BUTTONS)
882 {
883 if ((bits & CM_FORWARD) && (cmd->forwardmove % 5) == 0)
884 buttons |= BUTTON_UCMD_DBLFORWARD;
885 if ((bits & CM_SIDE) && (cmd->sidemove % 5) == 0)
886 buttons |= BUTTON_UCMD_DBLSIDE;
887 if ((bits & CM_UP) && (cmd->upmove % 5) == 0)
888 buttons |= BUTTON_UCMD_DBLUP;
889
890 if ((bits & CM_ANGLE1) && (cmd->angles[0] % 64) == 0 && (abs(cmd->angles[0] / 64)) < 128)
891 buttons |= BUTTON_UCMD_DBL_ANGLE1;
892 if ((bits & CM_ANGLE2) && (cmd->angles[1] % 256) == 0)
893 buttons |= BUTTON_UCMD_DBL_ANGLE2;
894
895 MSG_WriteByte (buttons);
896 }
897 }
898
899 if (bits & CM_ANGLE1)
900 {
901 if (buttons & BUTTON_UCMD_DBL_ANGLE1)
902 MSG_WriteChar (cmd->angles[0] / 64);
903 else
904 MSG_WriteShort (cmd->angles[0]);
905 }
906
907 if (bits & CM_ANGLE2)
908 {
909 if (buttons & BUTTON_UCMD_DBL_ANGLE2)
910 MSG_WriteChar (cmd->angles[1] / 256);
911 else
912 MSG_WriteShort (cmd->angles[1]);
913 }
914
915 if (bits & CM_ANGLE3)
916 MSG_WriteShort (cmd->angles[2]);
917
918 if (bits & CM_FORWARD)
919 {
920 if (buttons & BUTTON_UCMD_DBLFORWARD)
921 MSG_WriteChar (cmd->forwardmove / 5);
922 else
923 MSG_WriteShort (cmd->forwardmove);
924 }
925
926 if (bits & CM_SIDE)
927 {
928 if (buttons & BUTTON_UCMD_DBLSIDE)
929 MSG_WriteChar (cmd->sidemove / 5);
930 else
931 MSG_WriteShort (cmd->sidemove);
932 }
933
934 if (bits & CM_UP)
935 {
936 if (buttons & BUTTON_UCMD_DBLUP)
937 MSG_WriteChar (cmd->upmove / 5);
938 else
939 MSG_WriteShort (cmd->upmove);
940 }
941
942 if (protocol < MINOR_VERSION_R1Q2_UCMD_UPDATES)
943 {
944 if (bits & CM_BUTTONS)
945 MSG_WriteByte (buttons);
946 }
947
948 if (bits & CM_IMPULSE)
949 MSG_WriteByte (cmd->impulse);
950
951 MSG_WriteByte (cmd->msec);
952 MSG_WriteByte (cmd->lightlevel);
953 }
954
955
MSG_WriteDir(vec3_t dir)956 void MSG_WriteDir (vec3_t dir)
957 {
958 int i, best;
959 float d, bestd;
960
961 if (!dir)
962 {
963 MSG_WriteByte (0);
964 return;
965 }
966
967 bestd = 0;
968 best = 0;
969 for (i=0 ; i<NUMVERTEXNORMALS ; i++)
970 {
971 d = DotProduct (dir, bytedirs[i]);
972 if (d > bestd)
973 {
974 bestd = d;
975 best = i;
976 }
977 }
978 MSG_WriteByte (best);
979 }
980
981
MSG_ReadDir(sizebuf_t * sb,vec3_t dir)982 void MSG_ReadDir (sizebuf_t *sb, vec3_t dir)
983 {
984 int b;
985
986 b = MSG_ReadByte (sb);
987 if (b == -1 || b >= NUMVERTEXNORMALS)
988 Com_Error (ERR_DROP, "MSG_ReadDir: out of range (%d)", b);
989 VectorCopy (bytedirs[b], dir);
990 }
991
992
993 //============================================================
994
995 //
996 // reading functions
997 //
998
MSG_BeginReading(sizebuf_t * msg)999 void MSG_BeginReading (sizebuf_t *msg)
1000 {
1001 msg->readcount = 0;
1002 }
1003
1004 // returns -1 if no more characters are available
MSG_ReadChar(sizebuf_t * msg_read)1005 int MSG_ReadChar (sizebuf_t *msg_read)
1006 {
1007 int c;
1008
1009 if (msg_read->readcount+1 > msg_read->cursize)
1010 c = -1;
1011 else
1012 c = (signed char)msg_read->data[msg_read->readcount];
1013 msg_read->readcount++;
1014
1015 return c;
1016 }
1017
MSG_ReadByte(sizebuf_t * msg_read)1018 int MSG_ReadByte (sizebuf_t *msg_read)
1019 {
1020 int c;
1021
1022 if (msg_read->readcount+1 > msg_read->cursize)
1023 c = -1;
1024 else
1025 c = (unsigned char)msg_read->data[msg_read->readcount];
1026 msg_read->readcount++;
1027
1028 return c;
1029 }
1030
MSG_ReadShort(sizebuf_t * msg_read)1031 int MSG_ReadShort (sizebuf_t *msg_read)
1032 {
1033 int c;
1034
1035 if (msg_read->readcount+2 > msg_read->cursize)
1036 c = -1;
1037 else
1038 c = (int16)(msg_read->data[msg_read->readcount]
1039 + (msg_read->data[msg_read->readcount+1]<<8));
1040
1041 msg_read->readcount += 2;
1042
1043 return c;
1044 }
1045
MSG_ReadLong(sizebuf_t * msg_read)1046 int MSG_ReadLong (sizebuf_t *msg_read)
1047 {
1048 int c;
1049
1050 if (msg_read->readcount+4 > msg_read->cursize)
1051 c = -1;
1052 else
1053 c = msg_read->data[msg_read->readcount]
1054 + (msg_read->data[msg_read->readcount+1]<<8)
1055 + (msg_read->data[msg_read->readcount+2]<<16)
1056 + (msg_read->data[msg_read->readcount+3]<<24);
1057
1058 msg_read->readcount += 4;
1059
1060 return c;
1061 }
1062
MSG_ReadFloat(sizebuf_t * msg_read)1063 float MSG_ReadFloat (sizebuf_t *msg_read)
1064 {
1065 union
1066 {
1067 byte b[4];
1068 float f;
1069 int l;
1070 } dat;
1071
1072 if (msg_read->readcount+4 > msg_read->cursize)
1073 dat.f = -1;
1074 else
1075 {
1076 dat.b[0] = msg_read->data[msg_read->readcount];
1077 dat.b[1] = msg_read->data[msg_read->readcount+1];
1078 dat.b[2] = msg_read->data[msg_read->readcount+2];
1079 dat.b[3] = msg_read->data[msg_read->readcount+3];
1080 }
1081 msg_read->readcount += 4;
1082
1083 dat.l = LittleLong (dat.l);
1084
1085 return dat.f;
1086 }
1087
MSG_ReadString(sizebuf_t * msg_read)1088 char *MSG_ReadString (sizebuf_t *msg_read)
1089 {
1090 static char string[2048];
1091 int l,c;
1092
1093 l = 0;
1094 do
1095 {
1096 c = MSG_ReadByte (msg_read);
1097 if (c == -1 || c == 0)
1098 break;
1099 string[l] = c;
1100 l++;
1101 } while (l < sizeof(string)-1);
1102
1103 string[l] = 0;
1104
1105 return string;
1106 }
1107
MSG_ReadStringLine(sizebuf_t * msg_read)1108 char *MSG_ReadStringLine (sizebuf_t *msg_read)
1109 {
1110 static char string[2048];
1111 int l,c;
1112
1113 l = 0;
1114 do
1115 {
1116 c = MSG_ReadByte (msg_read);
1117 if (c == -1 || c == 0 || c == '\n')
1118 break;
1119 string[l] = c;
1120 l++;
1121 } while (l < sizeof(string)-1);
1122
1123 string[l] = 0;
1124 return string;
1125 }
1126
MSG_ReadCoord(sizebuf_t * msg_read)1127 float MSG_ReadCoord (sizebuf_t *msg_read)
1128 {
1129 return MSG_ReadShort(msg_read) * 0.125f;
1130 }
1131
MSG_ReadPos(sizebuf_t * msg_read,vec3_t pos)1132 void MSG_ReadPos (sizebuf_t *msg_read, vec3_t pos)
1133 {
1134 pos[0] = MSG_ReadShort(msg_read) * 0.125f;
1135 pos[1] = MSG_ReadShort(msg_read) * 0.125f;
1136 pos[2] = MSG_ReadShort(msg_read) * 0.125f;
1137 }
1138
MSG_ReadAngle(sizebuf_t * msg_read)1139 float MSG_ReadAngle (sizebuf_t *msg_read)
1140 {
1141 return MSG_ReadChar(msg_read) * 1.40625f;
1142 }
1143
MSG_ReadAngle16(sizebuf_t * msg_read)1144 float MSG_ReadAngle16 (sizebuf_t *msg_read)
1145 {
1146 return SHORT2ANGLE(MSG_ReadShort(msg_read));
1147 }
1148
1149 #ifndef NPROFILE
1150 unsigned long r1q2UserCmdOptimizedBytes = 0;
1151 #endif
1152
MSG_ReadDeltaUsercmd(sizebuf_t * msg_read,usercmd_t * from,usercmd_t * move,int protocol)1153 void MSG_ReadDeltaUsercmd (sizebuf_t *msg_read, usercmd_t *from, usercmd_t /*@out@*/*move, int protocol)
1154 {
1155 int buttons;
1156 int bits;
1157 unsigned msec;
1158
1159 memcpy (move, from, sizeof(*move));
1160
1161 bits = MSG_ReadByte (msg_read);
1162 buttons = 0;
1163
1164 if (protocol >= MINOR_VERSION_R1Q2_UCMD_UPDATES)
1165 {
1166 if (bits & CM_BUTTONS)
1167 {
1168 buttons = MSG_ReadByte (msg_read);
1169
1170 //only save real buttons, strip off the extra stolen bits
1171 move->buttons = buttons & (BUTTON_ATTACK|BUTTON_USE|BUTTON_ANY);
1172 }
1173 }
1174
1175 // read current angles
1176 if (bits & CM_ANGLE1)
1177 {
1178 if (buttons & BUTTON_UCMD_DBL_ANGLE1)
1179 {
1180 #ifndef NPROFILE
1181 r1q2UserCmdOptimizedBytes++;
1182 #endif
1183 move->angles[0] = MSG_ReadChar (msg_read) * 64;
1184 }
1185 else
1186 move->angles[0] = MSG_ReadShort (msg_read);
1187 }
1188
1189 if (bits & CM_ANGLE2)
1190 {
1191 if (buttons & BUTTON_UCMD_DBL_ANGLE2)
1192 {
1193 #ifndef NPROFILE
1194 r1q2UserCmdOptimizedBytes++;
1195 #endif
1196 move->angles[1] = MSG_ReadChar (msg_read) * 256;
1197 }
1198 else
1199 move->angles[1] = MSG_ReadShort (msg_read);
1200 }
1201
1202 if (bits & CM_ANGLE3)
1203 move->angles[2] = MSG_ReadShort (msg_read);
1204
1205 // read movement
1206 if (bits & CM_FORWARD)
1207 {
1208 if (buttons & BUTTON_UCMD_DBLFORWARD)
1209 {
1210 #ifndef NPROFILE
1211 r1q2UserCmdOptimizedBytes++;
1212 #endif
1213 move->forwardmove = MSG_ReadChar (msg_read) * 5;
1214 }
1215 else
1216 move->forwardmove = MSG_ReadShort (msg_read);
1217 }
1218
1219 if (bits & CM_SIDE)
1220 {
1221 if (buttons & BUTTON_UCMD_DBLSIDE)
1222 {
1223 #ifndef NPROFILE
1224 r1q2UserCmdOptimizedBytes++;
1225 #endif
1226 move->sidemove = MSG_ReadChar (msg_read) * 5;
1227 }
1228 else
1229 move->sidemove = MSG_ReadShort (msg_read);
1230 }
1231
1232 if (bits & CM_UP)
1233 {
1234 if (buttons & BUTTON_UCMD_DBLUP)
1235 {
1236 #ifndef NPROFILE
1237 r1q2UserCmdOptimizedBytes++;
1238 #endif
1239 move->upmove = MSG_ReadChar (msg_read) * 5;
1240 }
1241 else
1242 move->upmove = MSG_ReadShort (msg_read);
1243 }
1244
1245 // read buttons
1246 if (protocol < MINOR_VERSION_R1Q2_UCMD_UPDATES)
1247 {
1248 if (bits & CM_BUTTONS)
1249 move->buttons = MSG_ReadByte (msg_read);
1250 }
1251
1252 if (bits & CM_IMPULSE)
1253 move->impulse = MSG_ReadByte (msg_read);
1254
1255 // read time to run command
1256 msec = MSG_ReadByte (msg_read);
1257
1258 if (msec > 250)
1259 Com_Printf ("MSG_ReadDeltaUsercmd: funky msec (%d)!\n", LOG_GENERAL, msec);
1260
1261 move->msec = msec;
1262
1263 // read the light level
1264 move->lightlevel = MSG_ReadByte (msg_read);
1265 }
1266
1267
MSG_ReadData(sizebuf_t * msg_read,void * data,int len)1268 void MSG_ReadData (sizebuf_t *msg_read, void *data, int len)
1269 {
1270 int i;
1271
1272 for (i=0 ; i<len ; i++)
1273 ((byte *)data)[i] = MSG_ReadByte (msg_read);
1274 }
1275
1276
1277 //===========================================================================
1278
SZ_Init(sizebuf_t * buf,byte * data,int length)1279 void SZ_Init (sizebuf_t /*@out@*/*buf, byte /*@out@*/*data, int length)
1280 {
1281 Q_assert (length > 0);
1282
1283 memset (buf, 0, sizeof(*buf));
1284 buf->data = data;
1285 buf->maxsize = length;
1286 buf->buffsize = length; //should never change this
1287 }
1288
SZ_Clear(sizebuf_t * buf)1289 void SZ_Clear (sizebuf_t /*@out@*/*buf)
1290 {
1291 buf->cursize = 0;
1292 buf->overflowed = false;
1293 }
1294
SZ_GetSpace(sizebuf_t * buf,int length)1295 void *SZ_GetSpace (sizebuf_t /*@out@*/*buf, int length)
1296 {
1297 void *data;
1298
1299 Q_assert (length > 0);
1300
1301 if (buf->cursize + length > buf->maxsize)
1302 {
1303 if (!buf->data)
1304 Com_Error (ERR_FATAL, "SZ_GetSpace: attempted to write %d bytes to an uninitialized buffer!", length);
1305
1306 if (!buf->allowoverflow)
1307 {
1308 if (length > buf->maxsize)
1309 Com_Error (ERR_FATAL, "SZ_GetSpace: %i is > full buffer size %d (%d)", length, buf->maxsize, buf->buffsize);
1310
1311 Com_Error (ERR_FATAL, "SZ_GetSpace: overflow without allowoverflow set (%d+%d > %d)", buf->cursize, length, buf->maxsize);
1312 }
1313
1314 //r1: clear the buffer BEFORE the error!! (for console buffer)
1315 if (buf->cursize + length >= buf->buffsize)
1316 {
1317 SZ_Clear (buf);
1318 Com_DPrintf ("SZ_GetSpace: overflow\n");
1319 }
1320 else
1321 {
1322 Com_DPrintf ("SZ_GetSpace: overflowed maxsize\n");
1323 }
1324
1325 buf->overflowed = true;
1326 }
1327
1328 data = buf->data + buf->cursize;
1329 buf->cursize += length;
1330
1331 return data;
1332 }
1333
SZ_Write(sizebuf_t * buf,const void * data,int length)1334 void SZ_Write (sizebuf_t /*@out@*/*buf, const void *data, int length)
1335 {
1336 memcpy (SZ_GetSpace(buf,length),data,length);
1337 }
1338
SZ_Print(sizebuf_t * buf,const char * data)1339 void SZ_Print (sizebuf_t /*@out@*/*buf, const char *data)
1340 {
1341 int len;
1342
1343 len = (int)strlen(data)+1;
1344
1345 Q_assert (len > 1);
1346
1347 if (buf->cursize)
1348 {
1349 if (buf->data[buf->cursize-1])
1350 memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
1351 else
1352 memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
1353 }
1354 else
1355 memcpy ((byte *)SZ_GetSpace(buf, len),data,len);
1356 }
1357
1358
1359 //============================================================================
1360
1361
1362 /*
1363 ================
1364 COM_CheckParm
1365
1366 Returns the position (1 to argc-1) in the program's argument list
1367 where the given parameter apears, or 0 if not present
1368 ================
1369 */
1370 /*int COM_CheckParm (const char *parm)
1371 {
1372 int i;
1373
1374 for (i=1 ; i<com_argc ; i++)
1375 {
1376 if (!strcmp (parm,com_argv[i]))
1377 return i;
1378 }
1379
1380 return 0;
1381 }*/
1382
COM_Argc(void)1383 int COM_Argc (void)
1384 {
1385 return com_argc;
1386 }
1387
COM_Argv(int arg)1388 char *COM_Argv (int arg)
1389 {
1390 if (arg < 0 || arg >= com_argc || !com_argv[arg])
1391 return "";
1392 return com_argv[arg];
1393 }
1394
COM_ClearArgv(int arg)1395 void COM_ClearArgv (int arg)
1396 {
1397 if (arg < 0 || arg >= com_argc || !com_argv[arg])
1398 return;
1399 com_argv[arg] = "";
1400 }
1401
1402
1403 /*
1404 ================
1405 COM_InitArgv
1406 ================
1407 */
COM_InitArgv(int argc,char ** argv)1408 void COM_InitArgv (int argc, char **argv)
1409 {
1410 int i;
1411
1412 if (argc > MAX_NUM_ARGVS)
1413 Com_Error (ERR_FATAL, "argc > MAX_NUM_ARGVS");
1414 com_argc = argc;
1415 for (i=0 ; i<argc ; i++)
1416 {
1417 if (!argv[i] || strlen(argv[i]) >= MAX_TOKEN_CHARS )
1418 com_argv[i] = "";
1419 else
1420 com_argv[i] = argv[i];
1421 }
1422 }
1423
1424 /*
1425 ================
1426 COM_AddParm
1427
1428 Adds the given string at the end of the current argument list
1429 ================
1430 */
COM_AddParm(char * parm)1431 void COM_AddParm (char *parm)
1432 {
1433 if (com_argc == MAX_NUM_ARGVS)
1434 Com_Error (ERR_FATAL, "COM_AddParm: MAX_NUM_ARGVS");
1435 com_argv[com_argc++] = parm;
1436 }
1437
1438
1439
1440
1441 /// just for debugging
1442 /*int memsearch (byte *start, int count, int search)
1443 {
1444 int i;
1445
1446 for (i=0 ; i<count ; i++)
1447 if (start[i] == search)
1448 return i;
1449 return -1;
1450 }*/
1451
1452
CopyString(const char * in,int tag)1453 char *CopyString (const char *in, int tag)
1454 {
1455 char *out;
1456
1457 out = Z_TagMalloc ((int)strlen(in)+1, tag);
1458 strcpy (out, in);
1459 return out;
1460 }
1461
Info_Print(const char * s)1462 void Info_Print (const char *s)
1463 {
1464 char key[512];
1465 char value[512];
1466 char *o;
1467 int l;
1468
1469 if (*s == '\\')
1470 s++;
1471 while (*s)
1472 {
1473 o = key;
1474 while (*s && *s != '\\')
1475 *o++ = *s++;
1476
1477 l = (int)(o - key);
1478 if (l < 20)
1479 {
1480 memset (o, ' ', 20-l);
1481 key[20] = 0;
1482 }
1483 else
1484 *o = 0;
1485 Com_Printf ("%s", LOG_GENERAL, key);
1486
1487 if (!*s)
1488 {
1489 Com_Printf ("Info_Print: MISSING VALUE\n", LOG_GENERAL);
1490 return;
1491 }
1492
1493 o = value;
1494 s++;
1495 while (*s && *s != '\\')
1496 *o++ = *s++;
1497 *o = 0;
1498
1499 if (*s)
1500 s++;
1501 Com_Printf ("%s\n", LOG_GENERAL, value);
1502 }
1503 }
1504
1505 /*
1506 ==============================================================================
1507
1508 ZONE MEMORY ALLOCATION
1509
1510 just cleared malloc with counters now...
1511
1512 ==============================================================================
1513 */
1514
1515 #define Z_MAGIC 0x1d1d
1516 #define Z_MAGIC_DEBUG 0x2d2d
1517
1518 typedef struct zhead_s
1519 {
1520 struct zhead_s *prev, *next;
1521 int16 magic;
1522 int16 tag; // for group free
1523 int size;
1524 void *allocationLocation;
1525 } zhead_t;
1526
1527 typedef struct z_memloc_s
1528 {
1529 void *address;
1530 uint32 time;
1531 uint32 size;
1532 struct z_memloc_s *next;
1533 void *allocationLocation;
1534 } z_memloc_t;
1535
1536 static z_memloc_t z_game_locations;
1537
1538 static zhead_t z_chain = {0};
1539
1540 static long z_count = 0;
1541 static long z_bytes = 0;
1542
1543 static unsigned long z_allocs = 0;
1544 static unsigned long z_level_allocs = 0;
1545 static unsigned long z_game_allocs = 0;
1546
1547 qboolean free_from_game = false;
1548
1549 /*
1550 ========================
1551 Z_Free
1552 ========================
1553 */
Z_FreeRelease(const void * ptr)1554 void EXPORT Z_FreeRelease (const void *ptr)
1555 {
1556 zhead_t *z;
1557
1558 z = ((zhead_t *)ptr) - 1;
1559
1560 if (z->magic != Z_MAGIC && z->magic != Z_MAGIC_DEBUG)
1561 Com_Error (ERR_DIE, "Z_Free: bad magic");
1562
1563 z->prev->next = z->next;
1564 z->next->prev = z->prev;
1565
1566 z_count--;
1567 z_bytes -= z->size;
1568 free (z);
1569 }
1570
Z_FreeDebug(const void * ptr)1571 void EXPORT Z_FreeDebug (const void *ptr)
1572 {
1573 zhead_t *z;
1574
1575 if (!ptr)
1576 Com_Error (ERR_DIE, "Z_Free: null pointer given from %s", free_from_game ? "GAME" : "EXECUTABLE");
1577
1578 z = ((zhead_t *)ptr) - 1;
1579
1580 Z_Verify ("Z_FreeDebug: START FREE FROM %s OF %p (%d bytes tagged %d (%s))", free_from_game ? "GAME" : "EXECUTABLE", ptr, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG");
1581
1582 //magic test
1583 if (z->magic != Z_MAGIC && z->magic != Z_MAGIC_DEBUG)
1584 Com_Error (ERR_DIE, "Z_Free: bad magic freeing %p from %s", z, free_from_game ? "GAME" : "EXECUTABLE");
1585
1586 //size sanity test
1587 if (z->size <= 0 || z->size > 0x40000000)
1588 {
1589 if (z_allowcorruption->intvalue)
1590 Com_Printf ("Z_Free: crazy block size %d (maybe tag %d (%s)) from %s at %p, allocated at %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1591 else
1592 Com_Error (ERR_DIE, "Z_Free: crazy block size %d (maybe tag %d (%s)) from %s at %p allocated at %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1593 }
1594
1595 //we could segfault here if size is invalid :(
1596 if (z->magic == Z_MAGIC_DEBUG && (*(byte **)&z)[z->size-1] != 0xCC)
1597 {
1598 if (z_allowcorruption->intvalue)
1599 Com_Printf ("Z_Free: buffer overrun detected in block sized %d (tagged as %d (%s)) from %s at %p allocated at %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1600 else
1601 Com_Error (ERR_DIE, "Z_Free: buffer overrun detected in block sized %d (tagged as %d (%s)) from %s at %p allocated at %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE", z, z->allocationLocation);
1602 }
1603
1604 z->prev->next = z->next;
1605 z->next->prev = z->prev;
1606
1607 if (z->next->magic != Z_MAGIC && z->next->magic != Z_MAGIC_DEBUG)
1608 Com_Error (ERR_DIE, "Z_Free: memory corruption detected after free of block at %p from %s", z, free_from_game ? "GAME" : "EXECUTABLE");
1609
1610 z_count--;
1611 z_bytes -= z->size;
1612
1613 if (z_count < 0 || z_bytes < 0)
1614 Com_Error (ERR_DIE, "Z_Free: counters are screwed after free of %d bytes at %p tagged %d (%s) from %s", z->size, z, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", free_from_game ? "GAME" : "EXECUTABLE");
1615
1616 free (z);
1617
1618 Z_Verify ("Z_FreeDebug: END FREE OF %p FROM %s", ptr, free_from_game ? "GAME" : "EXECUTABLE");
1619 }
1620
1621 /*
1622 ========================
1623 Z_Stats_f
1624 ========================
1625 */
1626
1627 #define TAG_GAME 765 // clear when unloading the dll
1628 #define TAG_LEVEL 766 // clear when loading a new level
1629
Z_Stats_f(void)1630 void Z_Stats_f (void)
1631 {
1632 int i, total, num, bigtotal, bignum, level_count, level_size, game_count, game_size;
1633 zhead_t *z, *next;
1634
1635 bigtotal = bignum = level_size = level_count = game_size = game_count = 0;
1636
1637 for (i = 0; i < TAGMALLOC_MAX_TAGS; i++) {
1638 total = num = 0;
1639 for (z=z_chain.next ; z != &z_chain ; z=next)
1640 {
1641 next = z->next;
1642 if (z->tag == i) {
1643 total += z->size;
1644 num++;
1645 }
1646
1647 if (i == (TAGMALLOC_MAX_TAGS - 1)) {
1648 if (z->tag == TAG_LEVEL) {
1649 level_size += z->size;
1650 level_count ++;
1651 } else if (z->tag == TAG_GAME) {
1652 game_size += z->size;
1653 game_count++;
1654 }
1655 }
1656 }
1657 bigtotal += total;
1658 bignum += num;
1659 Com_Printf ("%14.14s: %8i bytes %5i blocks %8i allocs\n", LOG_GENERAL, tagmalloc_tags[i].name, total, num, tagmalloc_tags[i].allocs);
1660 }
1661
1662 bigtotal += game_size;
1663 bigtotal += level_size;
1664
1665 bignum += game_count;
1666 bignum += level_count;
1667
1668 Com_Printf ("%14.14s: %8i bytes %5i blocks %8lu allocs\n", LOG_GENERAL, "DLL_LEVEL", level_size, level_count, z_level_allocs);
1669 Com_Printf ("%14.14s: %8i bytes %5i blocks %8lu allocs\n\n", LOG_GENERAL, "DLL_GAME", game_size, game_count, z_game_allocs);
1670
1671 Com_Printf ("%lu unaccounted allocations\n", LOG_GENERAL, z_allocs);
1672
1673 Com_Printf (" CALCED_TOTAL: %i bytes in %i blocks\n", LOG_GENERAL, bigtotal, bignum);
1674 Com_Printf (" RUNNING_TOTAL: %li bytes in %li blocks\n", LOG_GENERAL, z_bytes, z_count);
1675 }
1676
1677 /*
1678 ========================
1679 Z_FreeTags
1680 ========================
1681 */
Z_FreeTags(int tag)1682 void Z_FreeTags (int tag)
1683 {
1684 zhead_t *z, *next;
1685
1686 Z_Verify ("Z_FreeTags: START");
1687
1688 for (z=z_chain.next ; z != &z_chain ; z=next)
1689 {
1690 next = z->next;
1691 if (z->tag == tag)
1692 Z_Free ((void *)(z+1));
1693 }
1694
1695 Z_Verify ("Z_FreeTags: END");
1696 }
1697
1698 /*
1699 ========================
1700 Z_FreeTags
1701 ========================
1702 */
Z_Verify(const char * format,...)1703 void Z_Verify (const char *format, ...)
1704 {
1705 va_list argptr;
1706 int i;
1707 zhead_t *z, *next;
1708 char string[1024];
1709
1710 va_start (argptr, format);
1711 vsnprintf (string, sizeof(string)-1, format, argptr);
1712 va_end (argptr);
1713
1714 string[sizeof(string)-1] = 0;
1715
1716 i = 0;
1717
1718 for (z=z_chain.next ; z != &z_chain ; z=next)
1719 {
1720 next = z->next;
1721 if (z->magic != Z_MAGIC)
1722 {
1723 if (z->magic == Z_MAGIC_DEBUG)
1724 {
1725 //size sanity test
1726 if (z->size <= 0 || z->size > 0x40000000)
1727 {
1728 if (z_allowcorruption->intvalue)
1729 Com_Printf ("Z_Verify: crazy block size %d (maybe tag %d (%s)) during '%s' at %p, allocated from %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1730 else
1731 Com_Error (ERR_DIE, "Z_Verify: crazy block size %d (maybe tag %d (%s)) during '%s' at %p, allocated from %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1732 }
1733
1734 //we could segfault here if size is invalid :(
1735 if ((*(byte **)&z)[z->size-1] != 0xCC)
1736 {
1737 if (z_allowcorruption->intvalue)
1738 Com_Printf ("Z_Verify: buffer overrun detected in block sized %d (tagged as %d (%s)) during '%s' at %p, allocated from %p", LOG_ERROR, z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1739 else
1740 Com_Error (ERR_DIE, "Z_Verify: buffer overrun detected in block sized %d (tagged as %d (%s)) during '%s' at %p, allocated from %p", z->size, z->tag, z->tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[z->tag].name : "UNKNOWN TAG", string, z, z->allocationLocation);
1741 }
1742 }
1743 else
1744 {
1745 if (z_allowcorruption->intvalue)
1746 Com_Printf ("Z_Verify: memory corruption detected during '%s' in block %p allocated from %p", LOG_ERROR, string, (void *)(z+1), z->allocationLocation);
1747 else
1748 Com_Error (ERR_DIE, "Z_Verify: memory corruption detected during '%s' in block %p allocated from %p", string, (void *)(z+1), z->allocationLocation);
1749 }
1750 }
1751
1752 if (i++ > z_count * 2)
1753 Com_Error (ERR_DIE, "Z_Verify: memory chain state corrupted during '%s'", string);
1754 }
1755 }
1756
Z_TagMallocDebug(int size,int tag)1757 RESTRICT void * EXPORT Z_TagMallocDebug (int size, int tag)
1758 {
1759 zhead_t *z;
1760
1761 Z_Verify ("Z_TagMallocDebug: START ALLOCATION OF %d BYTES FOR TAG %d (%s)", size, tag, tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[tag].name : "UNKNOWN TAG");
1762
1763 if (size <= 0 && tag < TAGMALLOC_MAX_TAGS)
1764 Com_Error (ERR_DIE, "Z_TagMalloc: trying to allocate %d bytes!", size);
1765
1766 size = size + sizeof(zhead_t);
1767
1768 if (size > 0x40000000)
1769 Com_Error (ERR_DIE, "Z_TagMalloc: trying to allocate %d bytes!", size);
1770
1771 size++;
1772
1773 z = malloc(size);
1774
1775 if (!z)
1776 Com_Error (ERR_DIE, "Z_TagMalloc: Out of memory. Couldn't allocate %i bytes for %s (already %li bytes in %li blocks)", size, tagmalloc_tags[tag].name, z_bytes, z_count);
1777
1778 //memset (z, 0xCC, size);
1779
1780 (*(byte **)&z)[size-1] = 0xCC;
1781
1782 z_count++;
1783
1784 if (tag < TAGMALLOC_MAX_TAGS)
1785 tagmalloc_tags[tag].allocs++;
1786
1787 z_bytes += size;
1788
1789 z->magic = Z_MAGIC_DEBUG;
1790 z->tag = tag;
1791 z->size = size;
1792
1793 #if defined _WIN32
1794 z->allocationLocation = _ReturnAddress ();
1795 #elif defined LINUX
1796 z->allocationLocation = __builtin_return_address (0);
1797 #else
1798 //FIXME: other OSes/CCs
1799 z->allocationLocation = 0;
1800 #endif
1801
1802 z->next = z_chain.next;
1803 z->prev = &z_chain;
1804 z_chain.next->prev = z;
1805 z_chain.next = z;
1806
1807 Z_Verify ("Z_TagMallocDebug: END ALLOCATION OF %d BYTES FOR TAG %d (%s)", size, tag, tag < TAGMALLOC_MAX_TAGS ? tagmalloc_tags[tag].name : "UNKNOWN TAG");
1808
1809 return (void *)(z+1);
1810 }
1811
1812 /*
1813 ========================
1814 Z_TagMalloc
1815 ========================
1816 */
Z_TagMallocRelease(int size,int tag)1817 RESTRICT void * EXPORT Z_TagMallocRelease (int size, int tag)
1818 {
1819 zhead_t *z;
1820
1821 //malloc can crash if negative size is passed, woops.
1822 if (size < 0)
1823 Com_Error (ERR_DIE, "Z_TagMalloc: Illegal allocation size of %d bytes from %p for tag %d", size,
1824 #if defined _WIN32
1825 _ReturnAddress (),
1826 #elif defined LINUX
1827 __builtin_return_address (0),
1828 #else
1829 NULL,
1830 #endif
1831 tag);
1832
1833 size = size + sizeof(zhead_t);
1834 z = malloc(size);
1835
1836 if (!z)
1837 Com_Error (ERR_DIE, "Z_TagMalloc: Out of memory. Couldn't allocate %i bytes for tag %d from %p (already %li bytes in %li blocks)", size, tag,
1838 #if defined _WIN32
1839 _ReturnAddress (),
1840 #elif defined LINUX
1841 __builtin_return_address (0),
1842 #else
1843 NULL,
1844 #endif
1845 z_bytes, z_count);
1846
1847 z_count++;
1848
1849 if ((uint32)tag < TAGMALLOC_MAX_TAGS)
1850 tagmalloc_tags[tag].allocs++;
1851
1852 z_bytes += size;
1853
1854 #if defined _WIN32
1855 z->allocationLocation = _ReturnAddress ();
1856 #elif defined LINUX
1857 z->allocationLocation = __builtin_return_address (0);
1858 #else
1859 //FIXME: other OSes/CCs
1860 z->allocationLocation = 0;
1861 #endif
1862
1863 z->magic = Z_MAGIC;
1864 z->tag = tag;
1865 z->size = size;
1866
1867 z->next = z_chain.next;
1868 z->prev = &z_chain;
1869 z_chain.next->prev = z;
1870 z_chain.next = z;
1871
1872 return (void *)(z+1);
1873 }
1874
Z_TagMallocGame(int size,int tag)1875 RESTRICT void * EXPORT Z_TagMallocGame (int size, int tag)
1876 {
1877 z_memloc_t *loc, *last, *newentry;
1878 byte *b;
1879
1880 void *retAddr;
1881
1882 #if defined _WIN32
1883 retAddr = _ReturnAddress ();
1884 #elif defined LINUX
1885 retAddr = __builtin_return_address (0);
1886 #else
1887 //FIXME: other OSes/CCs
1888 retAddr = 0;
1889 #endif
1890
1891 //aieeeee.
1892 if (z_buggygame->intvalue)
1893 size *= z_buggygame->intvalue;
1894
1895 if (!size)
1896 {
1897 if (z_buggygame->intvalue)
1898 {
1899 Com_Printf ("ERROR: Game DLL tried to allocate 0 bytes at %p. Giving it 1 byte of 0x00\n", LOG_ERROR|LOG_SERVER|LOG_GAME, retAddr);
1900 size = 1;
1901 }
1902 else
1903 {
1904 Com_Error (ERR_DIE, "Game DLL tried to allocate 0 bytes from code at %p!", retAddr);
1905 }
1906 }
1907
1908 b = Z_TagMalloc (size+4, tag);
1909
1910 memset (b, 0, size);
1911 *(int *)(b + size) = 0xFDFEFDFE;
1912
1913 if (tag == TAG_LEVEL)
1914 z_level_allocs++;
1915 else if (tag == TAG_GAME)
1916 z_game_allocs++;
1917
1918 loc = &z_game_locations;
1919 last = loc->next;
1920 newentry = malloc (sizeof(*loc));
1921 if (!newentry)
1922 Com_Error (ERR_DIE, "Z_TagMallocGame: Out of memory.");
1923
1924 newentry->address = b;
1925 newentry->size = size;
1926 newentry->next = last;
1927 newentry->time = curtime;
1928 newentry->allocationLocation = retAddr;
1929 loc->next = newentry;
1930
1931 return (void *)b;
1932 }
1933
Z_FreeGame(void * buf)1934 void EXPORT Z_FreeGame (void *buf)
1935 {
1936 z_memloc_t *loc, *last;
1937
1938 void *retAddr;
1939
1940 #if defined _WIN32
1941 retAddr = _ReturnAddress ();
1942 #elif defined LINUX
1943 retAddr = __builtin_return_address (0);
1944 #else
1945 //FIXME: other OSes/CCs
1946 retAddr = 0;
1947 #endif
1948
1949 loc = last = &z_game_locations;
1950
1951 while (loc->next)
1952 {
1953 loc = loc->next;
1954 if (buf == loc->address)
1955 {
1956 if (*(int *)((byte *)buf + loc->size) != 0xFDFEFDFE)
1957 {
1958 Com_Printf ("Memory corruption detected within the Game DLL. Please contact the mod author and inform them that they are not managing dynamically allocated memory correctly.\n", LOG_GENERAL);
1959 Com_Error (ERR_DIE, "Z_FreeGame: Game DLL corrupted a memory block of size %d at %p (allocated %u ms ago from code at %p), detected during free at %p", loc->size, loc->address, curtime - loc->time, loc->allocationLocation, retAddr);
1960 }
1961 free_from_game = true;
1962 Z_Free (buf);
1963 free_from_game = false;
1964
1965 last->next = loc->next;
1966 free (loc);
1967 return;
1968 }
1969 last = loc;
1970 }
1971
1972 if (z_buggygame->intvalue)
1973 {
1974 Com_Printf ("ERROR: Game DLL tried to free non-existent/freed memory at %p from code at %p, ignored.", LOG_ERROR|LOG_SERVER|LOG_GAME, buf, retAddr);
1975 }
1976 else
1977 {
1978 Com_Printf ("Memory management problem detected within the Game DLL. Please contact the mod author and inform them that they are not managing dynamically allocated memory correctly.\n", LOG_GENERAL);
1979 Com_Error (ERR_DIE, "Z_FreeGame: Game DLL tried to free non-existent/freed memory at %p from code at %p", buf, retAddr);
1980 }
1981 }
1982
Z_FreeTagsGame(int tag)1983 void EXPORT Z_FreeTagsGame (int tag)
1984 {
1985 zhead_t *z, *next;
1986
1987 z_memloc_t *loc, *last;
1988
1989 loc = last = &z_game_locations;
1990
1991 while (loc->next)
1992 {
1993 loc = loc->next;
1994
1995 if (*(int *)((byte *)loc->address + loc->size) != 0xFDFEFDFE)
1996 {
1997 Com_Printf ("Memory corruption detected within the Game DLL. Please contact the mod author and inform them that they are not managing dynamically allocated memory correctly.\n", LOG_GENERAL);
1998 Com_Error (ERR_DIE, "Z_FreeTagsGame: Game DLL corrupted a memory block of size %d at %p (allocated %u ms ago from code at %p)", loc->size, loc->address, curtime - loc->time, loc->allocationLocation);
1999 }
2000 }
2001
2002 for (z=z_chain.next ; z != &z_chain ; z=next)
2003 {
2004 next = z->next;
2005 if (z->tag == tag)
2006 Z_FreeGame ((void *)(z+1));
2007 }
2008
2009 Z_Verify (va("Z_FreeTags %d (GAME): END", tag));
2010 }
2011
2012
2013 /*
2014 ========================
2015 Z_Malloc
2016 ========================
2017 */
2018
2019 /*void *Z_Malloc (int size)
2020 {
2021 return Z_TagMalloc (size, 0);
2022 }*/
2023
2024
2025 //============================================================================
2026
2027 static byte chktbl[1024] = {
2028 0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda,
2029 0x88, 0x54, 0x15, 0x2b, 0xc6, 0x6c, 0x89, 0xc5, 0x9d, 0x48, 0xee, 0xe6, 0x8a, 0xb5, 0xf4,
2030 0xcb, 0xfb, 0xf1, 0x0c, 0x2e, 0xa0, 0xd7, 0xc9, 0x1f, 0xd6, 0x06, 0x9a, 0x09, 0x41, 0x54,
2031 0x67, 0x46, 0xc7, 0x74, 0xe3, 0xc8, 0xb6, 0x5d, 0xa6, 0x36, 0xc4, 0xab, 0x2c, 0x7e, 0x85,
2032 0xa8, 0xa4, 0xa6, 0x4d, 0x96, 0x19, 0x19, 0x9a, 0xcc, 0xd8, 0xac, 0x39, 0x5e, 0x3c, 0xf2,
2033 0xf5, 0x5a, 0x72, 0xe5, 0xa9, 0xd1, 0xb3, 0x23, 0x82, 0x6f, 0x29, 0xcb, 0xd1, 0xcc, 0x71,
2034 0xfb, 0xea, 0x92, 0xeb, 0x1c, 0xca, 0x4c, 0x70, 0xfe, 0x4d, 0xc9, 0x67, 0x43, 0x47, 0x94,
2035 0xb9, 0x47, 0xbc, 0x3f, 0x01, 0xab, 0x7b, 0xa6, 0xe2, 0x76, 0xef, 0x5a, 0x7a, 0x29, 0x0b,
2036 0x51, 0x54, 0x67, 0xd8, 0x1c, 0x14, 0x3e, 0x29, 0xec, 0xe9, 0x2d, 0x48, 0x67, 0xff, 0xed,
2037 0x54, 0x4f, 0x48, 0xc0, 0xaa, 0x61, 0xf7, 0x78, 0x12, 0x03, 0x7a, 0x9e, 0x8b, 0xcf, 0x83,
2038 0x7b, 0xae, 0xca, 0x7b, 0xd9, 0xe9, 0x53, 0x2a, 0xeb, 0xd2, 0xd8, 0xcd, 0xa3, 0x10, 0x25,
2039 0x78, 0x5a, 0xb5, 0x23, 0x06, 0x93, 0xb7, 0x84, 0xd2, 0xbd, 0x96, 0x75, 0xa5, 0x5e, 0xcf,
2040 0x4e, 0xe9, 0x50, 0xa1, 0xe6, 0x9d, 0xb1, 0xe3, 0x85, 0x66, 0x28, 0x4e, 0x43, 0xdc, 0x6e,
2041 0xbb, 0x33, 0x9e, 0xf3, 0x0d, 0x00, 0xc1, 0xcf, 0x67, 0x34, 0x06, 0x7c, 0x71, 0xe3, 0x63,
2042 0xb7, 0xb7, 0xdf, 0x92, 0xc4, 0xc2, 0x25, 0x5c, 0xff, 0xc3, 0x6e, 0xfc, 0xaa, 0x1e, 0x2a,
2043 0x48, 0x11, 0x1c, 0x36, 0x68, 0x78, 0x86, 0x79, 0x30, 0xc3, 0xd6, 0xde, 0xbc, 0x3a, 0x2a,
2044 0x6d, 0x1e, 0x46, 0xdd, 0xe0, 0x80, 0x1e, 0x44, 0x3b, 0x6f, 0xaf, 0x31, 0xda, 0xa2, 0xbd,
2045 0x77, 0x06, 0x56, 0xc0, 0xb7, 0x92, 0x4b, 0x37, 0xc0, 0xfc, 0xc2, 0xd5, 0xfb, 0xa8, 0xda,
2046 0xf5, 0x57, 0xa8, 0x18, 0xc0, 0xdf, 0xe7, 0xaa, 0x2a, 0xe0, 0x7c, 0x6f, 0x77, 0xb1, 0x26,
2047 0xba, 0xf9, 0x2e, 0x1d, 0x16, 0xcb, 0xb8, 0xa2, 0x44, 0xd5, 0x2f, 0x1a, 0x79, 0x74, 0x87,
2048 0x4b, 0x00, 0xc9, 0x4a, 0x3a, 0x65, 0x8f, 0xe6, 0x5d, 0xe5, 0x0a, 0x77, 0xd8, 0x1a, 0x14,
2049 0x41, 0x75, 0xb1, 0xe2, 0x50, 0x2c, 0x93, 0x38, 0x2b, 0x6d, 0xf3, 0xf6, 0xdb, 0x1f, 0xcd,
2050 0xff, 0x14, 0x70, 0xe7, 0x16, 0xe8, 0x3d, 0xf0, 0xe3, 0xbc, 0x5e, 0xb6, 0x3f, 0xcc, 0x81,
2051 0x24, 0x67, 0xf3, 0x97, 0x3b, 0xfe, 0x3a, 0x96, 0x85, 0xdf, 0xe4, 0x6e, 0x3c, 0x85, 0x05,
2052 0x0e, 0xa3, 0x2b, 0x07, 0xc8, 0xbf, 0xe5, 0x13, 0x82, 0x62, 0x08, 0x61, 0x69, 0x4b, 0x47,
2053 0x62, 0x73, 0x44, 0x64, 0x8e, 0xe2, 0x91, 0xa6, 0x9a, 0xb7, 0xe9, 0x04, 0xb6, 0x54, 0x0c,
2054 0xc5, 0xa9, 0x47, 0xa6, 0xc9, 0x08, 0xfe, 0x4e, 0xa6, 0xcc, 0x8a, 0x5b, 0x90, 0x6f, 0x2b,
2055 0x3f, 0xb6, 0x0a, 0x96, 0xc0, 0x78, 0x58, 0x3c, 0x76, 0x6d, 0x94, 0x1a, 0xe4, 0x4e, 0xb8,
2056 0x38, 0xbb, 0xf5, 0xeb, 0x29, 0xd8, 0xb0, 0xf3, 0x15, 0x1e, 0x99, 0x96, 0x3c, 0x5d, 0x63,
2057 0xd5, 0xb1, 0xad, 0x52, 0xb8, 0x55, 0x70, 0x75, 0x3e, 0x1a, 0xd5, 0xda, 0xf6, 0x7a, 0x48,
2058 0x7d, 0x44, 0x41, 0xf9, 0x11, 0xce, 0xd7, 0xca, 0xa5, 0x3d, 0x7a, 0x79, 0x7e, 0x7d, 0x25,
2059 0x1b, 0x77, 0xbc, 0xf7, 0xc7, 0x0f, 0x84, 0x95, 0x10, 0x92, 0x67, 0x15, 0x11, 0x5a, 0x5e,
2060 0x41, 0x66, 0x0f, 0x38, 0x03, 0xb2, 0xf1, 0x5d, 0xf8, 0xab, 0xc0, 0x02, 0x76, 0x84, 0x28,
2061 0xf4, 0x9d, 0x56, 0x46, 0x60, 0x20, 0xdb, 0x68, 0xa7, 0xbb, 0xee, 0xac, 0x15, 0x01, 0x2f,
2062 0x20, 0x09, 0xdb, 0xc0, 0x16, 0xa1, 0x89, 0xf9, 0x94, 0x59, 0x00, 0xc1, 0x76, 0xbf, 0xc1,
2063 0x4d, 0x5d, 0x2d, 0xa9, 0x85, 0x2c, 0xd6, 0xd3, 0x14, 0xcc, 0x02, 0xc3, 0xc2, 0xfa, 0x6b,
2064 0xb7, 0xa6, 0xef, 0xdd, 0x12, 0x26, 0xa4, 0x63, 0xe3, 0x62, 0xbd, 0x56, 0x8a, 0x52, 0x2b,
2065 0xb9, 0xdf, 0x09, 0xbc, 0x0e, 0x97, 0xa9, 0xb0, 0x82, 0x46, 0x08, 0xd5, 0x1a, 0x8e, 0x1b,
2066 0xa7, 0x90, 0x98, 0xb9, 0xbb, 0x3c, 0x17, 0x9a, 0xf2, 0x82, 0xba, 0x64, 0x0a, 0x7f, 0xca,
2067 0x5a, 0x8c, 0x7c, 0xd3, 0x79, 0x09, 0x5b, 0x26, 0xbb, 0xbd, 0x25, 0xdf, 0x3d, 0x6f, 0x9a,
2068 0x8f, 0xee, 0x21, 0x66, 0xb0, 0x8d, 0x84, 0x4c, 0x91, 0x45, 0xd4, 0x77, 0x4f, 0xb3, 0x8c,
2069 0xbc, 0xa8, 0x99, 0xaa, 0x19, 0x53, 0x7c, 0x02, 0x87, 0xbb, 0x0b, 0x7c, 0x1a, 0x2d, 0xdf,
2070 0x48, 0x44, 0x06, 0xd6, 0x7d, 0x0c, 0x2d, 0x35, 0x76, 0xae, 0xc4, 0x5f, 0x71, 0x85, 0x97,
2071 0xc4, 0x3d, 0xef, 0x52, 0xbe, 0x00, 0xe4, 0xcd, 0x49, 0xd1, 0xd1, 0x1c, 0x3c, 0xd0, 0x1c,
2072 0x42, 0xaf, 0xd4, 0xbd, 0x58, 0x34, 0x07, 0x32, 0xee, 0xb9, 0xb5, 0xea, 0xff, 0xd7, 0x8c,
2073 0x0d, 0x2e, 0x2f, 0xaf, 0x87, 0xbb, 0xe6, 0x52, 0x71, 0x22, 0xf5, 0x25, 0x17, 0xa1, 0x82,
2074 0x04, 0xc2, 0x4a, 0xbd, 0x57, 0xc6, 0xab, 0xc8, 0x35, 0x0c, 0x3c, 0xd9, 0xc2, 0x43, 0xdb,
2075 0x27, 0x92, 0xcf, 0xb8, 0x25, 0x60, 0xfa, 0x21, 0x3b, 0x04, 0x52, 0xc8, 0x96, 0xba, 0x74,
2076 0xe3, 0x67, 0x3e, 0x8e, 0x8d, 0x61, 0x90, 0x92, 0x59, 0xb6, 0x1a, 0x1c, 0x5e, 0x21, 0xc1,
2077 0x65, 0xe5, 0xa6, 0x34, 0x05, 0x6f, 0xc5, 0x60, 0xb1, 0x83, 0xc1, 0xd5, 0xd5, 0xed, 0xd9,
2078 0xc7, 0x11, 0x7b, 0x49, 0x7a, 0xf9, 0xf9, 0x84, 0x47, 0x9b, 0xe2, 0xa5, 0x82, 0xe0, 0xc2,
2079 0x88, 0xd0, 0xb2, 0x58, 0x88, 0x7f, 0x45, 0x09, 0x67, 0x74, 0x61, 0xbf, 0xe6, 0x40, 0xe2,
2080 0x9d, 0xc2, 0x47, 0x05, 0x89, 0xed, 0xcb, 0xbb, 0xb7, 0x27, 0xe7, 0xdc, 0x7a, 0xfd, 0xbf,
2081 0xa8, 0xd0, 0xaa, 0x10, 0x39, 0x3c, 0x20, 0xf0, 0xd3, 0x6e, 0xb1, 0x72, 0xf8, 0xe6, 0x0f,
2082 0xef, 0x37, 0xe5, 0x09, 0x33, 0x5a, 0x83, 0x43, 0x80, 0x4f, 0x65, 0x2f, 0x7c, 0x8c, 0x6a,
2083 0xa0, 0x82, 0x0c, 0xd4, 0xd4, 0xfa, 0x81, 0x60, 0x3d, 0xdf, 0x06, 0xf1, 0x5f, 0x08, 0x0d,
2084 0x6d, 0x43, 0xf2, 0xe3, 0x11, 0x7d, 0x80, 0x32, 0xc5, 0xfb, 0xc5, 0xd9, 0x27, 0xec, 0xc6,
2085 0x4e, 0x65, 0x27, 0x76, 0x87, 0xa6, 0xee, 0xee, 0xd7, 0x8b, 0xd1, 0xa0, 0x5c, 0xb0, 0x42,
2086 0x13, 0x0e, 0x95, 0x4a, 0xf2, 0x06, 0xc6, 0x43, 0x33, 0xf4, 0xc7, 0xf8, 0xe7, 0x1f, 0xdd,
2087 0xe4, 0x46, 0x4a, 0x70, 0x39, 0x6c, 0xd0, 0xed, 0xca, 0xbe, 0x60, 0x3b, 0xd1, 0x7b, 0x57,
2088 0x48, 0xe5, 0x3a, 0x79, 0xc1, 0x69, 0x33, 0x53, 0x1b, 0x80, 0xb8, 0x91, 0x7d, 0xb4, 0xf6,
2089 0x17, 0x1a, 0x1d, 0x5a, 0x32, 0xd6, 0xcc, 0x71, 0x29, 0x3f, 0x28, 0xbb, 0xf3, 0x5e, 0x71,
2090 0xb8, 0x43, 0xaf, 0xf8, 0xb9, 0x64, 0xef, 0xc4, 0xa5, 0x6c, 0x08, 0x53, 0xc7, 0x00, 0x10,
2091 0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32,
2092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2096 0x00, 0x00, 0x00, 0x00
2097 };
2098
2099 /*
2100 ====================
2101 COM_BlockSequenceCRCByte
2102
2103 For proxy protecting
2104 ====================
2105 */
COM_BlockSequenceCRCByte(byte * base,int length,int sequence)2106 byte COM_BlockSequenceCRCByte (byte *base, int length, int sequence)
2107 {
2108 int n;
2109 int x;
2110 byte *p;
2111 byte chkb[60 + 4];
2112 uint16 crc;
2113 byte r;
2114
2115
2116 if (sequence < 0)
2117 Sys_Error("sequence < 0, this shouldn't happen\n");
2118
2119 p = chktbl + (sequence % (sizeof(chktbl) - 4));
2120
2121 if (length > 60)
2122 length = 60;
2123 memcpy (chkb, base, length);
2124
2125 chkb[length] = p[0];
2126 chkb[length+1] = p[1];
2127 chkb[length+2] = p[2];
2128 chkb[length+3] = p[3];
2129
2130 length += 4;
2131
2132 crc = CRC_Block(chkb, length);
2133
2134 for (x=0, n=0; n<length; n++)
2135 x += chkb[n];
2136
2137 r = (crc ^ x) & 0xff;
2138
2139 return r;
2140 }
2141
2142 #ifdef USE_OPENSSL
Com_BlockChecksum(void * buffer,int length)2143 uint32 Com_BlockChecksum (void *buffer, int length)
2144 {
2145 int digest[4];
2146 uint32 val;
2147 MD4_CTX ctx;
2148
2149 MD4_Init (&ctx);
2150 MD4_Update (&ctx, (unsigned char *)buffer, length);
2151 MD4_Final ( (unsigned char *)digest, &ctx);
2152
2153 val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
2154
2155 return val;
2156 }
2157 #endif
2158
2159 //========================================================
2160
2161 /*float frand(void)
2162 {
2163 return (randomMT()&32767)* (1.0/32767);
2164 }
2165
2166 float crand(void)
2167 {
2168 return (randomMT()&32767)* (2.0/32767) - 1;
2169 }*/
2170
2171 void Key_Init (void);
2172 void SCR_EndLoadingPlaque (void);
2173
2174 /*
2175 =============
2176 Com_Error_f
2177
2178 Just throw a fatal error to
2179 test error shutdown procedures
2180 =============
2181 */
Com_Error_f(void)2182 void Com_Error_f (void)
2183 {
2184 Com_Error (ERR_FATAL, "%s", Cmd_Argv(1));
2185 }
2186
2187
2188 /*
2189 =================
2190 Qcommon_Init
2191 =================
2192 */
2193
Q_NullFunc(void)2194 void Q_NullFunc(void)
2195 {
2196 }
2197
Msg_Stats_f(void)2198 void Msg_Stats_f (void)
2199 {
2200 #ifndef NPROFILE
2201 int total;
2202 int i, j;
2203 int num;
2204 int sum;
2205
2206 total = msg_malloc_hits + msg_local_hits;
2207
2208 Com_Printf ("malloc: %d (%.2f%%), local: %d (%.2f%%)\n", LOG_GENERAL,
2209 msg_malloc_hits, ((float)msg_malloc_hits / (float)total) * 100.0f,
2210 msg_local_hits, ((float)msg_local_hits / (float)total) * 100.0f);
2211
2212 Com_Printf ("byte breakdown:\n", LOG_GENERAL);
2213
2214 total = 0;
2215 num = 0;
2216
2217 for (i = 0; i < sizeof(messageSizes) / sizeof(messageSizes[0]); i += 10)
2218 {
2219 sum = 0;
2220 for (j = i; j < i+ 10; j++)
2221 {
2222 sum += messageSizes[j];
2223 total += j * messageSizes[j];
2224 num += messageSizes[j];
2225 }
2226 Com_Printf ("%i-%d: %d\n", LOG_GENERAL, i, i + 10, sum);
2227 }
2228 Com_Printf ("mean: %.2f\n", LOG_GENERAL, (float)total / (float)num);
2229 #else
2230 Com_Printf ("This binary was built with NPROFILE, no stats available.\n", LOG_GENERAL);
2231 #endif
2232 }
2233
_z_debug_changed(cvar_t * cvar,char * o,char * n)2234 void _z_debug_changed (cvar_t *cvar, char *o, char *n)
2235 {
2236 if (cvar->intvalue)
2237 {
2238 Z_TagMalloc = Z_TagMallocDebug;
2239 Z_Free = Z_FreeDebug;
2240 }
2241 else
2242 {
2243 Z_TagMalloc = Z_TagMallocRelease;
2244 Z_Free = Z_FreeRelease;
2245 }
2246
2247 Com_Printf ("Z_Debug: Intensive memory checking %s.\n", LOG_GENERAL, cvar->intvalue ? "enabled" : "disabled");
2248 }
2249
_logfile_changed(cvar_t * cvar,char * o,char * n)2250 void _logfile_changed (cvar_t *cvar, char *o, char *n)
2251 {
2252 if (cvar->intvalue == 0)
2253 {
2254 if (logfile)
2255 {
2256 fclose (logfile);
2257 logfile = NULL;
2258 }
2259 }
2260 }
2261
Qcommon_Init(int argc,char ** argv)2262 void Qcommon_Init (int argc, char **argv)
2263 {
2264 if (setjmp (abortframe) )
2265 Sys_Error ("Error during initialization");
2266
2267 seedMT((uint32)time(0));
2268
2269 SZ_Init (&msgbuff, message_buff, sizeof(message_buff));
2270
2271 Z_Free = Z_FreeRelease;
2272 Z_TagMalloc = Z_TagMallocRelease;
2273
2274 z_chain.next = z_chain.prev = &z_chain;
2275
2276 uninitialized_cvar.string = "";
2277
2278 // prepare enough of the subsystems to handle
2279 // cvar and command buffer management
2280 COM_InitArgv (argc, argv);
2281
2282 Swap_Init ();
2283 Cbuf_Init ();
2284
2285 Cmd_Init ();
2286 Cvar_Init ();
2287
2288 z_debug = Cvar_Get ("z_debug", "0", 0);
2289 z_buggygame = Cvar_Get ("z_buggygame", "0", 0);
2290 z_allowcorruption = Cvar_Get ("z_allowcorruption", "0", 0);
2291
2292 cl_quietstartup = Cvar_Get ("cl_quietstartup", "1", 0);
2293
2294 z_debug->changed = _z_debug_changed;
2295 if (z_debug->intvalue)
2296 {
2297 Z_TagMalloc = Z_TagMallocDebug;
2298 Z_Free = Z_FreeDebug;
2299 }
2300
2301 #ifndef DEDICATED_ONLY
2302 Key_Init ();
2303 #else
2304 //r1: stub out these so configs don't spam unknown cmd
2305 Cmd_AddCommand ("bind",Q_NullFunc);
2306 Cmd_AddCommand ("unbind",Q_NullFunc);
2307 Cmd_AddCommand ("unbindall",Q_NullFunc);
2308 Cmd_AddCommand ("bindlist",Q_NullFunc);
2309 #endif
2310
2311 Cmd_AddCommand ("msg_stats", Msg_Stats_f);
2312 Cmd_AddCommand ("processtimes", Sys_ProcessTimes_f);
2313 Cmd_AddCommand ("spinstats", Sys_Spinstats_f);
2314
2315 // we need to add the early commands twice, because
2316 // a basedir or cddir needs to be set before execing
2317 // config files, but we want other parms to override
2318 // the settings of the config files
2319 Cbuf_AddEarlyCommands (false);
2320 Cbuf_Execute ();
2321
2322 FS_InitFilesystem ();
2323
2324 Cbuf_AddText ("exec default.cfg\n");
2325 Cbuf_AddText ("exec config.cfg\n");
2326
2327 Cbuf_AddEarlyCommands (true);
2328 Cbuf_Execute ();
2329
2330 //
2331 // init commands and vars
2332 //
2333 Cmd_AddCommand ("z_stats", Z_Stats_f);
2334 Cmd_AddCommand ("error", Com_Error_f);
2335
2336 host_speeds = Cvar_Get ("host_speeds", "0", 0);
2337 log_stats = Cvar_Get ("log_stats", "0", 0);
2338 timescale = Cvar_Get ("timescale", "1", 0);
2339 fixedtime = Cvar_Get ("fixedtime", "0", 0);
2340
2341 logfile_active = Cvar_Get ("logfile", "0", 0);
2342 logfile_timestamp = Cvar_Get ("logfile_timestamp", "1", 0);
2343 logfile_timestamp_format = Cvar_Get ("logfile_timestamp_format", "[%Y-%m-%d %H:%M]", 0);
2344 logfile_name = Cvar_Get ("logfile_name", "qconsole.log", 0);
2345 logfile_filterlevel = Cvar_Get ("logfile_filterlevel", "0", 0);
2346 logfile_active->changed = _logfile_changed;
2347
2348 con_filterlevel = Cvar_Get ("con_filterlevel", "0", 0);
2349
2350 #ifndef DEDICATED_ONLY
2351 showtrace = Cvar_Get ("showtrace", "0", 0);
2352 #endif
2353 #ifndef NO_SERVER
2354 #ifdef DEDICATED_ONLY
2355 dedicated = Cvar_Get ("dedicated", "1", CVAR_NOSET);
2356 #else
2357 dedicated = Cvar_Get ("dedicated", "0", CVAR_NOSET);
2358 #endif
2359 #endif
2360
2361 sys_loopstyle = Cvar_Get ("sys_loopstyle", "1", 0);
2362
2363 err_fatal = Cvar_Get ("err_fatal", "0", 0);
2364
2365 //s = va("R1Q2 %s %s %s %s", VERSION, CPUSTRING, __DATE__, BUILDSTRING);
2366 Cvar_Get ("version", R1Q2_VERSION_STRING, CVAR_SERVERINFO|CVAR_NOSET);
2367
2368 #ifndef NO_SERVER
2369 if (dedicated->intvalue)
2370 Cmd_AddCommand ("quit", Com_Quit);
2371 #endif
2372
2373 dbg_unload = Cvar_Get ("dbg_unload", "1", 0);
2374 dbg_crash_on_fatal_error = Cvar_Get ("dbg_crash_on_fatal_error", "0", 0);
2375
2376 Sys_Init ();
2377
2378 NET_Init ();
2379 Netchan_Init ();
2380
2381 #ifndef NO_SERVER
2382 SV_Init ();
2383 #endif
2384
2385 Com_Printf ("====== Quake2 Initialized ======\n", LOG_GENERAL);
2386 Com_Printf ("R1Q2 build " BUILD ", compiled " __DATE__ ".\n"
2387 "http://www.r1ch.net/stuff/r1q2/\n"
2388 BUILDSTRING " " CPUSTRING " (%s)\n\n", LOG_GENERAL, binary_name);
2389
2390 #ifndef DEDICATED_ONLY
2391 CL_Init ();
2392 #endif
2393
2394 // add + commands from command line
2395 if (!Cbuf_AddLateCommands ())
2396 {
2397 // if the user didn't give any commands, run default action
2398 #ifndef NO_SERVER
2399 if (!dedicated->intvalue)
2400 {
2401 #endif
2402
2403 #ifndef DEDICATED_ONLY
2404 Cbuf_AddText ("toggleconsole\n");
2405
2406 Com_Printf (
2407 "Welcome to R1Q2.\n"
2408 "\n"
2409 " Press <ESC> to open the menu.\n"
2410 " Type connect <host> to connect to a server.\n"
2411 " View the readme at http://www.r1ch.net/forum/index.php?board=8.0\n"
2412 "\n", LOG_GENERAL);
2413
2414 Sys_UpdateURLMenu ("http://www.r1ch.net/forum/index.php?board=8.0");
2415 #endif
2416
2417 #ifndef NO_SERVER
2418 }
2419 else
2420 Cbuf_AddText ("dedicated_start\n");
2421 #endif
2422 Cbuf_Execute ();
2423 }
2424 #ifndef DEDICATED_ONLY
2425 else
2426 {
2427 // the user asked for something explicit
2428 // so drop the loading plaque
2429 SCR_EndLoadingPlaque ();
2430 }
2431 #endif
2432
2433 Cbuf_Execute ();
2434
2435 //MSG_NUinitHuffman ();
2436
2437 //ugly
2438 q2_initialized = true;
2439 logfile_timestamp_format->flags |= CVAR_NOSET;
2440 }
2441
2442 /*
2443 =================
2444 Qcommon_Frame
2445 =================
2446 */
Qcommon_Frame(int msec)2447 void Qcommon_Frame (int msec)
2448 {
2449 #ifndef NO_SERVER
2450 char *s;
2451 #endif
2452
2453 #ifndef DEDICATED_ONLY
2454 int time_before = 0, time_between = 0, time_after;
2455 #endif
2456
2457 if (setjmp (abortframe) )
2458 return; // an ERR_DROP was thrown
2459
2460 //Com_Printf ("frame time: %d ms\n", LOG_GENERAL, msec);
2461
2462 /*if ( log_stats->modified )
2463 {
2464 log_stats->modified = false;
2465 if ( log_stats->intvalue )
2466 {
2467 if ( log_stats_file )
2468 {
2469 fclose( log_stats_file );
2470 log_stats_file = 0;
2471 }
2472 log_stats_file = fopen( "stats.log", "w" );
2473 if ( log_stats_file )
2474 fprintf( log_stats_file, "entities,dlights,parts,frame time\n" );
2475 }
2476 else
2477 {
2478 if ( log_stats_file )
2479 {
2480 fclose( log_stats_file );
2481 log_stats_file = 0;
2482 }
2483 }
2484 }*/
2485
2486 if (fixedtime->intvalue)
2487 {
2488 msec = fixedtime->intvalue;
2489 }
2490 else
2491 {
2492 msec = (int)(msec * timescale->value);
2493
2494 //r1: allow server to run zero msec frames to avoid spinloop
2495 /*if (!dedicated->intvalue)
2496 {
2497 if (msec < 1)
2498 msec = 1;
2499 }*/
2500 }
2501
2502 #ifndef DEDICATED_ONLY
2503 if (showtrace->intvalue)
2504 {
2505 extern int c_traces, c_brush_traces;
2506 extern int c_pointcontents;
2507
2508 Com_Printf ("%4i traces %4i points\n", LOG_GENERAL, c_traces, c_pointcontents);
2509 c_traces = 0;
2510 c_brush_traces = 0;
2511 c_pointcontents = 0;
2512 }
2513 #endif
2514
2515 #ifndef NO_SERVER
2516 #ifndef DEDICATED_ONLY
2517 if (dedicated->intvalue)
2518 {
2519 #endif
2520 do
2521 {
2522 s = Sys_ConsoleInput ();
2523 if (s)
2524 Cbuf_AddText (va("%s\n",s));
2525 Cbuf_Execute();
2526 } while (s);
2527 #ifndef DEDICATED_ONLY
2528 }
2529 #endif
2530 #endif
2531
2532 //Cbuf_Execute ();
2533
2534 #ifndef DEDICATED_ONLY
2535 if (host_speeds->intvalue)
2536 time_before = Sys_Milliseconds ();
2537 #endif
2538
2539 #ifndef NO_SERVER
2540 SV_Frame (msec);
2541 #endif
2542
2543 #ifndef DEDICATED_ONLY
2544 if (host_speeds->intvalue)
2545 time_between = Sys_Milliseconds ();
2546
2547 CL_Frame (msec);
2548
2549 if (host_speeds->intvalue) {
2550 int all, sv, gm, cl, rf;
2551
2552 time_after = Sys_Milliseconds ();
2553
2554 all = time_after - time_before;
2555 sv = time_between - time_before;
2556 cl = time_after - time_between;
2557 gm = time_after_game - time_before_game;
2558 rf = time_after_ref - time_before_ref;
2559 sv -= gm;
2560 cl -= rf;
2561 Com_Printf ("all:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n", LOG_GENERAL,
2562 all, sv, gm, cl, rf);
2563 }
2564 #endif
2565
2566 }
2567
2568 #ifndef NO_ZLIB
ZLibDecompress(byte * in,int inlen,byte * out,int outlen,int wbits)2569 int ZLibDecompress (byte *in, int inlen, byte *out, int outlen, int wbits)
2570 {
2571 z_stream zs;
2572 int result;
2573
2574 memset (&zs, 0, sizeof(zs));
2575
2576 zs.next_in = in;
2577 zs.avail_in = 0;
2578
2579 zs.next_out = out;
2580 zs.avail_out = outlen;
2581
2582 result = inflateInit2(&zs, wbits);
2583 if (result != Z_OK)
2584 {
2585 Com_Error (ERR_DROP, "ZLib data error! Error %d on inflateInit.\nMessage: %s", result, zs.msg);
2586 return 0;
2587 }
2588
2589 zs.avail_in = inlen;
2590
2591 result = inflate(&zs, Z_FINISH);
2592 if (result != Z_STREAM_END)
2593 {
2594 Com_Error (ERR_DROP, "ZLib data error! Error %d on inflate.\nMessage: %s", result, zs.msg);
2595 zs.total_out = 0;
2596 }
2597
2598 result = inflateEnd(&zs);
2599 if (result != Z_OK)
2600 {
2601 Com_Error (ERR_DROP, "ZLib data error! Error %d on inflateEnd.\nMessage: %s", result, zs.msg);
2602 return 0;
2603 }
2604
2605 return zs.total_out;
2606 }
2607
ZLibCompressChunk(byte * in,int len_in,byte * out,int len_out,int method,int wbits)2608 int ZLibCompressChunk(byte *in, int len_in, byte *out, int len_out, int method, int wbits)
2609 {
2610 z_stream zs;
2611 int result;
2612
2613 zs.next_in = in;
2614 zs.avail_in = len_in;
2615 zs.total_in = 0;
2616
2617 zs.next_out = out;
2618 zs.avail_out = len_out;
2619 zs.total_out = 0;
2620
2621 zs.msg = NULL;
2622 zs.state = NULL;
2623 zs.zalloc = Z_NULL;
2624 zs.zfree = Z_NULL;
2625 zs.opaque = NULL;
2626
2627 zs.data_type = Z_BINARY;
2628 zs.adler = 0;
2629 zs.reserved = 0;
2630
2631 result = deflateInit2 (&zs, method, Z_DEFLATED, wbits, 9, Z_DEFAULT_STRATEGY);
2632 if (result != Z_OK)
2633 return -1;
2634
2635 result = deflate(&zs, Z_FINISH);
2636 if (result != Z_STREAM_END)
2637 return -1;
2638
2639 result = deflateEnd(&zs);
2640 if (result != Z_OK)
2641 return -1;
2642
2643 return zs.total_out;
2644 }
2645 #endif
2646
StripHighBits(char * string,int highbits)2647 void StripHighBits (char *string, int highbits)
2648 {
2649 byte high;
2650 byte c;
2651 char *p;
2652
2653 p = string;
2654
2655 if (highbits)
2656 high = 127;
2657 else
2658 high = 255;
2659
2660 while (string[0])
2661 {
2662 c = *(string++);
2663
2664 if (c >= 32 && c <= high)
2665 *p++ = c;
2666 }
2667
2668 p[0] = '\0';
2669 }
2670
isvalidchar(int c)2671 qboolean isvalidchar (int c)
2672 {
2673 if (!isalnum(c) && c != '_' && c != '-')
2674 return false;
2675 return true;
2676 }
2677
ExpandNewLines(char * string)2678 void ExpandNewLines (char *string)
2679 {
2680 char *q = string;
2681 char *s = q;
2682
2683 if (!string[0])
2684 return;
2685
2686 while (*(q+1))
2687 {
2688 if (*q == '\\' && *(q+1) == 'n')
2689 {
2690 *s++ = '\n';
2691 q++;
2692 }
2693 else
2694 {
2695 *s++ = *q;
2696 }
2697 q++;
2698
2699 //crashfix, check if we reached eol on an expansion.
2700 if (!*q)
2701 break;
2702 }
2703
2704 if (*q)
2705 *s++ = *q;
2706 *s = '\0';
2707 }
2708
StripQuotes(char * string)2709 char *StripQuotes (char *string)
2710 {
2711 size_t i;
2712
2713 if (!string[0])
2714 return string;
2715
2716 i = strlen(string);
2717
2718 if (string[0] == '"' && string[i-1] == '"')
2719 {
2720 string[i-1] = 0;
2721 return string + 1;
2722 }
2723
2724 return string;
2725 }
2726
MakePrintable(const void * subject,size_t numchars)2727 const char *MakePrintable (const void *subject, size_t numchars)
2728 {
2729 int len;
2730 static char printable[4096];
2731 char tmp[8];
2732 char *p;
2733 const byte *s;
2734
2735 if (!subject)
2736 {
2737 strcpy (printable, "(null)");
2738 return printable;
2739 }
2740
2741 s = (const byte *)subject;
2742 p = printable;
2743 len = 0;
2744
2745 if (!numchars)
2746 numchars = strlen((const char *) s);
2747
2748 while (numchars--)
2749 {
2750 if (isprint(s[0]))
2751 {
2752 *p++ = s[0];
2753 len++;
2754 }
2755 else
2756 {
2757 sprintf (tmp, "%.3d", s[0]);
2758 *p++ = '\\';
2759 *p++ = tmp[0];
2760 *p++ = tmp[1];
2761 *p++ = tmp[2];
2762 len += 4;
2763 }
2764
2765 if (len >= sizeof(printable)-5)
2766 break;
2767
2768 s++;
2769 }
2770
2771 printable[len] = 0;
2772 return printable;
2773 }
2774
2775 /*
2776 =================
2777 Qcommon_Shutdown
2778 =================
2779 */
Qcommon_Shutdown(void)2780 void Qcommon_Shutdown (void)
2781 {
2782 }
2783
Z_CheckGameLeaks(void)2784 void Z_CheckGameLeaks (void)
2785 {
2786 z_memloc_t *loc, *last;
2787
2788 loc = last = &z_game_locations;
2789
2790 if (loc->next)
2791 {
2792 Com_Printf ("Memory leak detected in Game DLL. Leaked blocks: ", LOG_GENERAL|LOG_WARNING);
2793
2794 while (loc->next)
2795 {
2796 loc = loc->next;
2797 Com_Printf ("%p (%d bytes)%s", LOG_GENERAL|LOG_WARNING, loc->address, loc->size, loc->next ? ", " : "");
2798 }
2799 Com_Printf ("\n", LOG_GENERAL|LOG_WARNING);
2800 }
2801 }
2802
2803