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 dpprotocol)
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_ReadShort (void)
264 if (msg_readcount+2 > net_message.cursize)
270 c = (short)(net_message.data[msg_readcount]
271 + (net_message.data[msg_readcount+1]<<8));
278 int MSG_ReadLong (void)
282 if (msg_readcount+4 > net_message.cursize)
288 c = net_message.data[msg_readcount]
289 + (net_message.data[msg_readcount+1]<<8)
290 + (net_message.data[msg_readcount+2]<<16)
291 + (net_message.data[msg_readcount+3]<<24);
298 float MSG_ReadFloat (void)
307 dat.b[0] = net_message.data[msg_readcount];
308 dat.b[1] = net_message.data[msg_readcount+1];
309 dat.b[2] = net_message.data[msg_readcount+2];
310 dat.b[3] = net_message.data[msg_readcount+3];
313 dat.l = LittleLong (dat.l);
318 char *MSG_ReadString (void)
320 static char string[2048];
327 if (c == -1 || c == 0)
331 } while (l < (int)sizeof(string)-1);
338 // used by server (always latest dpprotocol)
339 float MSG_ReadDPCoord (void)
341 return (signed short) MSG_ReadShort();
345 float MSG_ReadCoord (void)
347 if (dpprotocol == DPPROTOCOL_VERSION2 || dpprotocol == DPPROTOCOL_VERSION3)
348 return (signed short) MSG_ReadShort();
349 else if (dpprotocol == DPPROTOCOL_VERSION1)
350 return MSG_ReadFloat();
352 return MSG_ReadShort() * (1.0f/8.0f);
356 //===========================================================================
358 void SZ_Alloc (sizebuf_t *buf, int startsize, const char *name)
362 buf->mempool = Mem_AllocPool(name);
363 buf->data = Mem_Alloc(buf->mempool, startsize);
364 buf->maxsize = startsize;
369 void SZ_Free (sizebuf_t *buf)
371 Mem_FreePool(&buf->mempool);
377 void SZ_Clear (sizebuf_t *buf)
382 void *SZ_GetSpace (sizebuf_t *buf, int length)
386 if (buf->cursize + length > buf->maxsize)
388 if (!buf->allowoverflow)
389 Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n");
391 if (length > buf->maxsize)
392 Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length);
394 buf->overflowed = true;
395 Con_Printf ("SZ_GetSpace: overflow\n");
399 data = buf->data + buf->cursize;
400 buf->cursize += length;
405 void SZ_Write (sizebuf_t *buf, const void *data, int length)
407 memcpy (SZ_GetSpace(buf,length),data,length);
410 void SZ_Print (sizebuf_t *buf, const char *data)
413 len = strlen(data)+1;
415 // byte * cast to keep VC++ happy
416 if (buf->data[buf->cursize-1])
417 memcpy ((qbyte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
419 memcpy ((qbyte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
422 static char *hexchar = "0123456789ABCDEF";
423 void Com_HexDumpToConsole(const qbyte *data, int size)
427 char *cur, *flushpointer;
430 flushpointer = text + 512;
431 for (i = 0;i < size;)
437 *cur++ = hexchar[(i >> 12) & 15];
438 *cur++ = hexchar[(i >> 8) & 15];
439 *cur++ = hexchar[(i >> 4) & 15];
440 *cur++ = hexchar[(i >> 0) & 15];
442 for (j = 0;j < n;j++)
446 *cur++ = hexchar[(d[j] >> 4) & 15] | 0x80;
447 *cur++ = hexchar[(d[j] >> 0) & 15] | 0x80;
451 *cur++ = hexchar[(d[j] >> 4) & 15];
452 *cur++ = hexchar[(d[j] >> 0) & 15];
460 for (j = 0;j < n;j++)
461 *cur++ = (d[j] >= ' ' && d[j] <= 0x7E) ? d[j] : '.';
466 if (cur >= flushpointer || i >= size)
469 Con_Printf("%s", text);
475 void SZ_HexDumpToConsole(const sizebuf_t *buf)
477 Com_HexDumpToConsole(buf->data, buf->cursize);
481 //============================================================================
488 Parse a token out of a string
491 int COM_ParseToken (const char **datapointer)
495 const char *data = *datapointer;
508 while ((c = *data) <= ' ')
520 if (c=='/' && data[1] == '/')
522 while (*data && *data != '\n')
528 // handle quoted strings specially
546 // parse single characters
547 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
552 *datapointer = data+1;
556 // parse a regular word
563 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
577 Returns the position (1 to argc-1) in the program's argument list
578 where the given parameter apears, or 0 if not present
581 int COM_CheckParm (const char *parm)
585 for (i=1 ; i<com_argc ; i++)
588 continue; // NEXTSTEP sometimes clears appkit vars.
589 if (!strcmp (parm,com_argv[i]))
600 Looks for the pop.txt file and verifies it.
601 Sets the "registered" cvar.
602 Immediately exits out if an alternate game was attempted to be started without
606 void COM_CheckRegistered (void)
608 Cvar_Set ("cmdline", com_cmdline);
610 if (!FS_FileExists("gfx/pop.lmp"))
613 Con_Printf ("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
615 Con_Printf ("Playing shareware version.\n");
619 Cvar_Set ("registered", "1");
620 Con_Printf ("Playing registered version.\n");
629 void COM_InitArgv (void)
632 // reconstitute the command line for the cmdline externally visible cvar
634 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
637 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
638 com_cmdline[n++] = com_argv[j][i++];
639 if (n < (CMDLINE_LENGTH - 1))
640 com_cmdline[n++] = ' ';
647 void COM_InitGameType (void)
649 char name[MAX_OSPATH];
650 FS_StripExtension(com_argv[0], name);
651 COM_ToLowerString(name, name);
653 if (strstr(name, "transfusion"))
654 gamemode = GAME_TRANSFUSION;
655 else if (strstr(name, "nexiuz"))
656 gamemode = GAME_NEXIUZ;
657 else if (strstr(name, "nehahra"))
658 gamemode = GAME_NEHAHRA;
659 else if (strstr(name, "hipnotic"))
660 gamemode = GAME_HIPNOTIC;
661 else if (strstr(name, "rogue"))
662 gamemode = GAME_ROGUE;
664 gamemode = GAME_NORMAL;
666 if (COM_CheckParm ("-transfusion"))
667 gamemode = GAME_TRANSFUSION;
668 else if (COM_CheckParm ("-nexiuz"))
669 gamemode = GAME_NEXIUZ;
670 else if (COM_CheckParm ("-nehahra"))
671 gamemode = GAME_NEHAHRA;
672 else if (COM_CheckParm ("-hipnotic"))
673 gamemode = GAME_HIPNOTIC;
674 else if (COM_CheckParm ("-rogue"))
675 gamemode = GAME_ROGUE;
676 else if (COM_CheckParm ("-quake"))
677 gamemode = GAME_NORMAL;
682 gamename = "DarkPlaces-Quake";
686 gamename = "Darkplaces-Hipnotic";
687 gamedirname = "hipnotic";
690 gamename = "Darkplaces-Rogue";
691 gamedirname = "rogue";
694 gamename = "DarkPlaces-Nehahra";
695 gamedirname = "nehahra";
699 gamedirname = "data";
701 case GAME_TRANSFUSION:
702 gamename = "Transfusion";
703 gamedirname = "transfusion";
706 Sys_Error("COM_InitGameType: unknown gamemode %i\n", gamemode);
712 extern void Mathlib_Init(void);
713 extern void FS_Init (void);
722 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
723 qbyte swaptest[2] = {1,0};
725 // set the byte swapping variables in a portable manner
726 if ( *(short *)swaptest == 1)
728 BigShort = ShortSwap;
729 LittleShort = ShortNoSwap;
731 LittleLong = LongNoSwap;
732 BigFloat = FloatSwap;
733 LittleFloat = FloatNoSwap;
737 BigShort = ShortNoSwap;
738 LittleShort = ShortSwap;
739 BigLong = LongNoSwap;
740 LittleLong = LongSwap;
741 BigFloat = FloatNoSwap;
742 LittleFloat = FloatSwap;
746 Cvar_RegisterVariable (®istered);
747 Cvar_RegisterVariable (&cmdline);
752 COM_CheckRegistered ();
762 does a varargs printf into a temp buffer, so I don't need to have
763 varargs versions of all text functions.
764 FIXME: make this buffer size safe someday
767 char *va(const char *format, ...)
770 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
771 static char string[8][1024], *s;
772 static int stringindex = 0;
774 s = string[stringindex];
775 stringindex = (stringindex + 1) & 7;
776 va_start (argptr, format);
777 vsprintf (s, format,argptr);
784 //======================================
785 // LordHavoc: added these because they are useful
787 void COM_ToLowerString(const char *in, char *out)
791 if (*in >= 'A' && *in <= 'Z')
792 *out++ = *in++ + 'a' - 'A';
798 void COM_ToUpperString(const char *in, char *out)
802 if (*in >= 'a' && *in <= 'z')
803 *out++ = *in++ + 'A' - 'a';
809 int COM_StringBeginsWith(const char *s, const char *match)
811 for (;*s && *match;s++, match++)