2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // common.c -- misc functions used in client and server
30 cvar_t registered = {0, "registered","0"};
31 cvar_t cmdline = {0, "cmdline","0"};
33 extern qboolean fs_modified; // set true if using non-id files
37 const char **com_argv;
39 // LordHavoc: made commandline 1024 characters instead of 256
40 #define CMDLINE_LENGTH 1024
41 char com_cmdline[CMDLINE_LENGTH];
46 char com_modname[MAX_OSPATH] = "";
50 ============================================================================
54 ============================================================================
57 short ShortSwap (short l)
76 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
79 float FloatSwap (float f)
89 dat2.b[0] = dat1.b[3];
90 dat2.b[1] = dat1.b[2];
91 dat2.b[2] = dat1.b[1];
92 dat2.b[3] = dat1.b[0];
97 // Extract integers from buffers
99 unsigned int BuffBigLong (const qbyte *buffer)
101 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
104 unsigned short BuffBigShort (const qbyte *buffer)
106 return (buffer[0] << 8) | buffer[1];
109 unsigned int BuffLittleLong (const qbyte *buffer)
111 return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
114 unsigned short BuffLittleShort (const qbyte *buffer)
116 return (buffer[1] << 8) | buffer[0];
121 ==============================================================================
125 Handles byte ordering and avoids alignment errors
126 ==============================================================================
133 void MSG_WriteChar (sizebuf_t *sb, int c)
137 buf = SZ_GetSpace (sb, 1);
141 void MSG_WriteByte (sizebuf_t *sb, int c)
145 buf = SZ_GetSpace (sb, 1);
149 void MSG_WriteShort (sizebuf_t *sb, int c)
153 buf = SZ_GetSpace (sb, 2);
158 void MSG_WriteLong (sizebuf_t *sb, int c)
162 buf = SZ_GetSpace (sb, 4);
164 buf[1] = (c>>8)&0xff;
165 buf[2] = (c>>16)&0xff;
169 void MSG_WriteFloat (sizebuf_t *sb, float f)
179 dat.l = LittleLong (dat.l);
181 SZ_Write (sb, &dat.l, 4);
184 void MSG_WriteString (sizebuf_t *sb, const char *s)
187 SZ_Write (sb, "", 1);
189 SZ_Write (sb, s, strlen(s)+1);
192 // used by server (always latest PROTOCOL_DARKPLACES)
193 void MSG_WriteDPCoord (sizebuf_t *sb, float f)
196 MSG_WriteShort (sb, (int)(f + 0.5f));
198 MSG_WriteShort (sb, (int)(f - 0.5f));
201 void MSG_WritePreciseAngle (sizebuf_t *sb, float f)
204 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
206 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) - 0.5f) & 65535);
209 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
210 void MSG_WriteAngle (sizebuf_t *sb, float f)
213 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
215 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) - 0.5f) & 255);
222 qboolean msg_badread;
224 void MSG_BeginReading (void)
230 int MSG_ReadLittleShort (void)
232 if (msg_readcount+2 > net_message.cursize)
238 return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
241 int MSG_ReadBigShort (void)
243 if (msg_readcount+2 > net_message.cursize)
249 return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
252 int MSG_ReadLittleLong (void)
254 if (msg_readcount+4 > net_message.cursize)
260 return net_message.data[msg_readcount-4] | (net_message.data[msg_readcount-3]<<8) | (net_message.data[msg_readcount-2]<<16) | (net_message.data[msg_readcount-1]<<24);
263 int MSG_ReadBigLong (void)
265 if (msg_readcount+4 > net_message.cursize)
271 return (net_message.data[msg_readcount-4]<<24) + (net_message.data[msg_readcount-3]<<16) + (net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1];
274 float MSG_ReadLittleFloat (void)
281 if (msg_readcount+4 > net_message.cursize)
287 dat.l = net_message.data[msg_readcount-4] | (net_message.data[msg_readcount-3]<<8) | (net_message.data[msg_readcount-2]<<16) | (net_message.data[msg_readcount-1]<<24);
291 float MSG_ReadBigFloat (void)
298 if (msg_readcount+4 > net_message.cursize)
304 dat.l = (net_message.data[msg_readcount-4]<<24) | (net_message.data[msg_readcount-3]<<16) | (net_message.data[msg_readcount-2]<<8) | net_message.data[msg_readcount-1];
308 char *MSG_ReadString (void)
310 static char string[2048];
312 for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadChar()) != -1 && c != 0;l++)
318 int MSG_ReadBytes (int numbytes, unsigned char *out)
321 for (l = 0;l < numbytes && (c = MSG_ReadChar()) != -1;l++)
327 float MSG_ReadCoord (void)
329 if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
330 return (signed short) MSG_ReadLittleShort();
331 else if (cl.protocol == PROTOCOL_DARKPLACES1)
332 return MSG_ReadLittleFloat();
334 return MSG_ReadLittleShort() * (1.0f/8.0f);
338 //===========================================================================
340 void SZ_Alloc (sizebuf_t *buf, int startsize, const char *name)
344 buf->mempool = Mem_AllocPool(name);
345 buf->data = Mem_Alloc(buf->mempool, startsize);
346 buf->maxsize = startsize;
351 void SZ_Free (sizebuf_t *buf)
353 Mem_FreePool(&buf->mempool);
359 void SZ_Clear (sizebuf_t *buf)
364 void *SZ_GetSpace (sizebuf_t *buf, int length)
368 if (buf->cursize + length > buf->maxsize)
370 if (!buf->allowoverflow)
371 Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n");
373 if (length > buf->maxsize)
374 Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length);
376 buf->overflowed = true;
377 Con_Print("SZ_GetSpace: overflow\n");
381 data = buf->data + buf->cursize;
382 buf->cursize += length;
387 void SZ_Write (sizebuf_t *buf, const void *data, int length)
389 memcpy (SZ_GetSpace(buf,length),data,length);
392 // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
393 // attention, it has been eradicated from here, its only (former) use in
394 // all of darkplaces.
396 static char *hexchar = "0123456789ABCDEF";
397 void Com_HexDumpToConsole(const qbyte *data, int size)
401 char *cur, *flushpointer;
404 flushpointer = text + 512;
405 for (i = 0;i < size;)
411 *cur++ = hexchar[(i >> 12) & 15];
412 *cur++ = hexchar[(i >> 8) & 15];
413 *cur++ = hexchar[(i >> 4) & 15];
414 *cur++ = hexchar[(i >> 0) & 15];
416 for (j = 0;j < n;j++)
420 *cur++ = hexchar[(d[j] >> 4) & 15] | 0x80;
421 *cur++ = hexchar[(d[j] >> 0) & 15] | 0x80;
425 *cur++ = hexchar[(d[j] >> 4) & 15];
426 *cur++ = hexchar[(d[j] >> 0) & 15];
434 for (j = 0;j < n;j++)
435 *cur++ = (d[j] >= ' ' && d[j] <= 0x7E) ? d[j] : '.';
440 if (cur >= flushpointer || i >= size)
449 void SZ_HexDumpToConsole(const sizebuf_t *buf)
451 Com_HexDumpToConsole(buf->data, buf->cursize);
455 //============================================================================
462 Parse a token out of a string
465 int COM_ParseToken(const char **datapointer, int returnnewline)
468 const char *data = *datapointer;
481 for (;*data <= ' ' && (*data != '\n' || !returnnewline);data++)
491 if (data[0] == '/' && data[1] == '/')
494 while (*data && *data != '\n')
498 else if (data[0] == '/' && data[1] == '*')
502 while (*data && (data[0] != '*' || data[1] != '/'))
507 else if (*data == '\"')
510 for (data++;*data != '\"';data++)
512 if (!*data || len >= (int)sizeof(com_token) - 1)
518 com_token[len++] = *data;
521 *datapointer = data+1;
524 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == '\'' || *data == ':' || *data == ',' || *data == ';')
527 com_token[len++] = *data++;
535 for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != '\'' && *data != ':' && *data != ',' && *data != ';';data++)
537 if (len >= (int)sizeof(com_token) - 1)
543 com_token[len++] = *data;
553 COM_ParseTokenConsole
555 Parse a token out of a string, behaving like the qwcl console
558 int COM_ParseTokenConsole(const char **datapointer)
561 const char *data = *datapointer;
574 for (;*data <= ' ';data++)
584 if (*data == '/' && data[1] == '/')
587 while (*data && *data != '\n')
591 else if (*data == '\"')
594 for (data++;*data != '\"';data++)
596 if (!*data || len >= (int)sizeof(com_token) - 1)
602 com_token[len++] = *data;
605 *datapointer = data+1;
611 for (;*data > ' ';data++)
613 if (len >= (int)sizeof(com_token) - 1)
619 com_token[len++] = *data;
632 Returns the position (1 to argc-1) in the program's argument list
633 where the given parameter apears, or 0 if not present
636 int COM_CheckParm (const char *parm)
640 for (i=1 ; i<com_argc ; i++)
643 continue; // NEXTSTEP sometimes clears appkit vars.
644 if (!strcmp (parm,com_argv[i]))
655 Looks for the pop.txt file and verifies it.
656 Sets the "registered" cvar.
657 Immediately exits out if an alternate game was attempted to be started without
661 void COM_CheckRegistered (void)
663 Cvar_Set ("cmdline", com_cmdline);
665 if (!FS_FileExists("gfx/pop.lmp"))
668 Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
670 Con_Print("Playing shareware version.\n");
674 Cvar_Set ("registered", "1");
675 Con_Print("Playing registered version.\n");
684 void COM_InitArgv (void)
687 // reconstitute the command line for the cmdline externally visible cvar
689 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
692 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
693 com_cmdline[n++] = com_argv[j][i++];
694 if (n < (CMDLINE_LENGTH - 1))
695 com_cmdline[n++] = ' ';
702 void COM_InitGameType (void)
704 char name[MAX_OSPATH];
705 FS_StripExtension (com_argv[0], name, sizeof (name));
706 COM_ToLowerString (name, name, sizeof (name));
708 if (strstr(name, "transfusion"))
709 gamemode = GAME_TRANSFUSION;
710 else if (strstr(name, "nexuiz"))
711 gamemode = GAME_NEXUIZ;
712 else if (strstr(name, "nehahra"))
713 gamemode = GAME_NEHAHRA;
714 else if (strstr(name, "hipnotic"))
715 gamemode = GAME_HIPNOTIC;
716 else if (strstr(name, "rogue"))
717 gamemode = GAME_ROGUE;
718 else if (strstr(name, "gvb2"))
719 gamemode = GAME_GOODVSBAD2;
720 else if (strstr(name, "teu"))
722 else if (strstr(name, "battlemech"))
723 gamemode = GAME_BATTLEMECH;
724 else if (strstr(name, "zymotic"))
725 gamemode = GAME_ZYMOTIC;
726 else if (strstr(name, "fniggium"))
727 gamemode = GAME_FNIGGIUM;
728 else if (strstr(name, "setheral"))
729 gamemode = GAME_SETHERAL;
730 else if (strstr(name, "som"))
732 else if (strstr(name, "tenebrae"))
733 gamemode = GAME_TENEBRAE;
735 gamemode = GAME_NORMAL;
737 if (COM_CheckParm ("-transfusion"))
738 gamemode = GAME_TRANSFUSION;
739 else if (COM_CheckParm ("-nexuiz"))
740 gamemode = GAME_NEXUIZ;
741 else if (COM_CheckParm ("-nehahra"))
742 gamemode = GAME_NEHAHRA;
743 else if (COM_CheckParm ("-hipnotic"))
744 gamemode = GAME_HIPNOTIC;
745 else if (COM_CheckParm ("-rogue"))
746 gamemode = GAME_ROGUE;
747 else if (COM_CheckParm ("-quake"))
748 gamemode = GAME_NORMAL;
749 else if (COM_CheckParm ("-goodvsbad2"))
750 gamemode = GAME_GOODVSBAD2;
751 else if (COM_CheckParm ("-teu"))
753 else if (COM_CheckParm ("-battlemech"))
754 gamemode = GAME_BATTLEMECH;
755 else if (COM_CheckParm ("-zymotic"))
756 gamemode = GAME_ZYMOTIC;
757 else if (COM_CheckParm ("-fniggium"))
758 gamemode = GAME_FNIGGIUM;
759 else if (COM_CheckParm ("-setheral"))
760 gamemode = GAME_SETHERAL;
761 else if (COM_CheckParm ("-som"))
763 else if (COM_CheckParm ("-tenebrae"))
764 gamemode = GAME_TENEBRAE;
769 gamename = "DarkPlaces-Quake";
773 gamename = "Darkplaces-Hipnotic";
774 gamedirname = "hipnotic";
777 gamename = "Darkplaces-Rogue";
778 gamedirname = "rogue";
781 gamename = "DarkPlaces-Nehahra";
782 gamedirname = "nehahra";
786 gamedirname = "data";
788 case GAME_TRANSFUSION:
789 gamename = "Transfusion";
790 gamedirname = "basetf";
792 case GAME_GOODVSBAD2:
793 gamename = "GoodVs.Bad2";
797 gamename = "TheEvilUnleashed";
798 gamedirname = "baseteu";
800 case GAME_BATTLEMECH:
801 gamename = "Battlemech";
802 gamedirname = "base";
805 gamename = "Zymotic";
806 gamedirname = "data";
809 gamename = "Fniggium";
810 gamedirname = "data";
813 gamename = "Setheral";
814 gamedirname = "data";
817 gamename = "Son of Man";
818 gamedirname = "data";
821 gamename = "DarkPlaces-Tenebrae";
822 gamedirname = "tenebrae";
825 Sys_Error("COM_InitGameType: unknown gamemode %i\n", gamemode);
831 extern void Mathlib_Init(void);
832 extern void FS_Init (void);
841 Cvar_RegisterVariable (®istered);
842 Cvar_RegisterVariable (&cmdline);
848 COM_CheckRegistered ();
858 does a varargs printf into a temp buffer, so I don't need to have
859 varargs versions of all text functions.
860 FIXME: make this buffer size safe someday
863 char *va(const char *format, ...)
866 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
867 static char string[8][1024], *s;
868 static int stringindex = 0;
870 s = string[stringindex];
871 stringindex = (stringindex + 1) & 7;
872 va_start (argptr, format);
873 vsnprintf (s, sizeof (string[0]), format,argptr);
880 //======================================
882 void COM_ToLowerString (const char *in, char *out, size_t size_out)
887 while (*in && size_out > 1)
889 if (*in >= 'A' && *in <= 'Z')
890 *out++ = *in++ + 'a' - 'A';
898 void COM_ToUpperString (const char *in, char *out, size_t size_out)
903 while (*in && size_out > 1)
905 if (*in >= 'a' && *in <= 'z')
906 *out++ = *in++ + 'A' - 'a';
914 int COM_StringBeginsWith(const char *s, const char *match)
916 for (;*s && *match;s++, match++)
922 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
924 int argc, commentprefixlength;
928 tokenbufend = tokenbuf + tokenbufsize;
930 commentprefixlength = 0;
932 commentprefixlength = strlen(commentprefix);
933 while (*l && *l != '\n')
937 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
939 while (*l && *l != '\n')
945 argv[argc++] = tokenbuf;
949 while (*l && *l != '"')
951 if (tokenbuf >= tokenbufend)
962 if (tokenbuf >= tokenbufend)
967 if (tokenbuf >= tokenbufend)
980 // written by Elric, thanks Elric!
981 char *SearchInfostring(const char *infostring, const char *key)
983 static char value [256];
985 size_t value_ind, key_ind;
988 if (*infostring++ != '\\')
1003 if (c == '\\' || key_ind == sizeof (crt_key) - 1)
1005 crt_key[key_ind] = '\0';
1009 crt_key[key_ind++] = c;
1012 // If it's the key we are looking for, save it in "value"
1013 if (!strcmp(crt_key, key))
1019 if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
1021 value[value_ind] = '\0';
1025 value[value_ind++] = c;
1029 // Else, skip the value
1043 //========================================================
1044 // strlcat and strlcpy, from OpenBSD
1047 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1049 * Permission to use, copy, modify, and distribute this software for any
1050 * purpose with or without fee is hereby granted, provided that the above
1051 * copyright notice and this permission notice appear in all copies.
1053 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1054 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1055 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1056 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1057 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1058 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1059 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1062 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
1063 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
1066 #ifndef HAVE_STRLCAT
1068 strlcat(char *dst, const char *src, size_t siz)
1070 register char *d = dst;
1071 register const char *s = src;
1072 register size_t n = siz;
1075 /* Find the end of dst and adjust bytes left but don't go past end */
1076 while (n-- != 0 && *d != '\0')
1082 return(dlen + strlen(s));
1083 while (*s != '\0') {
1092 return(dlen + (s - src)); /* count does not include NUL */
1094 #endif // #ifndef HAVE_STRLCAT
1097 #ifndef HAVE_STRLCPY
1099 strlcpy(char *dst, const char *src, size_t siz)
1101 register char *d = dst;
1102 register const char *s = src;
1103 register size_t n = siz;
1105 /* Copy as many bytes as will fit */
1106 if (n != 0 && --n != 0) {
1108 if ((*d++ = *s++) == 0)
1113 /* Not enough room in dst, add NUL and traverse rest of src */
1116 *d = '\0'; /* NUL-terminate dst */
1121 return(s - src - 1); /* count does not include NUL */
1124 #endif // #ifndef HAVE_STRLCPY