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;)
412 *cur++ = hexchar[(i >> 12) & 15];
413 *cur++ = hexchar[(i >> 8) & 15];
414 *cur++ = hexchar[(i >> 4) & 15];
415 *cur++ = hexchar[(i >> 0) & 15];
418 for (j = 0;j < 16;j++)
422 *cur++ = hexchar[(d[j] >> 4) & 15];
423 *cur++ = hexchar[(d[j] >> 0) & 15];
434 for (j = 0;j < 16;j++)
438 if (d[j] >= ' ' && d[j] <= 127)
448 if (cur >= flushpointer || i >= size)
457 void SZ_HexDumpToConsole(const sizebuf_t *buf)
459 Com_HexDumpToConsole(buf->data, buf->cursize);
463 //============================================================================
470 Parse a token out of a string
473 int COM_ParseToken(const char **datapointer, int returnnewline)
476 const char *data = *datapointer;
489 for (;*data <= ' ' && (*data != '\n' || !returnnewline);data++)
499 if (data[0] == '/' && data[1] == '/')
502 while (*data && *data != '\n')
506 else if (data[0] == '/' && data[1] == '*')
510 while (*data && (data[0] != '*' || data[1] != '/'))
515 else if (*data == '\"')
518 for (data++;*data != '\"';data++)
520 if (!*data || len >= (int)sizeof(com_token) - 1)
526 com_token[len++] = *data;
529 *datapointer = data+1;
532 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == '\'' || *data == ':' || *data == ',' || *data == ';')
535 com_token[len++] = *data++;
543 for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != '\'' && *data != ':' && *data != ',' && *data != ';';data++)
545 if (len >= (int)sizeof(com_token) - 1)
551 com_token[len++] = *data;
561 COM_ParseTokenConsole
563 Parse a token out of a string, behaving like the qwcl console
566 int COM_ParseTokenConsole(const char **datapointer)
569 const char *data = *datapointer;
582 for (;*data <= ' ';data++)
592 if (*data == '/' && data[1] == '/')
595 while (*data && *data != '\n')
599 else if (*data == '\"')
602 for (data++;*data != '\"';data++)
604 if (!*data || len >= (int)sizeof(com_token) - 1)
610 com_token[len++] = *data;
613 *datapointer = data+1;
619 for (;*data > ' ';data++)
621 if (len >= (int)sizeof(com_token) - 1)
627 com_token[len++] = *data;
640 Returns the position (1 to argc-1) in the program's argument list
641 where the given parameter apears, or 0 if not present
644 int COM_CheckParm (const char *parm)
648 for (i=1 ; i<com_argc ; i++)
651 continue; // NEXTSTEP sometimes clears appkit vars.
652 if (!strcmp (parm,com_argv[i]))
663 Looks for the pop.txt file and verifies it.
664 Sets the "registered" cvar.
665 Immediately exits out if an alternate game was attempted to be started without
669 void COM_CheckRegistered (void)
671 Cvar_Set ("cmdline", com_cmdline);
673 if (!FS_FileExists("gfx/pop.lmp"))
676 Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
678 Con_Print("Playing shareware version.\n");
682 Cvar_Set ("registered", "1");
683 Con_Print("Playing registered version.\n");
692 void COM_InitArgv (void)
695 // reconstitute the command line for the cmdline externally visible cvar
697 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
700 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
701 com_cmdline[n++] = com_argv[j][i++];
702 if (n < (CMDLINE_LENGTH - 1))
703 com_cmdline[n++] = ' ';
710 void COM_InitGameType (void)
712 char name[MAX_OSPATH];
713 FS_StripExtension (com_argv[0], name, sizeof (name));
714 COM_ToLowerString (name, name, sizeof (name));
716 if (strstr(name, "transfusion"))
717 gamemode = GAME_TRANSFUSION;
718 else if (strstr(name, "nexuiz"))
719 gamemode = GAME_NEXUIZ;
720 else if (strstr(name, "nehahra"))
721 gamemode = GAME_NEHAHRA;
722 else if (strstr(name, "hipnotic"))
723 gamemode = GAME_HIPNOTIC;
724 else if (strstr(name, "rogue"))
725 gamemode = GAME_ROGUE;
726 else if (strstr(name, "gvb2"))
727 gamemode = GAME_GOODVSBAD2;
728 else if (strstr(name, "teu"))
730 else if (strstr(name, "battlemech"))
731 gamemode = GAME_BATTLEMECH;
732 else if (strstr(name, "zymotic"))
733 gamemode = GAME_ZYMOTIC;
734 else if (strstr(name, "fniggium"))
735 gamemode = GAME_FNIGGIUM;
736 else if (strstr(name, "setheral"))
737 gamemode = GAME_SETHERAL;
738 else if (strstr(name, "som"))
740 else if (strstr(name, "tenebrae"))
741 gamemode = GAME_TENEBRAE;
743 gamemode = GAME_NORMAL;
745 if (COM_CheckParm ("-transfusion"))
746 gamemode = GAME_TRANSFUSION;
747 else if (COM_CheckParm ("-nexuiz"))
748 gamemode = GAME_NEXUIZ;
749 else if (COM_CheckParm ("-nehahra"))
750 gamemode = GAME_NEHAHRA;
751 else if (COM_CheckParm ("-hipnotic"))
752 gamemode = GAME_HIPNOTIC;
753 else if (COM_CheckParm ("-rogue"))
754 gamemode = GAME_ROGUE;
755 else if (COM_CheckParm ("-quake"))
756 gamemode = GAME_NORMAL;
757 else if (COM_CheckParm ("-goodvsbad2"))
758 gamemode = GAME_GOODVSBAD2;
759 else if (COM_CheckParm ("-teu"))
761 else if (COM_CheckParm ("-battlemech"))
762 gamemode = GAME_BATTLEMECH;
763 else if (COM_CheckParm ("-zymotic"))
764 gamemode = GAME_ZYMOTIC;
765 else if (COM_CheckParm ("-fniggium"))
766 gamemode = GAME_FNIGGIUM;
767 else if (COM_CheckParm ("-setheral"))
768 gamemode = GAME_SETHERAL;
769 else if (COM_CheckParm ("-som"))
771 else if (COM_CheckParm ("-tenebrae"))
772 gamemode = GAME_TENEBRAE;
777 gamename = "DarkPlaces-Quake";
781 gamename = "Darkplaces-Hipnotic";
782 gamedirname = "hipnotic";
785 gamename = "Darkplaces-Rogue";
786 gamedirname = "rogue";
789 gamename = "DarkPlaces-Nehahra";
790 gamedirname = "nehahra";
794 gamedirname = "data";
796 case GAME_TRANSFUSION:
797 gamename = "Transfusion";
798 gamedirname = "basetf";
800 case GAME_GOODVSBAD2:
801 gamename = "GoodVs.Bad2";
805 gamename = "TheEvilUnleashed";
806 gamedirname = "baseteu";
808 case GAME_BATTLEMECH:
809 gamename = "Battlemech";
810 gamedirname = "base";
813 gamename = "Zymotic";
814 gamedirname = "data";
817 gamename = "Fniggium";
818 gamedirname = "data";
821 gamename = "Setheral";
822 gamedirname = "data";
825 gamename = "Son of Man";
826 gamedirname = "data";
829 gamename = "DarkPlaces-Tenebrae";
830 gamedirname = "tenebrae";
833 Sys_Error("COM_InitGameType: unknown gamemode %i\n", gamemode);
839 extern void Mathlib_Init(void);
840 extern void FS_Init (void);
849 Cvar_RegisterVariable (®istered);
850 Cvar_RegisterVariable (&cmdline);
856 COM_CheckRegistered ();
866 does a varargs printf into a temp buffer, so I don't need to have
867 varargs versions of all text functions.
868 FIXME: make this buffer size safe someday
871 char *va(const char *format, ...)
874 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
875 static char string[8][1024], *s;
876 static int stringindex = 0;
878 s = string[stringindex];
879 stringindex = (stringindex + 1) & 7;
880 va_start (argptr, format);
881 vsnprintf (s, sizeof (string[0]), format,argptr);
888 //======================================
890 void COM_ToLowerString (const char *in, char *out, size_t size_out)
895 while (*in && size_out > 1)
897 if (*in >= 'A' && *in <= 'Z')
898 *out++ = *in++ + 'a' - 'A';
906 void COM_ToUpperString (const char *in, char *out, size_t size_out)
911 while (*in && size_out > 1)
913 if (*in >= 'a' && *in <= 'z')
914 *out++ = *in++ + 'A' - 'a';
922 int COM_StringBeginsWith(const char *s, const char *match)
924 for (;*s && *match;s++, match++)
930 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
932 int argc, commentprefixlength;
936 tokenbufend = tokenbuf + tokenbufsize;
938 commentprefixlength = 0;
940 commentprefixlength = strlen(commentprefix);
941 while (*l && *l != '\n')
945 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
947 while (*l && *l != '\n')
953 argv[argc++] = tokenbuf;
957 while (*l && *l != '"')
959 if (tokenbuf >= tokenbufend)
970 if (tokenbuf >= tokenbufend)
975 if (tokenbuf >= tokenbufend)
988 // written by Elric, thanks Elric!
989 char *SearchInfostring(const char *infostring, const char *key)
991 static char value [256];
993 size_t value_ind, key_ind;
996 if (*infostring++ != '\\')
1011 if (c == '\\' || key_ind == sizeof (crt_key) - 1)
1013 crt_key[key_ind] = '\0';
1017 crt_key[key_ind++] = c;
1020 // If it's the key we are looking for, save it in "value"
1021 if (!strcmp(crt_key, key))
1027 if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
1029 value[value_ind] = '\0';
1033 value[value_ind++] = c;
1037 // Else, skip the value
1051 //========================================================
1052 // strlcat and strlcpy, from OpenBSD
1055 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1057 * Permission to use, copy, modify, and distribute this software for any
1058 * purpose with or without fee is hereby granted, provided that the above
1059 * copyright notice and this permission notice appear in all copies.
1061 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1062 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1063 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1064 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1065 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1066 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1067 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1070 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
1071 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
1074 #ifndef HAVE_STRLCAT
1076 strlcat(char *dst, const char *src, size_t siz)
1078 register char *d = dst;
1079 register const char *s = src;
1080 register size_t n = siz;
1083 /* Find the end of dst and adjust bytes left but don't go past end */
1084 while (n-- != 0 && *d != '\0')
1090 return(dlen + strlen(s));
1091 while (*s != '\0') {
1100 return(dlen + (s - src)); /* count does not include NUL */
1102 #endif // #ifndef HAVE_STRLCAT
1105 #ifndef HAVE_STRLCPY
1107 strlcpy(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;
1113 /* Copy as many bytes as will fit */
1114 if (n != 0 && --n != 0) {
1116 if ((*d++ = *s++) == 0)
1121 /* Not enough room in dst, add NUL and traverse rest of src */
1124 *d = '\0'; /* NUL-terminate dst */
1129 return(s - src - 1); /* count does not include NUL */
1132 #endif // #ifndef HAVE_STRLCPY