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];
45 const char *gamedirname1;
46 const char *gamedirname2;
47 const char *gamescreenshotname;
48 const char *gameuserdirname;
49 char com_modname[MAX_OSPATH] = "";
53 ============================================================================
57 ============================================================================
60 short ShortSwap (short l)
79 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
82 float FloatSwap (float f)
92 dat2.b[0] = dat1.b[3];
93 dat2.b[1] = dat1.b[2];
94 dat2.b[2] = dat1.b[1];
95 dat2.b[3] = dat1.b[0];
100 // Extract integers from buffers
102 unsigned int BuffBigLong (const qbyte *buffer)
104 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
107 unsigned short BuffBigShort (const qbyte *buffer)
109 return (buffer[0] << 8) | buffer[1];
112 unsigned int BuffLittleLong (const qbyte *buffer)
114 return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
117 unsigned short BuffLittleShort (const qbyte *buffer)
119 return (buffer[1] << 8) | buffer[0];
124 ============================================================================
128 ============================================================================
131 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
132 // and the initial and final xor values shown below... in other words, the
133 // CCITT standard CRC used by XMODEM
135 #define CRC_INIT_VALUE 0xffff
136 #define CRC_XOR_VALUE 0x0000
138 static unsigned short crctable[256] =
140 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
141 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
142 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
143 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
144 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
145 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
146 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
147 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
148 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
149 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
150 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
151 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
152 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
153 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
154 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
155 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
156 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
157 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
158 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
159 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
160 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
161 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
162 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
163 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
164 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
165 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
166 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
167 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
168 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
169 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
170 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
171 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
174 unsigned short CRC_Block(const qbyte *data, size_t size)
176 unsigned short crc = CRC_INIT_VALUE;
178 crc = (crc << 8) ^ crctable[(crc >> 8) ^ (*data++)];
179 return crc ^ CRC_XOR_VALUE;
184 ==============================================================================
188 Handles byte ordering and avoids alignment errors
189 ==============================================================================
196 void MSG_WriteChar (sizebuf_t *sb, int c)
200 buf = SZ_GetSpace (sb, 1);
204 void MSG_WriteByte (sizebuf_t *sb, int c)
208 buf = SZ_GetSpace (sb, 1);
212 void MSG_WriteShort (sizebuf_t *sb, int c)
216 buf = SZ_GetSpace (sb, 2);
221 void MSG_WriteLong (sizebuf_t *sb, int c)
225 buf = SZ_GetSpace (sb, 4);
227 buf[1] = (c>>8)&0xff;
228 buf[2] = (c>>16)&0xff;
232 void MSG_WriteFloat (sizebuf_t *sb, float f)
242 dat.l = LittleLong (dat.l);
244 SZ_Write (sb, &dat.l, 4);
247 void MSG_WriteString (sizebuf_t *sb, const char *s)
250 SZ_Write (sb, "", 1);
252 SZ_Write (sb, s, (int)strlen(s)+1);
255 void MSG_WriteCoord13i (sizebuf_t *sb, float f)
258 MSG_WriteShort (sb, (int)(f * 8.0 + 0.5));
260 MSG_WriteShort (sb, (int)(f * 8.0 - 0.5));
263 void MSG_WriteCoord16i (sizebuf_t *sb, float f)
266 MSG_WriteShort (sb, (int)(f + 0.5));
268 MSG_WriteShort (sb, (int)(f - 0.5));
271 void MSG_WriteCoord32f (sizebuf_t *sb, float f)
273 MSG_WriteFloat (sb, f);
276 void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
278 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE)
279 MSG_WriteCoord13i (sb, f);
280 else if (protocol == PROTOCOL_DARKPLACES1)
281 MSG_WriteCoord32f (sb, f);
282 else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
283 MSG_WriteCoord16i (sb, f);
285 MSG_WriteCoord32f (sb, f);
288 void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
290 MSG_WriteCoord (sb, v[0], protocol);
291 MSG_WriteCoord (sb, v[1], protocol);
292 MSG_WriteCoord (sb, v[2], protocol);
295 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
296 void MSG_WriteAngle8i (sizebuf_t *sb, float f)
299 MSG_WriteByte (sb, (int)(f*(256.0/360.0) + 0.5) & 255);
301 MSG_WriteByte (sb, (int)(f*(256.0/360.0) - 0.5) & 255);
304 void MSG_WriteAngle16i (sizebuf_t *sb, float f)
307 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) + 0.5) & 65535);
309 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) - 0.5) & 65535);
312 void MSG_WriteAngle32f (sizebuf_t *sb, float f)
314 MSG_WriteFloat (sb, f);
317 void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
319 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
320 MSG_WriteAngle8i (sb, f);
322 MSG_WriteAngle16i (sb, f);
329 qboolean msg_badread;
331 void MSG_BeginReading (void)
337 int MSG_ReadLittleShort (void)
339 if (msg_readcount+2 > net_message.cursize)
345 return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
348 int MSG_ReadBigShort (void)
350 if (msg_readcount+2 > net_message.cursize)
356 return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
359 int MSG_ReadLittleLong (void)
361 if (msg_readcount+4 > net_message.cursize)
367 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);
370 int MSG_ReadBigLong (void)
372 if (msg_readcount+4 > net_message.cursize)
378 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];
381 float MSG_ReadLittleFloat (void)
388 if (msg_readcount+4 > net_message.cursize)
394 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);
398 float MSG_ReadBigFloat (void)
405 if (msg_readcount+4 > net_message.cursize)
411 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];
415 char *MSG_ReadString (void)
417 static char string[2048];
419 for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadChar()) != -1 && c != 0;l++)
425 int MSG_ReadBytes (int numbytes, unsigned char *out)
428 for (l = 0;l < numbytes && (c = MSG_ReadChar()) != -1;l++)
433 float MSG_ReadCoord13i (void)
435 return MSG_ReadLittleShort() * (1.0/8.0);
438 float MSG_ReadCoord16i (void)
440 return (signed short) MSG_ReadLittleShort();
443 float MSG_ReadCoord32f (void)
445 return MSG_ReadLittleFloat();
448 float MSG_ReadCoord (protocolversion_t protocol)
450 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE)
451 return MSG_ReadCoord13i();
452 else if (protocol == PROTOCOL_DARKPLACES1)
453 return MSG_ReadCoord32f();
454 else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
455 return MSG_ReadCoord16i();
457 return MSG_ReadCoord32f();
460 void MSG_ReadVector (float *v, protocolversion_t protocol)
462 v[0] = MSG_ReadCoord(protocol);
463 v[1] = MSG_ReadCoord(protocol);
464 v[2] = MSG_ReadCoord(protocol);
467 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
468 float MSG_ReadAngle8i (void)
470 return (signed char) MSG_ReadByte () * (360.0/256.0);
473 float MSG_ReadAngle16i (void)
475 return (signed short)MSG_ReadShort () * (360.0/65536.0);
478 float MSG_ReadAngle32f (void)
480 return MSG_ReadFloat ();
483 float MSG_ReadAngle (protocolversion_t protocol)
485 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
486 return MSG_ReadAngle8i ();
488 return MSG_ReadAngle16i ();
492 //===========================================================================
494 void SZ_Clear (sizebuf_t *buf)
499 void *SZ_GetSpace (sizebuf_t *buf, int length)
503 if (buf->cursize + length > buf->maxsize)
505 if (!buf->allowoverflow)
506 Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n");
508 if (length > buf->maxsize)
509 Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length);
511 buf->overflowed = true;
512 Con_Print("SZ_GetSpace: overflow\n");
516 data = buf->data + buf->cursize;
517 buf->cursize += length;
522 void SZ_Write (sizebuf_t *buf, const void *data, int length)
524 memcpy (SZ_GetSpace(buf,length),data,length);
527 // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
528 // attention, it has been eradicated from here, its only (former) use in
529 // all of darkplaces.
531 static char *hexchar = "0123456789ABCDEF";
532 void Com_HexDumpToConsole(const qbyte *data, int size)
536 char *cur, *flushpointer;
539 flushpointer = text + 512;
540 for (i = 0;i < size;)
547 *cur++ = hexchar[(i >> 12) & 15];
548 *cur++ = hexchar[(i >> 8) & 15];
549 *cur++ = hexchar[(i >> 4) & 15];
550 *cur++ = hexchar[(i >> 0) & 15];
553 for (j = 0;j < 16;j++)
557 *cur++ = hexchar[(d[j] >> 4) & 15];
558 *cur++ = hexchar[(d[j] >> 0) & 15];
569 for (j = 0;j < 16;j++)
573 if (d[j] >= ' ' && d[j] <= 127)
583 if (cur >= flushpointer || i >= size)
592 void SZ_HexDumpToConsole(const sizebuf_t *buf)
594 Com_HexDumpToConsole(buf->data, buf->cursize);
598 //============================================================================
605 Parse a token out of a string
608 int COM_ParseToken(const char **datapointer, int returnnewline)
611 const char *data = *datapointer;
628 for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
638 // handle Windows line ending
639 if (data[0] == '\r' && data[1] == '\n')
642 if (data[0] == '/' && data[1] == '/')
645 while (*data && *data != '\n' && *data != '\r')
649 else if (data[0] == '/' && data[1] == '*')
653 while (*data && (data[0] != '*' || data[1] != '/'))
658 else if (*data == '\"')
661 for (data++;*data != '\"';data++)
663 if (*data == '\\' && data[1] == '"' )
665 if (!*data || len >= (int)sizeof(com_token) - 1)
671 com_token[len++] = *data;
674 *datapointer = data+1;
677 else if (*data == '\'')
680 for (data++;*data != '\'';data++)
682 if (*data == '\\' && data[1] == '\'' )
684 if (!*data || len >= (int)sizeof(com_token) - 1)
690 com_token[len++] = *data;
693 *datapointer = data+1;
696 else if (*data == '\r')
698 // translate Mac line ending to UNIX
699 com_token[len++] = '\n';
704 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == '\'' || *data == ':' || *data == ',' || *data == ';')
707 com_token[len++] = *data++;
715 for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != '\'' && *data != ':' && *data != ',' && *data != ';' && *data != '\'' && *data != '"';data++)
717 if (len >= (int)sizeof(com_token) - 1)
723 com_token[len++] = *data;
733 COM_ParseTokenConsole
735 Parse a token out of a string, behaving like the qwcl console
738 int COM_ParseTokenConsole(const char **datapointer)
741 const char *data = *datapointer;
754 for (;*data <= ' ';data++)
764 if (*data == '/' && data[1] == '/')
767 while (*data && *data != '\n' && *data != '\r')
771 else if (*data == '\"')
774 for (data++;*data != '\"';data++)
776 if (!*data || len >= (int)sizeof(com_token) - 1)
782 com_token[len++] = *data;
785 *datapointer = data+1;
790 for (;*data > ' ';data++)
792 if (len >= (int)sizeof(com_token) - 1)
798 com_token[len++] = *data;
805 if (com_token[0] == '$' && com_token[1])
809 cvar = Cvar_FindVar(&com_token[1]);
812 strcpy(com_token, cvar->string);
814 else if( com_token[1] == '$' )
816 // remove the first $
819 for( pos = com_token ; *pos ; pos++ )
833 Returns the position (1 to argc-1) in the program's argument list
834 where the given parameter apears, or 0 if not present
837 int COM_CheckParm (const char *parm)
841 for (i=1 ; i<com_argc ; i++)
844 continue; // NEXTSTEP sometimes clears appkit vars.
845 if (!strcmp (parm,com_argv[i]))
856 Looks for the pop.txt file and verifies it.
857 Sets the "registered" cvar.
858 Immediately exits out if an alternate game was attempted to be started without
862 void COM_CheckRegistered (void)
864 Cvar_Set ("cmdline", com_cmdline);
866 if (gamemode == GAME_NORMAL && !FS_FileExists("gfx/pop.lmp"))
869 Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
871 Con_Print("Playing shareware version.\n");
875 Cvar_Set ("registered", "1");
876 Con_Print("Playing registered version.\n");
885 void COM_InitArgv (void)
888 // reconstitute the command line for the cmdline externally visible cvar
890 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
893 if (strstr(com_argv[j], " "))
895 // arg contains whitespace, store quotes around it
896 com_cmdline[n++] = '\"';
897 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
898 com_cmdline[n++] = com_argv[j][i++];
899 com_cmdline[n++] = '\"';
903 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
904 com_cmdline[n++] = com_argv[j][i++];
906 if (n < (CMDLINE_LENGTH - 1))
907 com_cmdline[n++] = ' ';
915 //===========================================================================
921 const char* prog_name;
923 const char* gamename;
924 const char* gamedirname1;
925 const char* gamedirname2;
926 const char* gamescreenshotname;
927 const char* gameuserdirname;
930 static const gamemode_info_t gamemode_info [] =
931 {// prog_name cmdline gamename gamedirname gamescreenshotname
934 // COMMANDLINEOPTION: Game: -quake runs the game Quake (default)
935 { "", "-quake", "DarkPlaces-Quake", "id1", NULL, "dp", "darkplaces" },
937 // COMMANDLINEOPTION: Game: -hipnotic runs Quake mission pack 1: The Scourge of Armagon
938 { "hipnotic", "-hipnotic", "Darkplaces-Hipnotic", "id1", "hipnotic", "dp", "darkplaces" },
940 // COMMANDLINEOPTION: Game: -rogue runs Quake mission pack 2: The Dissolution of Eternity
941 { "rogue", "-rogue", "Darkplaces-Rogue", "id1", "rogue", "dp", "darkplaces" },
943 // COMMANDLINEOPTION: Game: -nehahra runs The Seal of Nehahra movie and game
944 { "nehahra", "-nehahra", "DarkPlaces-Nehahra", "id1", "nehahra", "dp", "darkplaces" },
946 // COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz
947 { "nexuiz", "-nexuiz", "Nexuiz", "data", NULL, "nexuiz", "nexuiz" },
949 // COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake)
950 { "transfusion", "-transfusion", "Transfusion", "basetf", NULL, "transfusion", "transfusion" },
952 // COMMANDLINEOPTION: Game: -goodvsbad2 runs the psychadelic RTS FPS game Good Vs Bad 2
953 { "gvb2", "-goodvsbad2", "GoodVs.Bad2", "rts", NULL, "gvb2", "gvb2" },
955 // COMMANDLINEOPTION: Game: -teu runs The Evil Unleashed (this option is obsolete as they are not using darkplaces)
956 { "teu", "-teu", "TheEvilUnleashed", "baseteu", NULL, "teu", "teu" },
958 // COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech
959 { "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" },
961 // COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic
962 { "zymotic", "-zymotic", "Zymotic", "data", NULL, "zymotic", "zymotic" },
964 // COMMANDLINEOPTION: Game: -fniggium runs the post apocalyptic melee RPG Fniggium
965 { "fniggium", "-fniggium", "Fniggium", "data", NULL, "fniggium", "fniggium" },
967 // COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral
968 { "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" },
970 // COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man
971 { "som", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" },
973 // COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented)
974 { "tenebrae", "-tenebrae", "DarkPlaces-Tenebrae", "id1", "tenebrae", "dp", "darkplaces" },
976 // COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric
977 { "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" },
979 // COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content
980 { "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces"},
982 // COMMANDLINEOPTION: Game: -prydon runs the topdown point and click action-RPG Prydon Gate
983 { "prydon", "-prydon", "PrydonGate", "id1", "prydon", "prydon", "darkplaces"},
985 // COMMANDLINEOPTION: Game: -netherworld runs the game Netherworld: Dark Masters
986 { "netherworld", "-netherworld", "Dark Masters", "id1", "netherworld", "nw", "darkplaces"},
988 // COMMANDLINEOPTION: Game: -netherworld runs the game The Hunted
989 { "thehunted", "-thehunted", "The Hunted", "thdata", NULL, "th", "thehunted"},
992 void COM_InitGameType (void)
994 char name [MAX_OSPATH];
997 FS_StripExtension (com_argv[0], name, sizeof (name));
998 COM_ToLowerString (name, name, sizeof (name));
1000 // Check the binary name; default to GAME_NORMAL (0)
1001 gamemode = GAME_NORMAL;
1002 for (i = 1; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
1003 if (strstr (name, gamemode_info[i].prog_name))
1009 // Look for a command-line option
1010 for (i = 0; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
1011 if (COM_CheckParm (gamemode_info[i].cmdline))
1017 gamename = gamemode_info[gamemode].gamename;
1018 gamedirname1 = gamemode_info[gamemode].gamedirname1;
1019 gamedirname2 = gamemode_info[gamemode].gamedirname2;
1020 gamescreenshotname = gamemode_info[gamemode].gamescreenshotname;
1021 gameuserdirname = gamemode_info[gamemode].gameuserdirname;
1030 void COM_Init_Commands (void)
1032 Cvar_RegisterVariable (®istered);
1033 Cvar_RegisterVariable (&cmdline);
1040 does a varargs printf into a temp buffer, so I don't need to have
1041 varargs versions of all text functions.
1042 FIXME: make this buffer size safe someday
1045 char *va(const char *format, ...)
1048 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
1049 static char string[8][1024], *s;
1050 static int stringindex = 0;
1052 s = string[stringindex];
1053 stringindex = (stringindex + 1) & 7;
1054 va_start (argptr, format);
1055 dpvsnprintf (s, sizeof (string[0]), format,argptr);
1062 //======================================
1064 // snprintf and vsnprintf are NOT portable. Use their DP counterparts instead
1070 # define snprintf _snprintf
1071 # define vsnprintf _vsnprintf
1075 int dpsnprintf (char *buffer, size_t buffersize, const char *format, ...)
1080 va_start (args, format);
1081 result = dpvsnprintf (buffer, buffersize, format, args);
1088 int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list args)
1092 result = vsnprintf (buffer, buffersize, format, args);
1093 if (result < 0 || (size_t)result >= buffersize)
1095 buffer[buffersize - 1] = '\0';
1103 //======================================
1105 void COM_ToLowerString (const char *in, char *out, size_t size_out)
1110 while (*in && size_out > 1)
1112 if (*in >= 'A' && *in <= 'Z')
1113 *out++ = *in++ + 'a' - 'A';
1121 void COM_ToUpperString (const char *in, char *out, size_t size_out)
1126 while (*in && size_out > 1)
1128 if (*in >= 'a' && *in <= 'z')
1129 *out++ = *in++ + 'A' - 'a';
1137 int COM_StringBeginsWith(const char *s, const char *match)
1139 for (;*s && *match;s++, match++)
1145 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
1147 int argc, commentprefixlength;
1151 tokenbufend = tokenbuf + tokenbufsize;
1153 commentprefixlength = 0;
1155 commentprefixlength = (int)strlen(commentprefix);
1156 while (*l && *l != '\n' && *l != '\r')
1160 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
1162 while (*l && *l != '\n' && *l != '\r')
1166 if (argc >= maxargc)
1168 argv[argc++] = tokenbuf;
1172 while (*l && *l != '"')
1174 if (tokenbuf >= tokenbufend)
1185 if (tokenbuf >= tokenbufend)
1190 if (tokenbuf >= tokenbufend)
1209 // written by Elric, thanks Elric!
1210 char *SearchInfostring(const char *infostring, const char *key)
1212 static char value [256];
1214 size_t value_ind, key_ind;
1217 if (*infostring++ != '\\')
1232 if (c == '\\' || key_ind == sizeof (crt_key) - 1)
1234 crt_key[key_ind] = '\0';
1238 crt_key[key_ind++] = c;
1241 // If it's the key we are looking for, save it in "value"
1242 if (!strcmp(crt_key, key))
1248 if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
1250 value[value_ind] = '\0';
1254 value[value_ind++] = c;
1258 // Else, skip the value
1272 //========================================================
1273 // strlcat and strlcpy, from OpenBSD
1276 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1278 * Permission to use, copy, modify, and distribute this software for any
1279 * purpose with or without fee is hereby granted, provided that the above
1280 * copyright notice and this permission notice appear in all copies.
1282 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1283 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1284 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1285 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1286 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1287 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1288 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1291 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
1292 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
1295 #ifndef HAVE_STRLCAT
1297 strlcat(char *dst, const char *src, size_t siz)
1299 register char *d = dst;
1300 register const char *s = src;
1301 register size_t n = siz;
1304 /* Find the end of dst and adjust bytes left but don't go past end */
1305 while (n-- != 0 && *d != '\0')
1311 return(dlen + strlen(s));
1312 while (*s != '\0') {
1321 return(dlen + (s - src)); /* count does not include NUL */
1323 #endif // #ifndef HAVE_STRLCAT
1326 #ifndef HAVE_STRLCPY
1328 strlcpy(char *dst, const char *src, size_t siz)
1330 register char *d = dst;
1331 register const char *s = src;
1332 register size_t n = siz;
1334 /* Copy as many bytes as will fit */
1335 if (n != 0 && --n != 0) {
1337 if ((*d++ = *s++) == 0)
1342 /* Not enough room in dst, add NUL and traverse rest of src */
1345 *d = '\0'; /* NUL-terminate dst */
1350 return(s - src - 1); /* count does not include NUL */
1353 #endif // #ifndef HAVE_STRLCPY