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 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
58 short (*BigShort) (short l);
59 short (*LittleShort) (short l);
60 int (*BigLong) (int l);
61 int (*LittleLong) (int l);
62 float (*BigFloat) (float l);
63 float (*LittleFloat) (float l);
66 short ShortSwap (short l)
76 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
77 short ShortNoSwap (short l)
92 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
95 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
96 int LongNoSwap (int l)
102 float FloatSwap (float f)
112 dat2.b[0] = dat1.b[3];
113 dat2.b[1] = dat1.b[2];
114 dat2.b[2] = dat1.b[1];
115 dat2.b[3] = dat1.b[0];
119 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
120 float FloatNoSwap (float f)
127 // Extract integers from buffers
129 unsigned int BuffBigLong (const qbyte *buffer)
131 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
134 unsigned short BuffBigShort (const qbyte *buffer)
136 return (buffer[0] << 8) | buffer[1];
139 unsigned int BuffLittleLong (const qbyte *buffer)
141 return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
144 unsigned short BuffLittleShort (const qbyte *buffer)
146 return (buffer[1] << 8) | buffer[0];
151 ==============================================================================
155 Handles byte ordering and avoids alignment errors
156 ==============================================================================
163 void MSG_WriteChar (sizebuf_t *sb, int c)
167 buf = SZ_GetSpace (sb, 1);
171 void MSG_WriteByte (sizebuf_t *sb, int c)
175 buf = SZ_GetSpace (sb, 1);
179 void MSG_WriteShort (sizebuf_t *sb, int c)
183 buf = SZ_GetSpace (sb, 2);
188 void MSG_WriteLong (sizebuf_t *sb, int c)
192 buf = SZ_GetSpace (sb, 4);
194 buf[1] = (c>>8)&0xff;
195 buf[2] = (c>>16)&0xff;
199 void MSG_WriteFloat (sizebuf_t *sb, float f)
209 dat.l = LittleLong (dat.l);
211 SZ_Write (sb, &dat.l, 4);
214 void MSG_WriteString (sizebuf_t *sb, const char *s)
217 SZ_Write (sb, "", 1);
219 SZ_Write (sb, s, strlen(s)+1);
222 // used by server (always latest PROTOCOL_DARKPLACES)
223 void MSG_WriteDPCoord (sizebuf_t *sb, float f)
226 MSG_WriteShort (sb, (int)(f + 0.5f));
228 MSG_WriteShort (sb, (int)(f - 0.5f));
231 void MSG_WritePreciseAngle (sizebuf_t *sb, float f)
234 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
236 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) - 0.5f) & 65535);
239 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
240 void MSG_WriteAngle (sizebuf_t *sb, float f)
243 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
245 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) - 0.5f) & 255);
252 qboolean msg_badread;
254 void MSG_BeginReading (void)
260 int MSG_ReadLittleShort (void)
262 if (msg_readcount+2 > net_message.cursize)
268 return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
271 int MSG_ReadBigShort (void)
273 if (msg_readcount+2 > net_message.cursize)
279 return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
282 int MSG_ReadLittleLong (void)
284 if (msg_readcount+4 > net_message.cursize)
290 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);
293 int MSG_ReadBigLong (void)
295 if (msg_readcount+4 > net_message.cursize)
301 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];
304 float MSG_ReadLittleFloat (void)
311 if (msg_readcount+4 > net_message.cursize)
317 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);
321 float MSG_ReadBigFloat (void)
328 if (msg_readcount+4 > net_message.cursize)
334 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];
338 char *MSG_ReadString (void)
340 static char string[2048];
342 for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadChar()) != -1 && c != 0;l++)
348 int MSG_ReadBytes (int numbytes, unsigned char *out)
351 for (l = 0;l < numbytes && (c = MSG_ReadChar()) != -1;l++)
356 // used by server (always latest PROTOCOL_DARKPLACES)
357 float MSG_ReadDPCoord (void)
359 return (signed short) MSG_ReadLittleShort();
363 float MSG_ReadCoord (void)
365 if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
366 return (signed short) MSG_ReadLittleShort();
367 else if (cl.protocol == PROTOCOL_DARKPLACES1)
368 return MSG_ReadLittleFloat();
370 return MSG_ReadLittleShort() * (1.0f/8.0f);
374 //===========================================================================
376 void SZ_Alloc (sizebuf_t *buf, int startsize, const char *name)
380 buf->mempool = Mem_AllocPool(name);
381 buf->data = Mem_Alloc(buf->mempool, startsize);
382 buf->maxsize = startsize;
387 void SZ_Free (sizebuf_t *buf)
389 Mem_FreePool(&buf->mempool);
395 void SZ_Clear (sizebuf_t *buf)
400 void *SZ_GetSpace (sizebuf_t *buf, int length)
404 if (buf->cursize + length > buf->maxsize)
406 if (!buf->allowoverflow)
407 Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n");
409 if (length > buf->maxsize)
410 Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length);
412 buf->overflowed = true;
413 Con_Printf ("SZ_GetSpace: overflow\n");
417 data = buf->data + buf->cursize;
418 buf->cursize += length;
423 void SZ_Write (sizebuf_t *buf, const void *data, int length)
425 memcpy (SZ_GetSpace(buf,length),data,length);
428 // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
429 // attention, it has been eradicated from here, its only (former) use in
430 // all of darkplaces.
432 static char *hexchar = "0123456789ABCDEF";
433 void Com_HexDumpToConsole(const qbyte *data, int size)
437 char *cur, *flushpointer;
440 flushpointer = text + 512;
441 for (i = 0;i < size;)
447 *cur++ = hexchar[(i >> 12) & 15];
448 *cur++ = hexchar[(i >> 8) & 15];
449 *cur++ = hexchar[(i >> 4) & 15];
450 *cur++ = hexchar[(i >> 0) & 15];
452 for (j = 0;j < n;j++)
456 *cur++ = hexchar[(d[j] >> 4) & 15] | 0x80;
457 *cur++ = hexchar[(d[j] >> 0) & 15] | 0x80;
461 *cur++ = hexchar[(d[j] >> 4) & 15];
462 *cur++ = hexchar[(d[j] >> 0) & 15];
470 for (j = 0;j < n;j++)
471 *cur++ = (d[j] >= ' ' && d[j] <= 0x7E) ? d[j] : '.';
476 if (cur >= flushpointer || i >= size)
479 Con_Printf("%s", text);
485 void SZ_HexDumpToConsole(const sizebuf_t *buf)
487 Com_HexDumpToConsole(buf->data, buf->cursize);
491 //============================================================================
498 Parse a token out of a string
501 int COM_ParseToken(const char **datapointer, int returnnewline)
505 const char *data = *datapointer;
518 while ((c = *data) <= ' ' && (c != '\n' || !returnnewline))
529 // check if it's a comment
535 while (*data && *data != '\n')
542 while (*data && (*data != '*' || data[1] != '/'))
549 // handle quoted strings specially
567 // parse single characters
568 if (c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';' || c == '\n')
573 *datapointer = data+1;
577 // parse a regular word
584 if (c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';')
595 COM_ParseTokenConsole
597 Parse a token out of a string, behaving like the qwcl console
600 int COM_ParseTokenConsole(const char **datapointer)
604 const char *data = *datapointer;
617 while ((c = *data) <= ' ')
629 if (c == '/' && data[1] == '/')
631 while (*data && *data != '\n')
636 // handle quoted strings specially
654 // parse a regular word
673 Returns the position (1 to argc-1) in the program's argument list
674 where the given parameter apears, or 0 if not present
677 int COM_CheckParm (const char *parm)
681 for (i=1 ; i<com_argc ; i++)
684 continue; // NEXTSTEP sometimes clears appkit vars.
685 if (!strcmp (parm,com_argv[i]))
696 Looks for the pop.txt file and verifies it.
697 Sets the "registered" cvar.
698 Immediately exits out if an alternate game was attempted to be started without
702 void COM_CheckRegistered (void)
704 Cvar_Set ("cmdline", com_cmdline);
706 if (!FS_FileExists("gfx/pop.lmp"))
709 Con_Printf ("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
711 Con_Printf ("Playing shareware version.\n");
715 Cvar_Set ("registered", "1");
716 Con_Printf ("Playing registered version.\n");
725 void COM_InitArgv (void)
728 // reconstitute the command line for the cmdline externally visible cvar
730 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
733 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
734 com_cmdline[n++] = com_argv[j][i++];
735 if (n < (CMDLINE_LENGTH - 1))
736 com_cmdline[n++] = ' ';
743 void COM_InitGameType (void)
745 char name[MAX_OSPATH];
746 FS_StripExtension (com_argv[0], name, sizeof (name));
747 COM_ToLowerString (name, name, sizeof (name));
749 if (strstr(name, "transfusion"))
750 gamemode = GAME_TRANSFUSION;
751 else if (strstr(name, "nexuiz"))
752 gamemode = GAME_NEXUIZ;
753 else if (strstr(name, "nehahra"))
754 gamemode = GAME_NEHAHRA;
755 else if (strstr(name, "hipnotic"))
756 gamemode = GAME_HIPNOTIC;
757 else if (strstr(name, "rogue"))
758 gamemode = GAME_ROGUE;
759 else if (strstr(name, "gvb2"))
760 gamemode = GAME_GOODVSBAD2;
761 else if (strstr(name, "teu"))
763 else if (strstr(name, "battlemech"))
764 gamemode = GAME_BATTLEMECH;
765 else if (strstr(name, "zymotic"))
766 gamemode = GAME_ZYMOTIC;
767 else if (strstr(name, "fniggium"))
768 gamemode = GAME_FNIGGIUM;
769 else if (strstr(name, "setheral"))
770 gamemode = GAME_SETHERAL;
771 else if (strstr(name, "som"))
774 gamemode = GAME_NORMAL;
776 if (COM_CheckParm ("-transfusion"))
777 gamemode = GAME_TRANSFUSION;
778 else if (COM_CheckParm ("-nexuiz"))
779 gamemode = GAME_NEXUIZ;
780 else if (COM_CheckParm ("-nehahra"))
781 gamemode = GAME_NEHAHRA;
782 else if (COM_CheckParm ("-hipnotic"))
783 gamemode = GAME_HIPNOTIC;
784 else if (COM_CheckParm ("-rogue"))
785 gamemode = GAME_ROGUE;
786 else if (COM_CheckParm ("-quake"))
787 gamemode = GAME_NORMAL;
788 else if (COM_CheckParm ("-goodvsbad2"))
789 gamemode = GAME_GOODVSBAD2;
790 else if (COM_CheckParm ("-teu"))
792 else if (COM_CheckParm ("-battlemech"))
793 gamemode = GAME_BATTLEMECH;
794 else if (COM_CheckParm ("-zymotic"))
795 gamemode = GAME_ZYMOTIC;
796 else if (COM_CheckParm ("-fniggium"))
797 gamemode = GAME_FNIGGIUM;
798 else if (COM_CheckParm ("-setheral"))
799 gamemode = GAME_SETHERAL;
800 else if (COM_CheckParm ("-som"))
806 gamename = "DarkPlaces-Quake";
810 gamename = "Darkplaces-Hipnotic";
811 gamedirname = "hipnotic";
814 gamename = "Darkplaces-Rogue";
815 gamedirname = "rogue";
818 gamename = "DarkPlaces-Nehahra";
819 gamedirname = "nehahra";
823 gamedirname = "data";
825 case GAME_TRANSFUSION:
826 gamename = "Transfusion";
827 gamedirname = "transfusion";
829 case GAME_GOODVSBAD2:
830 gamename = "GoodVs.Bad2";
834 gamename = "TheEvilUnleashed";
835 gamedirname = "baseteu";
837 case GAME_BATTLEMECH:
838 gamename = "Battlemech";
839 gamedirname = "base";
842 gamename = "Zymotic";
843 gamedirname = "data";
846 gamename = "Fniggium";
847 gamedirname = "data";
850 gamename = "Setheral";
851 gamedirname = "data";
854 gamename = "Son of Man";
855 gamedirname = "data";
858 Sys_Error("COM_InitGameType: unknown gamemode %i\n", gamemode);
864 extern void Mathlib_Init(void);
865 extern void FS_Init (void);
874 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
875 qbyte swaptest[2] = {1,0};
877 // set the byte swapping variables in a portable manner
878 if ( *(short *)swaptest == 1)
880 BigShort = ShortSwap;
881 LittleShort = ShortNoSwap;
883 LittleLong = LongNoSwap;
884 BigFloat = FloatSwap;
885 LittleFloat = FloatNoSwap;
889 BigShort = ShortNoSwap;
890 LittleShort = ShortSwap;
891 BigLong = LongNoSwap;
892 LittleLong = LongSwap;
893 BigFloat = FloatNoSwap;
894 LittleFloat = FloatSwap;
898 Cvar_RegisterVariable (®istered);
899 Cvar_RegisterVariable (&cmdline);
905 COM_CheckRegistered ();
915 does a varargs printf into a temp buffer, so I don't need to have
916 varargs versions of all text functions.
917 FIXME: make this buffer size safe someday
920 char *va(const char *format, ...)
923 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
924 static char string[8][1024], *s;
925 static int stringindex = 0;
927 s = string[stringindex];
928 stringindex = (stringindex + 1) & 7;
929 va_start (argptr, format);
930 vsnprintf (s, sizeof (string[0]), format,argptr);
937 //======================================
939 void COM_ToLowerString (const char *in, char *out, size_t size_out)
944 while (*in && size_out > 1)
946 if (*in >= 'A' && *in <= 'Z')
947 *out++ = *in++ + 'a' - 'A';
955 void COM_ToUpperString (const char *in, char *out, size_t size_out)
960 while (*in && size_out > 1)
962 if (*in >= 'a' && *in <= 'z')
963 *out++ = *in++ + 'A' - 'a';
971 int COM_StringBeginsWith(const char *s, const char *match)
973 for (;*s && *match;s++, match++)
979 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
981 int argc, commentprefixlength;
985 tokenbufend = tokenbuf + tokenbufsize;
987 commentprefixlength = 0;
989 commentprefixlength = strlen(commentprefix);
990 while (*l && *l != '\n')
994 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
996 while (*l && *l != '\n')
1000 if (argc >= maxargc)
1002 argv[argc++] = tokenbuf;
1006 while (*l && *l != '"')
1008 if (tokenbuf >= tokenbufend)
1019 if (tokenbuf >= tokenbufend)
1024 if (tokenbuf >= tokenbufend)
1037 // written by Elric, thanks Elric!
1038 char *SearchInfostring(const char *infostring, const char *key)
1040 static char value [256];
1042 size_t value_ind, key_ind;
1045 if (*infostring++ != '\\')
1060 if (c == '\\' || key_ind == sizeof (crt_key) - 1)
1062 crt_key[key_ind] = '\0';
1066 crt_key[key_ind++] = c;
1069 // If it's the key we are looking for, save it in "value"
1070 if (!strcmp(crt_key, key))
1076 if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
1078 value[value_ind] = '\0';
1082 value[value_ind++] = c;
1086 // Else, skip the value
1100 //========================================================
1101 // strlcat and strlcpy, from OpenBSD
1104 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1106 * Permission to use, copy, modify, and distribute this software for any
1107 * purpose with or without fee is hereby granted, provided that the above
1108 * copyright notice and this permission notice appear in all copies.
1110 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1111 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1112 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1113 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1114 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1115 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1116 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1119 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
1120 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
1123 // Most (all?) BSDs already have them
1124 #if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__)
1127 strlcat(char *dst, const char *src, size_t siz)
1129 register char *d = dst;
1130 register const char *s = src;
1131 register size_t n = siz;
1134 /* Find the end of dst and adjust bytes left but don't go past end */
1135 while (n-- != 0 && *d != '\0')
1141 return(dlen + strlen(s));
1142 while (*s != '\0') {
1151 return(dlen + (s - src)); /* count does not include NUL */
1155 strlcpy(char *dst, const char *src, size_t siz)
1157 register char *d = dst;
1158 register const char *s = src;
1159 register size_t n = siz;
1161 /* Copy as many bytes as will fit */
1162 if (n != 0 && --n != 0) {
1164 if ((*d++ = *s++) == 0)
1169 /* Not enough room in dst, add NUL and traverse rest of src */
1172 *d = '\0'; /* NUL-terminate dst */
1177 return(s - src - 1); /* count does not include NUL */
1180 #endif // #if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__)