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 ==============================================================================
131 Handles byte ordering and avoids alignment errors
132 ==============================================================================
139 void MSG_WriteChar (sizebuf_t *sb, int c)
143 buf = SZ_GetSpace (sb, 1);
147 void MSG_WriteByte (sizebuf_t *sb, int c)
151 buf = SZ_GetSpace (sb, 1);
155 void MSG_WriteShort (sizebuf_t *sb, int c)
159 buf = SZ_GetSpace (sb, 2);
164 void MSG_WriteLong (sizebuf_t *sb, int c)
168 buf = SZ_GetSpace (sb, 4);
170 buf[1] = (c>>8)&0xff;
171 buf[2] = (c>>16)&0xff;
175 void MSG_WriteFloat (sizebuf_t *sb, float f)
185 dat.l = LittleLong (dat.l);
187 SZ_Write (sb, &dat.l, 4);
190 void MSG_WriteString (sizebuf_t *sb, const char *s)
193 SZ_Write (sb, "", 1);
195 SZ_Write (sb, s, strlen(s)+1);
198 // used by server (always latest dpprotocol)
199 void MSG_WriteDPCoord (sizebuf_t *sb, float f)
202 MSG_WriteShort (sb, (int)(f + 0.5f));
204 MSG_WriteShort (sb, (int)(f - 0.5f));
207 void MSG_WritePreciseAngle (sizebuf_t *sb, float f)
210 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
212 MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) - 0.5f) & 65535);
215 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
216 void MSG_WriteAngle (sizebuf_t *sb, float f)
219 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
221 MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) - 0.5f) & 255);
228 qboolean msg_badread;
230 void MSG_BeginReading (void)
236 int MSG_ReadShort (void)
240 if (msg_readcount+2 > net_message.cursize)
246 c = (short)(net_message.data[msg_readcount]
247 + (net_message.data[msg_readcount+1]<<8));
254 int MSG_ReadLong (void)
258 if (msg_readcount+4 > net_message.cursize)
264 c = net_message.data[msg_readcount]
265 + (net_message.data[msg_readcount+1]<<8)
266 + (net_message.data[msg_readcount+2]<<16)
267 + (net_message.data[msg_readcount+3]<<24);
274 float MSG_ReadFloat (void)
283 dat.b[0] = net_message.data[msg_readcount];
284 dat.b[1] = net_message.data[msg_readcount+1];
285 dat.b[2] = net_message.data[msg_readcount+2];
286 dat.b[3] = net_message.data[msg_readcount+3];
289 dat.l = LittleLong (dat.l);
294 char *MSG_ReadString (void)
296 static char string[2048];
303 if (c == -1 || c == 0)
307 } while (l < (int)sizeof(string)-1);
314 // used by server (always latest dpprotocol)
315 float MSG_ReadDPCoord (void)
317 return (signed short) MSG_ReadShort();
321 float MSG_ReadCoord (void)
323 if (dpprotocol == DPPROTOCOL_VERSION2 || dpprotocol == DPPROTOCOL_VERSION3)
324 return (signed short) MSG_ReadShort();
325 else if (dpprotocol == DPPROTOCOL_VERSION1)
326 return MSG_ReadFloat();
328 return MSG_ReadShort() * (1.0f/8.0f);
332 //===========================================================================
334 void SZ_Alloc (sizebuf_t *buf, int startsize, const char *name)
338 buf->mempool = Mem_AllocPool(name);
339 buf->data = Mem_Alloc(buf->mempool, startsize);
340 buf->maxsize = startsize;
345 void SZ_Free (sizebuf_t *buf)
347 Mem_FreePool(&buf->mempool);
353 void SZ_Clear (sizebuf_t *buf)
358 void *SZ_GetSpace (sizebuf_t *buf, int length)
362 if (buf->cursize + length > buf->maxsize)
364 if (!buf->allowoverflow)
365 Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n");
367 if (length > buf->maxsize)
368 Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length);
370 buf->overflowed = true;
371 Con_Printf ("SZ_GetSpace: overflow\n");
375 data = buf->data + buf->cursize;
376 buf->cursize += length;
381 void SZ_Write (sizebuf_t *buf, const void *data, int length)
383 memcpy (SZ_GetSpace(buf,length),data,length);
386 void SZ_Print (sizebuf_t *buf, const char *data)
389 len = strlen(data)+1;
391 // byte * cast to keep VC++ happy
392 if (buf->data[buf->cursize-1])
393 memcpy ((qbyte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
395 memcpy ((qbyte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
398 static char *hexchar = "0123456789ABCDEF";
399 void Com_HexDumpToConsole(const qbyte *data, int size)
403 char *cur, *flushpointer;
406 flushpointer = text + 512;
407 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];
418 for (j = 0;j < n;j++)
422 *cur++ = hexchar[(d[j] >> 4) & 15] | 0x80;
423 *cur++ = hexchar[(d[j] >> 0) & 15] | 0x80;
427 *cur++ = hexchar[(d[j] >> 4) & 15];
428 *cur++ = hexchar[(d[j] >> 0) & 15];
436 for (j = 0;j < n;j++)
437 *cur++ = (d[j] >= ' ' && d[j] <= 0x7E) ? d[j] : '.';
442 if (cur >= flushpointer || i >= size)
445 Con_Printf("%s", text);
451 void SZ_HexDumpToConsole(const sizebuf_t *buf)
453 Com_HexDumpToConsole(buf->data, buf->cursize);
457 //============================================================================
464 Parse a token out of a string
467 int COM_ParseToken (const char **datapointer)
471 const char *data = *datapointer;
484 while ((c = *data) <= ' ')
496 if (c=='/' && data[1] == '/')
498 while (*data && *data != '\n')
504 // handle quoted strings specially
522 // parse single characters
523 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
528 *datapointer = data+1;
532 // parse a regular word
539 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
553 Returns the position (1 to argc-1) in the program's argument list
554 where the given parameter apears, or 0 if not present
557 int COM_CheckParm (const char *parm)
561 for (i=1 ; i<com_argc ; i++)
564 continue; // NEXTSTEP sometimes clears appkit vars.
565 if (!strcmp (parm,com_argv[i]))
576 Looks for the pop.txt file and verifies it.
577 Sets the "registered" cvar.
578 Immediately exits out if an alternate game was attempted to be started without
582 void COM_CheckRegistered (void)
584 Cvar_Set ("cmdline", com_cmdline);
586 if (!FS_FileExists("gfx/pop.lmp"))
589 Con_Printf ("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
591 Con_Printf ("Playing shareware version.\n");
595 Cvar_Set ("registered", "1");
596 Con_Printf ("Playing registered version.\n");
605 void COM_InitArgv (void)
608 // reconstitute the command line for the cmdline externally visible cvar
610 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
613 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
614 com_cmdline[n++] = com_argv[j][i++];
615 if (n < (CMDLINE_LENGTH - 1))
616 com_cmdline[n++] = ' ';
623 void COM_InitGameType (void)
625 char name[MAX_OSPATH];
626 FS_StripExtension(com_argv[0], name);
627 COM_ToLowerString(name, name);
629 if (strstr(name, "transfusion"))
630 gamemode = GAME_TRANSFUSION;
631 else if (strstr(name, "nexiuz"))
632 gamemode = GAME_NEXIUZ;
633 else if (strstr(name, "nehahra"))
634 gamemode = GAME_NEHAHRA;
635 else if (strstr(name, "hipnotic"))
636 gamemode = GAME_HIPNOTIC;
637 else if (strstr(name, "rogue"))
638 gamemode = GAME_ROGUE;
640 gamemode = GAME_NORMAL;
642 if (COM_CheckParm ("-transfusion"))
643 gamemode = GAME_TRANSFUSION;
644 else if (COM_CheckParm ("-nexiuz"))
645 gamemode = GAME_NEXIUZ;
646 else if (COM_CheckParm ("-nehahra"))
647 gamemode = GAME_NEHAHRA;
648 else if (COM_CheckParm ("-hipnotic"))
649 gamemode = GAME_HIPNOTIC;
650 else if (COM_CheckParm ("-rogue"))
651 gamemode = GAME_ROGUE;
652 else if (COM_CheckParm ("-quake"))
653 gamemode = GAME_NORMAL;
658 gamename = "DarkPlaces-Quake";
662 gamename = "Darkplaces-Hipnotic";
663 gamedirname = "hipnotic";
666 gamename = "Darkplaces-Rogue";
667 gamedirname = "rogue";
670 gamename = "DarkPlaces-Nehahra";
671 gamedirname = "nehahra";
675 gamedirname = "data";
677 case GAME_TRANSFUSION:
678 gamename = "Transfusion";
679 gamedirname = "transfusion";
682 Sys_Error("COM_InitGameType: unknown gamemode %i\n", gamemode);
688 extern void Mathlib_Init(void);
689 extern void FS_Init (void);
698 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
699 qbyte swaptest[2] = {1,0};
701 // set the byte swapping variables in a portable manner
702 if ( *(short *)swaptest == 1)
704 BigShort = ShortSwap;
705 LittleShort = ShortNoSwap;
707 LittleLong = LongNoSwap;
708 BigFloat = FloatSwap;
709 LittleFloat = FloatNoSwap;
713 BigShort = ShortNoSwap;
714 LittleShort = ShortSwap;
715 BigLong = LongNoSwap;
716 LittleLong = LongSwap;
717 BigFloat = FloatNoSwap;
718 LittleFloat = FloatSwap;
722 Cvar_RegisterVariable (®istered);
723 Cvar_RegisterVariable (&cmdline);
728 COM_CheckRegistered ();
738 does a varargs printf into a temp buffer, so I don't need to have
739 varargs versions of all text functions.
740 FIXME: make this buffer size safe someday
743 char *va(const char *format, ...)
746 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
747 static char string[8][1024], *s;
748 static int stringindex = 0;
750 s = string[stringindex];
751 stringindex = (stringindex + 1) & 7;
752 va_start (argptr, format);
753 vsprintf (s, format,argptr);
760 //======================================
761 // LordHavoc: added these because they are useful
763 void COM_ToLowerString(const char *in, char *out)
767 if (*in >= 'A' && *in <= 'Z')
768 *out++ = *in++ + 'a' - 'A';
774 void COM_ToUpperString(const char *in, char *out)
778 if (*in >= 'a' && *in <= 'z')
779 *out++ = *in++ + 'A' - 'a';
785 int COM_StringBeginsWith(const char *s, const char *match)
787 for (;*s && *match;s++, match++)