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 *gamescreenshotname;
47 char com_modname[MAX_OSPATH] = "";
51 ============================================================================
55 ============================================================================
58 short ShortSwap (short l)
77 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
80 float FloatSwap (float f)
90 dat2.b[0] = dat1.b[3];
91 dat2.b[1] = dat1.b[2];
92 dat2.b[2] = dat1.b[1];
93 dat2.b[3] = dat1.b[0];
98 // Extract integers from buffers
100 unsigned int BuffBigLong (const qbyte *buffer)
102 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
105 unsigned short BuffBigShort (const qbyte *buffer)
107 return (buffer[0] << 8) | buffer[1];
110 unsigned int BuffLittleLong (const qbyte *buffer)
112 return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
115 unsigned short BuffLittleShort (const qbyte *buffer)
117 return (buffer[1] << 8) | buffer[0];
122 ==============================================================================
126 Handles byte ordering and avoids alignment errors
127 ==============================================================================
134 void MSG_WriteChar (sizebuf_t *sb, int c)
138 buf = SZ_GetSpace (sb, 1);
142 void MSG_WriteByte (sizebuf_t *sb, int c)
146 buf = SZ_GetSpace (sb, 1);
150 void MSG_WriteShort (sizebuf_t *sb, int c)
154 buf = SZ_GetSpace (sb, 2);
159 void MSG_WriteLong (sizebuf_t *sb, int c)
163 buf = SZ_GetSpace (sb, 4);
165 buf[1] = (c>>8)&0xff;
166 buf[2] = (c>>16)&0xff;
170 void MSG_WriteFloat (sizebuf_t *sb, float f)
180 dat.l = LittleLong (dat.l);
182 SZ_Write (sb, &dat.l, 4);
185 void MSG_WriteString (sizebuf_t *sb, const char *s)
188 SZ_Write (sb, "", 1);
190 SZ_Write (sb, s, strlen(s)+1);
193 // used by server (always latest PROTOCOL_DARKPLACES)
194 void MSG_WriteDPCoord (sizebuf_t *sb, float f)
197 MSG_WriteShort (sb, (int)(f + 0.5f));
199 MSG_WriteShort (sb, (int)(f - 0.5f));
202 void MSG_WritePreciseAngle (sizebuf_t *sb, float f)
205 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
207 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) - 0.5f) & 65535);
210 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
211 void MSG_WriteAngle (sizebuf_t *sb, float f)
214 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
216 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) - 0.5f) & 255);
223 qboolean msg_badread;
225 void MSG_BeginReading (void)
231 int MSG_ReadLittleShort (void)
233 if (msg_readcount+2 > net_message.cursize)
239 return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
242 int MSG_ReadBigShort (void)
244 if (msg_readcount+2 > net_message.cursize)
250 return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
253 int MSG_ReadLittleLong (void)
255 if (msg_readcount+4 > net_message.cursize)
261 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);
264 int MSG_ReadBigLong (void)
266 if (msg_readcount+4 > net_message.cursize)
272 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];
275 float MSG_ReadLittleFloat (void)
282 if (msg_readcount+4 > net_message.cursize)
288 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);
292 float MSG_ReadBigFloat (void)
299 if (msg_readcount+4 > net_message.cursize)
305 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];
309 char *MSG_ReadString (void)
311 static char string[2048];
313 for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadChar()) != -1 && c != 0;l++)
319 int MSG_ReadBytes (int numbytes, unsigned char *out)
322 for (l = 0;l < numbytes && (c = MSG_ReadChar()) != -1;l++)
328 float MSG_ReadCoord (void)
330 if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
331 return (signed short) MSG_ReadLittleShort();
332 else if (cl.protocol == PROTOCOL_DARKPLACES1)
333 return MSG_ReadLittleFloat();
335 return MSG_ReadLittleShort() * (1.0f/8.0f);
339 //===========================================================================
341 void SZ_Alloc (sizebuf_t *buf, int startsize, const char *name)
345 buf->mempool = Mem_AllocPool(name);
346 buf->data = Mem_Alloc(buf->mempool, startsize);
347 buf->maxsize = startsize;
352 void SZ_Free (sizebuf_t *buf)
354 Mem_FreePool(&buf->mempool);
360 void SZ_Clear (sizebuf_t *buf)
365 void *SZ_GetSpace (sizebuf_t *buf, int length)
369 if (buf->cursize + length > buf->maxsize)
371 if (!buf->allowoverflow)
372 Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n");
374 if (length > buf->maxsize)
375 Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length);
377 buf->overflowed = true;
378 Con_Print("SZ_GetSpace: overflow\n");
382 data = buf->data + buf->cursize;
383 buf->cursize += length;
388 void SZ_Write (sizebuf_t *buf, const void *data, int length)
390 memcpy (SZ_GetSpace(buf,length),data,length);
393 // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
394 // attention, it has been eradicated from here, its only (former) use in
395 // all of darkplaces.
397 static char *hexchar = "0123456789ABCDEF";
398 void Com_HexDumpToConsole(const qbyte *data, int size)
402 char *cur, *flushpointer;
405 flushpointer = text + 512;
406 for (i = 0;i < size;)
413 *cur++ = hexchar[(i >> 12) & 15];
414 *cur++ = hexchar[(i >> 8) & 15];
415 *cur++ = hexchar[(i >> 4) & 15];
416 *cur++ = hexchar[(i >> 0) & 15];
419 for (j = 0;j < 16;j++)
423 *cur++ = hexchar[(d[j] >> 4) & 15];
424 *cur++ = hexchar[(d[j] >> 0) & 15];
435 for (j = 0;j < 16;j++)
439 if (d[j] >= ' ' && d[j] <= 127)
449 if (cur >= flushpointer || i >= size)
458 void SZ_HexDumpToConsole(const sizebuf_t *buf)
460 Com_HexDumpToConsole(buf->data, buf->cursize);
464 //============================================================================
471 Parse a token out of a string
474 int COM_ParseToken(const char **datapointer, int returnnewline)
477 const char *data = *datapointer;
490 for (;*data <= ' ' && (*data != '\n' || !returnnewline);data++)
500 if (data[0] == '/' && data[1] == '/')
503 while (*data && *data != '\n')
507 else if (data[0] == '/' && data[1] == '*')
511 while (*data && (data[0] != '*' || data[1] != '/'))
516 else if (*data == '\"')
519 for (data++;*data != '\"';data++)
521 if (!*data || len >= (int)sizeof(com_token) - 1)
527 com_token[len++] = *data;
530 *datapointer = data+1;
533 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == '\'' || *data == ':' || *data == ',' || *data == ';')
536 com_token[len++] = *data++;
544 for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != '\'' && *data != ':' && *data != ',' && *data != ';';data++)
546 if (len >= (int)sizeof(com_token) - 1)
552 com_token[len++] = *data;
562 COM_ParseTokenConsole
564 Parse a token out of a string, behaving like the qwcl console
567 int COM_ParseTokenConsole(const char **datapointer)
570 const char *data = *datapointer;
583 for (;*data <= ' ';data++)
593 if (*data == '/' && data[1] == '/')
596 while (*data && *data != '\n')
600 else if (*data == '\"')
603 for (data++;*data != '\"';data++)
605 if (!*data || len >= (int)sizeof(com_token) - 1)
611 com_token[len++] = *data;
614 *datapointer = data+1;
620 for (;*data > ' ';data++)
622 if (len >= (int)sizeof(com_token) - 1)
628 com_token[len++] = *data;
641 Returns the position (1 to argc-1) in the program's argument list
642 where the given parameter apears, or 0 if not present
645 int COM_CheckParm (const char *parm)
649 for (i=1 ; i<com_argc ; i++)
652 continue; // NEXTSTEP sometimes clears appkit vars.
653 if (!strcmp (parm,com_argv[i]))
664 Looks for the pop.txt file and verifies it.
665 Sets the "registered" cvar.
666 Immediately exits out if an alternate game was attempted to be started without
670 void COM_CheckRegistered (void)
672 Cvar_Set ("cmdline", com_cmdline);
674 if (!FS_FileExists("gfx/pop.lmp"))
677 Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
679 Con_Print("Playing shareware version.\n");
683 Cvar_Set ("registered", "1");
684 Con_Print("Playing registered version.\n");
693 void COM_InitArgv (void)
696 // reconstitute the command line for the cmdline externally visible cvar
698 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
701 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
702 com_cmdline[n++] = com_argv[j][i++];
703 if (n < (CMDLINE_LENGTH - 1))
704 com_cmdline[n++] = ' ';
711 void COM_InitGameType (void)
713 char name[MAX_OSPATH];
714 FS_StripExtension (com_argv[0], name, sizeof (name));
715 COM_ToLowerString (name, name, sizeof (name));
717 if (strstr(name, "transfusion"))
718 gamemode = GAME_TRANSFUSION;
719 else if (strstr(name, "nexuiz"))
720 gamemode = GAME_NEXUIZ;
721 else if (strstr(name, "nehahra"))
722 gamemode = GAME_NEHAHRA;
723 else if (strstr(name, "hipnotic"))
724 gamemode = GAME_HIPNOTIC;
725 else if (strstr(name, "rogue"))
726 gamemode = GAME_ROGUE;
727 else if (strstr(name, "gvb2"))
728 gamemode = GAME_GOODVSBAD2;
729 else if (strstr(name, "teu"))
731 else if (strstr(name, "battlemech"))
732 gamemode = GAME_BATTLEMECH;
733 else if (strstr(name, "zymotic"))
734 gamemode = GAME_ZYMOTIC;
735 else if (strstr(name, "fniggium"))
736 gamemode = GAME_FNIGGIUM;
737 else if (strstr(name, "setheral"))
738 gamemode = GAME_SETHERAL;
739 else if (strstr(name, "som"))
741 else if (strstr(name, "tenebrae"))
742 gamemode = GAME_TENEBRAE;
743 else if (strstr(name, "neoteric"))
744 gamemode = GAME_NEOTERIC;
745 else if (strstr(name, "openquartz"))
746 gamemode = GAME_OPENQUARTZ;
748 gamemode = GAME_NORMAL;
750 if (COM_CheckParm ("-transfusion"))
751 gamemode = GAME_TRANSFUSION;
752 else if (COM_CheckParm ("-nexuiz"))
753 gamemode = GAME_NEXUIZ;
754 else if (COM_CheckParm ("-nehahra"))
755 gamemode = GAME_NEHAHRA;
756 else if (COM_CheckParm ("-hipnotic"))
757 gamemode = GAME_HIPNOTIC;
758 else if (COM_CheckParm ("-rogue"))
759 gamemode = GAME_ROGUE;
760 else if (COM_CheckParm ("-quake"))
761 gamemode = GAME_NORMAL;
762 else if (COM_CheckParm ("-goodvsbad2"))
763 gamemode = GAME_GOODVSBAD2;
764 else if (COM_CheckParm ("-teu"))
766 else if (COM_CheckParm ("-battlemech"))
767 gamemode = GAME_BATTLEMECH;
768 else if (COM_CheckParm ("-zymotic"))
769 gamemode = GAME_ZYMOTIC;
770 else if (COM_CheckParm ("-fniggium"))
771 gamemode = GAME_FNIGGIUM;
772 else if (COM_CheckParm ("-setheral"))
773 gamemode = GAME_SETHERAL;
774 else if (COM_CheckParm ("-som"))
776 else if (COM_CheckParm ("-tenebrae"))
777 gamemode = GAME_TENEBRAE;
778 else if (COM_CheckParm ("-neoteric"))
779 gamemode = GAME_NEOTERIC;
780 else if (COM_CheckParm ("-openquartz"))
781 gamemode = GAME_OPENQUARTZ;
786 gamename = "DarkPlaces-Quake";
788 gamescreenshotname = "dp";
791 gamename = "Darkplaces-Hipnotic";
792 gamedirname = "hipnotic";
793 gamescreenshotname = "dp";
796 gamename = "Darkplaces-Rogue";
797 gamedirname = "rogue";
798 gamescreenshotname = "dp";
801 gamename = "DarkPlaces-Nehahra";
802 gamedirname = "nehahra";
803 gamescreenshotname = "dp";
807 gamedirname = "data";
808 gamescreenshotname = "nexuiz";
810 case GAME_TRANSFUSION:
811 gamename = "Transfusion";
812 gamedirname = "basetf";
813 gamescreenshotname = "transfusion";
815 case GAME_GOODVSBAD2:
816 gamename = "GoodVs.Bad2";
818 gamescreenshotname = "gvb2";
821 gamename = "TheEvilUnleashed";
822 gamedirname = "baseteu";
823 gamescreenshotname = "teu";
825 case GAME_BATTLEMECH:
826 gamename = "Battlemech";
827 gamedirname = "base";
828 gamescreenshotname = "battlemech";
831 gamename = "Zymotic";
832 gamedirname = "data";
833 gamescreenshotname = "zymotic";
836 gamename = "Fniggium";
837 gamedirname = "data";
838 gamescreenshotname = "fniggium";
841 gamename = "Setheral";
842 gamedirname = "data";
843 gamescreenshotname = "setheral";
846 gamename = "Son of Man";
847 gamedirname = "sonofman";
848 gamescreenshotname = "som";
851 gamename = "DarkPlaces-Tenebrae";
852 gamedirname = "tenebrae";
853 gamescreenshotname = "dp";
856 gamename = "Neoteric";
857 gamedirname = "neobase";
858 gamescreenshotname = "neo";
860 case GAME_OPENQUARTZ:
861 gamename = "OpenQuartz";
863 gamescreenshotname = "openquartz";
866 Sys_Error("COM_InitGameType: unknown gamemode %i\n", gamemode);
872 extern void Mathlib_Init(void);
873 extern void FS_Init (void);
882 Cvar_RegisterVariable (®istered);
883 Cvar_RegisterVariable (&cmdline);
889 COM_CheckRegistered ();
897 does a varargs printf into a temp buffer, so I don't need to have
898 varargs versions of all text functions.
899 FIXME: make this buffer size safe someday
902 char *va(const char *format, ...)
905 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
906 static char string[8][1024], *s;
907 static int stringindex = 0;
909 s = string[stringindex];
910 stringindex = (stringindex + 1) & 7;
911 va_start (argptr, format);
912 vsnprintf (s, sizeof (string[0]), format,argptr);
919 //======================================
921 void COM_ToLowerString (const char *in, char *out, size_t size_out)
926 while (*in && size_out > 1)
928 if (*in >= 'A' && *in <= 'Z')
929 *out++ = *in++ + 'a' - 'A';
937 void COM_ToUpperString (const char *in, char *out, size_t size_out)
942 while (*in && size_out > 1)
944 if (*in >= 'a' && *in <= 'z')
945 *out++ = *in++ + 'A' - 'a';
953 int COM_StringBeginsWith(const char *s, const char *match)
955 for (;*s && *match;s++, match++)
961 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
963 int argc, commentprefixlength;
967 tokenbufend = tokenbuf + tokenbufsize;
969 commentprefixlength = 0;
971 commentprefixlength = strlen(commentprefix);
972 while (*l && *l != '\n')
976 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
978 while (*l && *l != '\n')
984 argv[argc++] = tokenbuf;
988 while (*l && *l != '"')
990 if (tokenbuf >= tokenbufend)
1001 if (tokenbuf >= tokenbufend)
1006 if (tokenbuf >= tokenbufend)
1019 // written by Elric, thanks Elric!
1020 char *SearchInfostring(const char *infostring, const char *key)
1022 static char value [256];
1024 size_t value_ind, key_ind;
1027 if (*infostring++ != '\\')
1042 if (c == '\\' || key_ind == sizeof (crt_key) - 1)
1044 crt_key[key_ind] = '\0';
1048 crt_key[key_ind++] = c;
1051 // If it's the key we are looking for, save it in "value"
1052 if (!strcmp(crt_key, key))
1058 if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
1060 value[value_ind] = '\0';
1064 value[value_ind++] = c;
1068 // Else, skip the value
1082 //========================================================
1083 // strlcat and strlcpy, from OpenBSD
1086 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1088 * Permission to use, copy, modify, and distribute this software for any
1089 * purpose with or without fee is hereby granted, provided that the above
1090 * copyright notice and this permission notice appear in all copies.
1092 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1093 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1094 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1095 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1096 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1097 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1098 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1101 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
1102 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
1105 #ifndef HAVE_STRLCAT
1107 strlcat(char *dst, const char *src, size_t siz)
1109 register char *d = dst;
1110 register const char *s = src;
1111 register size_t n = siz;
1114 /* Find the end of dst and adjust bytes left but don't go past end */
1115 while (n-- != 0 && *d != '\0')
1121 return(dlen + strlen(s));
1122 while (*s != '\0') {
1131 return(dlen + (s - src)); /* count does not include NUL */
1133 #endif // #ifndef HAVE_STRLCAT
1136 #ifndef HAVE_STRLCPY
1138 strlcpy(char *dst, const char *src, size_t siz)
1140 register char *d = dst;
1141 register const char *s = src;
1142 register size_t n = siz;
1144 /* Copy as many bytes as will fit */
1145 if (n != 0 && --n != 0) {
1147 if ((*d++ = *s++) == 0)
1152 /* Not enough room in dst, add NUL and traverse rest of src */
1155 *d = '\0'; /* NUL-terminate dst */
1160 return(s - src - 1); /* count does not include NUL */
1163 #endif // #ifndef HAVE_STRLCPY