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", "indicates if this is running registered quake (whether gfx/qpop.lmp was found)"};
31 cvar_t cmdline = {0, "cmdline","0", "contains commandline the engine was launched with"};
33 extern qboolean fs_modified; // set true if using non-id files
35 char com_token[MAX_INPUTLINE];
37 const char **com_argv;
39 char com_cmdline[MAX_INPUTLINE];
43 const char *gamedirname1;
44 const char *gamedirname2;
45 const char *gamescreenshotname;
46 const char *gameuserdirname;
47 char com_modname[MAX_OSPATH] = "";
51 ============================================================================
55 ============================================================================
58 short ShortSwap (short l)
70 unsigned char b1,b2,b3,b4;
77 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
80 float FloatSwap (float f)
90 dat2.b[0] = dat1.b[3];
91 dat2.b[1] = dat1.b[2];
92 dat2.b[2] = dat1.b[1];
93 dat2.b[3] = dat1.b[0];
98 // Extract integers from buffers
100 unsigned int BuffBigLong (const unsigned char *buffer)
102 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
105 unsigned short BuffBigShort (const unsigned char *buffer)
107 return (buffer[0] << 8) | buffer[1];
110 unsigned int BuffLittleLong (const unsigned char *buffer)
112 return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
115 unsigned short BuffLittleShort (const unsigned char *buffer)
117 return (buffer[1] << 8) | buffer[0];
122 ============================================================================
126 ============================================================================
129 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
130 // and the initial and final xor values shown below... in other words, the
131 // CCITT standard CRC used by XMODEM
133 #define CRC_INIT_VALUE 0xffff
134 #define CRC_XOR_VALUE 0x0000
136 static unsigned short crctable[256] =
138 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
139 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
140 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
141 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
142 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
143 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
144 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
145 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
146 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
147 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
148 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
149 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
150 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
151 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
152 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
153 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
154 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
155 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
156 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
157 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
158 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
159 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
160 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
161 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
162 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
163 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
164 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
165 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
166 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
167 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
168 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
169 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
172 unsigned short CRC_Block(const unsigned char *data, size_t size)
174 unsigned short crc = CRC_INIT_VALUE;
176 crc = (crc << 8) ^ crctable[(crc >> 8) ^ (*data++)];
177 return crc ^ CRC_XOR_VALUE;
182 ==============================================================================
186 Handles byte ordering and avoids alignment errors
187 ==============================================================================
194 void MSG_WriteChar (sizebuf_t *sb, int c)
198 buf = SZ_GetSpace (sb, 1);
202 void MSG_WriteByte (sizebuf_t *sb, int c)
206 buf = SZ_GetSpace (sb, 1);
210 void MSG_WriteShort (sizebuf_t *sb, int c)
214 buf = SZ_GetSpace (sb, 2);
219 void MSG_WriteLong (sizebuf_t *sb, int c)
223 buf = SZ_GetSpace (sb, 4);
225 buf[1] = (c>>8)&0xff;
226 buf[2] = (c>>16)&0xff;
230 void MSG_WriteFloat (sizebuf_t *sb, float f)
240 dat.l = LittleLong (dat.l);
242 SZ_Write (sb, (unsigned char *)&dat.l, 4);
245 void MSG_WriteString (sizebuf_t *sb, const char *s)
248 SZ_Write (sb, (unsigned char *)"", 1);
250 SZ_Write (sb, (unsigned char *)s, (int)strlen(s)+1);
253 void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s)
256 SZ_Write (sb, (unsigned char *)s, (int)strlen(s));
259 void MSG_WriteCoord13i (sizebuf_t *sb, float f)
262 MSG_WriteShort (sb, (int)(f * 8.0 + 0.5));
264 MSG_WriteShort (sb, (int)(f * 8.0 - 0.5));
267 void MSG_WriteCoord16i (sizebuf_t *sb, float f)
270 MSG_WriteShort (sb, (int)(f + 0.5));
272 MSG_WriteShort (sb, (int)(f - 0.5));
275 void MSG_WriteCoord32f (sizebuf_t *sb, float f)
277 MSG_WriteFloat (sb, f);
280 void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
282 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE)
283 MSG_WriteCoord13i (sb, f);
284 else if (protocol == PROTOCOL_DARKPLACES1)
285 MSG_WriteCoord32f (sb, f);
286 else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
287 MSG_WriteCoord16i (sb, f);
289 MSG_WriteCoord32f (sb, f);
292 void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
294 MSG_WriteCoord (sb, v[0], protocol);
295 MSG_WriteCoord (sb, v[1], protocol);
296 MSG_WriteCoord (sb, v[2], protocol);
299 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
300 void MSG_WriteAngle8i (sizebuf_t *sb, float f)
303 MSG_WriteByte (sb, (int)(f*(256.0/360.0) + 0.5) & 255);
305 MSG_WriteByte (sb, (int)(f*(256.0/360.0) - 0.5) & 255);
308 void MSG_WriteAngle16i (sizebuf_t *sb, float f)
311 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) + 0.5) & 65535);
313 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) - 0.5) & 65535);
316 void MSG_WriteAngle32f (sizebuf_t *sb, float f)
318 MSG_WriteFloat (sb, f);
321 void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
323 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
324 MSG_WriteAngle8i (sb, f);
326 MSG_WriteAngle16i (sb, f);
333 qboolean msg_badread;
335 void MSG_BeginReading (void)
341 int MSG_ReadLittleShort (void)
343 if (msg_readcount+2 > net_message.cursize)
349 return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
352 int MSG_ReadBigShort (void)
354 if (msg_readcount+2 > net_message.cursize)
360 return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
363 int MSG_ReadLittleLong (void)
365 if (msg_readcount+4 > net_message.cursize)
371 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);
374 int MSG_ReadBigLong (void)
376 if (msg_readcount+4 > net_message.cursize)
382 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];
385 float MSG_ReadLittleFloat (void)
392 if (msg_readcount+4 > net_message.cursize)
398 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);
402 float MSG_ReadBigFloat (void)
409 if (msg_readcount+4 > net_message.cursize)
415 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];
419 char *MSG_ReadString (void)
421 static char string[MAX_INPUTLINE];
423 for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadChar()) != -1 && c != 0;l++)
429 int MSG_ReadBytes (int numbytes, unsigned char *out)
432 for (l = 0;l < numbytes && (c = MSG_ReadChar()) != -1;l++)
437 float MSG_ReadCoord13i (void)
439 return MSG_ReadLittleShort() * (1.0/8.0);
442 float MSG_ReadCoord16i (void)
444 return (signed short) MSG_ReadLittleShort();
447 float MSG_ReadCoord32f (void)
449 return MSG_ReadLittleFloat();
452 float MSG_ReadCoord (protocolversion_t protocol)
454 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE)
455 return MSG_ReadCoord13i();
456 else if (protocol == PROTOCOL_DARKPLACES1)
457 return MSG_ReadCoord32f();
458 else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
459 return MSG_ReadCoord16i();
461 return MSG_ReadCoord32f();
464 void MSG_ReadVector (float *v, protocolversion_t protocol)
466 v[0] = MSG_ReadCoord(protocol);
467 v[1] = MSG_ReadCoord(protocol);
468 v[2] = MSG_ReadCoord(protocol);
471 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
472 float MSG_ReadAngle8i (void)
474 return (signed char) MSG_ReadByte () * (360.0/256.0);
477 float MSG_ReadAngle16i (void)
479 return (signed short)MSG_ReadShort () * (360.0/65536.0);
482 float MSG_ReadAngle32f (void)
484 return MSG_ReadFloat ();
487 float MSG_ReadAngle (protocolversion_t protocol)
489 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
490 return MSG_ReadAngle8i ();
492 return MSG_ReadAngle16i ();
496 //===========================================================================
498 void SZ_Clear (sizebuf_t *buf)
503 unsigned char *SZ_GetSpace (sizebuf_t *buf, int length)
507 if (buf->cursize + length > buf->maxsize)
509 if (!buf->allowoverflow)
510 Host_Error ("SZ_GetSpace: overflow without allowoverflow set");
512 if (length > buf->maxsize)
513 Host_Error ("SZ_GetSpace: %i is > full buffer size", length);
515 buf->overflowed = true;
516 Con_Print("SZ_GetSpace: overflow\n");
520 data = buf->data + buf->cursize;
521 buf->cursize += length;
526 void SZ_Write (sizebuf_t *buf, const unsigned char *data, int length)
528 memcpy (SZ_GetSpace(buf,length),data,length);
531 // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
532 // attention, it has been eradicated from here, its only (former) use in
533 // all of darkplaces.
535 static char *hexchar = "0123456789ABCDEF";
536 void Com_HexDumpToConsole(const unsigned char *data, int size)
540 char *cur, *flushpointer;
541 const unsigned char *d;
543 flushpointer = text + 512;
544 for (i = 0;i < size;)
551 *cur++ = hexchar[(i >> 12) & 15];
552 *cur++ = hexchar[(i >> 8) & 15];
553 *cur++ = hexchar[(i >> 4) & 15];
554 *cur++ = hexchar[(i >> 0) & 15];
557 for (j = 0;j < 16;j++)
561 *cur++ = hexchar[(d[j] >> 4) & 15];
562 *cur++ = hexchar[(d[j] >> 0) & 15];
573 for (j = 0;j < 16;j++)
577 if (d[j] >= ' ' && d[j] <= 127)
587 if (cur >= flushpointer || i >= size)
596 void SZ_HexDumpToConsole(const sizebuf_t *buf)
598 Com_HexDumpToConsole(buf->data, buf->cursize);
602 //============================================================================
609 Parse a token out of a string
612 int COM_ParseToken(const char **datapointer, int returnnewline)
615 const char *data = *datapointer;
632 for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
642 // handle Windows line ending
643 if (data[0] == '\r' && data[1] == '\n')
646 if (data[0] == '/' && data[1] == '/')
649 while (*data && *data != '\n' && *data != '\r')
653 else if (data[0] == '/' && data[1] == '*')
657 while (*data && (data[0] != '*' || data[1] != '/'))
662 else if (*data == '\"')
665 for (data++;*data != '\"';data++)
667 if (*data == '\\' && data[1] == '"' )
669 if (!*data || len >= (int)sizeof(com_token) - 1)
675 com_token[len++] = *data;
678 *datapointer = data+1;
681 else if (*data == '\'')
684 for (data++;*data != '\'';data++)
686 if (*data == '\\' && data[1] == '\'' )
688 if (!*data || len >= (int)sizeof(com_token) - 1)
694 com_token[len++] = *data;
697 *datapointer = data+1;
700 else if (*data == '\r')
702 // translate Mac line ending to UNIX
703 com_token[len++] = '\n';
708 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == '\'' || *data == ':' || *data == ',' || *data == ';')
711 com_token[len++] = *data++;
719 for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != '\'' && *data != ':' && *data != ',' && *data != ';' && *data != '\'' && *data != '"';data++)
721 if (len >= (int)sizeof(com_token) - 1)
727 com_token[len++] = *data;
737 COM_ParseTokenConsole
739 Parse a token out of a string, behaving like the qwcl console
742 int COM_ParseTokenConsole(const char **datapointer)
745 const char *data = *datapointer;
758 for (;*data <= ' ';data++)
768 if (*data == '/' && data[1] == '/')
771 while (*data && *data != '\n' && *data != '\r')
775 else if (*data == '\"')
778 for (data++;*data != '\"';data++)
780 if (!*data || len >= (int)sizeof(com_token) - 1)
786 com_token[len++] = *data;
789 *datapointer = data+1;
794 for (;*data > ' ';data++)
796 if (len >= (int)sizeof(com_token) - 1)
802 com_token[len++] = *data;
816 Returns the position (1 to argc-1) in the program's argument list
817 where the given parameter apears, or 0 if not present
820 int COM_CheckParm (const char *parm)
824 for (i=1 ; i<com_argc ; i++)
827 continue; // NEXTSTEP sometimes clears appkit vars.
828 if (!strcmp (parm,com_argv[i]))
839 Looks for the pop.txt file and verifies it.
840 Sets the "registered" cvar.
841 Immediately exits out if an alternate game was attempted to be started without
845 void COM_CheckRegistered (void)
847 Cvar_Set ("cmdline", com_cmdline);
849 if (gamemode == GAME_NORMAL && !FS_FileExists("gfx/pop.lmp"))
852 Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
854 Con_Print("Playing shareware version.\n");
858 Cvar_Set ("registered", "1");
859 Con_Print("Playing registered version.\n");
868 void COM_InitArgv (void)
871 // reconstitute the command line for the cmdline externally visible cvar
873 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
876 if (strstr(com_argv[j], " "))
878 // arg contains whitespace, store quotes around it
879 com_cmdline[n++] = '\"';
880 while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i])
881 com_cmdline[n++] = com_argv[j][i++];
882 com_cmdline[n++] = '\"';
886 while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i])
887 com_cmdline[n++] = com_argv[j][i++];
889 if (n < ((int)sizeof(com_cmdline) - 1))
890 com_cmdline[n++] = ' ';
898 //===========================================================================
902 typedef struct gamemode_info_s
904 const char* prog_name;
906 const char* gamename;
907 const char* gamedirname1;
908 const char* gamedirname2;
909 const char* gamescreenshotname;
910 const char* gameuserdirname;
913 static const gamemode_info_t gamemode_info [] =
914 {// prog_name cmdline gamename gamedirname gamescreenshotname
917 // COMMANDLINEOPTION: Game: -quake runs the game Quake (default)
918 { "", "-quake", "DarkPlaces-Quake", "id1", NULL, "dp", "darkplaces" },
920 // COMMANDLINEOPTION: Game: -hipnotic runs Quake mission pack 1: The Scourge of Armagon
921 { "hipnotic", "-hipnotic", "Darkplaces-Hipnotic", "id1", "hipnotic", "dp", "darkplaces" },
923 // COMMANDLINEOPTION: Game: -rogue runs Quake mission pack 2: The Dissolution of Eternity
924 { "rogue", "-rogue", "Darkplaces-Rogue", "id1", "rogue", "dp", "darkplaces" },
926 // COMMANDLINEOPTION: Game: -nehahra runs The Seal of Nehahra movie and game
927 { "nehahra", "-nehahra", "DarkPlaces-Nehahra", "id1", "nehahra", "dp", "darkplaces" },
929 // COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz
930 { "nexuiz", "-nexuiz", "Nexuiz", "data", NULL, "nexuiz", "nexuiz" },
932 // COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake)
933 { "transfusion", "-transfusion", "Transfusion", "basetf", NULL, "transfusion", "transfusion" },
935 // COMMANDLINEOPTION: Game: -goodvsbad2 runs the psychadelic RTS FPS game Good Vs Bad 2
936 { "gvb2", "-goodvsbad2", "GoodVs.Bad2", "rts", NULL, "gvb2", "gvb2" },
938 // COMMANDLINEOPTION: Game: -teu runs The Evil Unleashed (this option is obsolete as they are not using darkplaces)
939 { "teu", "-teu", "TheEvilUnleashed", "baseteu", NULL, "teu", "teu" },
941 // COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech
942 { "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" },
944 // COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic
945 { "zymotic", "-zymotic", "Zymotic", "basezym", NULL, "zymotic", "zymotic" },
947 // COMMANDLINEOPTION: Game: -fniggium runs the post apocalyptic melee RPG Fniggium
948 { "fniggium", "-fniggium", "Fniggium", "data", NULL, "fniggium", "fniggium" },
950 // COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral
951 { "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" },
953 // COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man
954 { "som", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" },
956 // COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented)
957 { "tenebrae", "-tenebrae", "DarkPlaces-Tenebrae", "id1", "tenebrae", "dp", "darkplaces" },
959 // COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric
960 { "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" },
962 // COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content
963 { "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces" },
965 // COMMANDLINEOPTION: Game: -prydon runs the topdown point and click action-RPG Prydon Gate
966 { "prydon", "-prydon", "PrydonGate", "id1", "prydon", "prydon", "darkplaces" },
968 // COMMANDLINEOPTION: Game: -netherworld runs the game Netherworld: Dark Master
969 { "netherworld", "-netherworld", "Netherworld: Dark Master", "id1", "netherworld", "nw", "darkplaces" },
971 // COMMANDLINEOPTION: Game: -thehunted runs the game The Hunted
972 { "thehunted", "-thehunted", "The Hunted", "thdata", NULL, "th", "thehunted" },
973 // GAME_DEFEATINDETAIL2
974 // COMMANDLINEOPTION: Game: -did2 runs the game Defeat In Detail 2
975 { "did2", "-did2", "Defeat In Detail 2", "data", NULL, "did2_", "did2" },
978 void COM_InitGameType (void)
980 char name [MAX_OSPATH];
983 FS_StripExtension (com_argv[0], name, sizeof (name));
984 COM_ToLowerString (name, name, sizeof (name));
986 // Check the binary name; default to GAME_NORMAL (0)
987 gamemode = GAME_NORMAL;
988 for (i = 1; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
989 if (strstr (name, gamemode_info[i].prog_name))
991 gamemode = (gamemode_t)i;
995 // Look for a command-line option
996 for (i = 0; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
997 if (COM_CheckParm (gamemode_info[i].cmdline))
999 gamemode = (gamemode_t)i;
1003 gamename = gamemode_info[gamemode].gamename;
1004 gamedirname1 = gamemode_info[gamemode].gamedirname1;
1005 gamedirname2 = gamemode_info[gamemode].gamedirname2;
1006 gamescreenshotname = gamemode_info[gamemode].gamescreenshotname;
1007 gameuserdirname = gamemode_info[gamemode].gameuserdirname;
1016 void COM_Init_Commands (void)
1018 Cvar_RegisterVariable (®istered);
1019 Cvar_RegisterVariable (&cmdline);
1026 does a varargs printf into a temp buffer, so I don't need to have
1027 varargs versions of all text functions.
1028 FIXME: make this buffer size safe someday
1031 char *va(const char *format, ...)
1034 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
1035 static char string[8][1024], *s;
1036 static int stringindex = 0;
1038 s = string[stringindex];
1039 stringindex = (stringindex + 1) & 7;
1040 va_start (argptr, format);
1041 dpvsnprintf (s, sizeof (string[0]), format,argptr);
1048 //======================================
1050 // snprintf and vsnprintf are NOT portable. Use their DP counterparts instead
1056 # define snprintf _snprintf
1057 # define vsnprintf _vsnprintf
1061 int dpsnprintf (char *buffer, size_t buffersize, const char *format, ...)
1066 va_start (args, format);
1067 result = dpvsnprintf (buffer, buffersize, format, args);
1074 int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list args)
1078 result = vsnprintf (buffer, buffersize, format, args);
1079 if (result < 0 || (size_t)result >= buffersize)
1081 buffer[buffersize - 1] = '\0';
1089 //======================================
1091 void COM_ToLowerString (const char *in, char *out, size_t size_out)
1096 while (*in && size_out > 1)
1098 if (*in >= 'A' && *in <= 'Z')
1099 *out++ = *in++ + 'a' - 'A';
1107 void COM_ToUpperString (const char *in, char *out, size_t size_out)
1112 while (*in && size_out > 1)
1114 if (*in >= 'a' && *in <= 'z')
1115 *out++ = *in++ + 'A' - 'a';
1123 int COM_StringBeginsWith(const char *s, const char *match)
1125 for (;*s && *match;s++, match++)
1131 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
1133 int argc, commentprefixlength;
1137 tokenbufend = tokenbuf + tokenbufsize;
1139 commentprefixlength = 0;
1141 commentprefixlength = (int)strlen(commentprefix);
1142 while (*l && *l != '\n' && *l != '\r')
1146 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
1148 while (*l && *l != '\n' && *l != '\r')
1152 if (argc >= maxargc)
1154 argv[argc++] = tokenbuf;
1158 while (*l && *l != '"')
1160 if (tokenbuf >= tokenbufend)
1171 if (tokenbuf >= tokenbufend)
1176 if (tokenbuf >= tokenbufend)
1195 // written by Elric, thanks Elric!
1196 char *SearchInfostring(const char *infostring, const char *key)
1198 static char value [MAX_INPUTLINE];
1199 char crt_key [MAX_INPUTLINE];
1200 size_t value_ind, key_ind;
1203 if (*infostring++ != '\\')
1218 if (c == '\\' || key_ind == sizeof (crt_key) - 1)
1220 crt_key[key_ind] = '\0';
1224 crt_key[key_ind++] = c;
1227 // If it's the key we are looking for, save it in "value"
1228 if (!strcmp(crt_key, key))
1234 if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
1236 value[value_ind] = '\0';
1240 value[value_ind++] = c;
1244 // Else, skip the value
1257 void InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength)
1265 keylength = strlen(key);
1266 if (valuelength < 1 || !value)
1268 Con_Printf("InfoString_GetValue: no room in value\n");
1272 if (strchr(key, '\\'))
1274 Con_Printf("InfoString_GetValue: key name \"%s\" contains \\ which is not possible in an infostring\n", key);
1279 Con_Printf("InfoString_GetValue: can not look up a key with no name\n");
1282 while (buffer[pos] == '\\')
1284 if (!memcmp(buffer + pos+1, key, keylength))
1286 for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
1288 for (j = 0;buffer[pos+j] && buffer[pos+j] != '\\' && j < (int)valuelength - 1;j++)
1289 value[j] = buffer[pos+j];
1293 for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
1294 for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
1296 // if we reach this point the key was not found
1299 void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value)
1307 keylength = strlen(key);
1308 if (strchr(key, '\\') || strchr(value, '\\'))
1310 Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \\ which is not possible to store in an infostring\n", key, value);
1315 Con_Printf("InfoString_SetValue: can not set a key with no name\n");
1318 while (buffer[pos] == '\\')
1320 if (!memcmp(buffer + pos+1, key, keylength))
1322 for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
1323 for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
1325 // if we found the key, find the end of it because we will be replacing it
1327 if (buffer[pos] == '\\')
1329 for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos++);
1330 for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos++);
1332 if (bufferlength <= 1 + strlen(key) + 1 + strlen(value) + strlen(buffer + pos2))
1334 Con_Printf("InfoString_SetValue: no room for \"%s\" \"%s\" in infostring\n", key, value);
1337 if (value && value[0])
1339 // set the key/value and append the remaining text
1340 char tempbuffer[4096];
1341 strlcpy(tempbuffer, buffer + pos2, sizeof(tempbuffer));
1342 sprintf(buffer + pos, "\\%s\\%s%s", key, value, tempbuffer);
1346 // just remove the key from the text
1347 strcpy(buffer + pos, buffer + pos2);
1352 //========================================================
1353 // strlcat and strlcpy, from OpenBSD
1356 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1358 * Permission to use, copy, modify, and distribute this software for any
1359 * purpose with or without fee is hereby granted, provided that the above
1360 * copyright notice and this permission notice appear in all copies.
1362 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1363 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1364 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1365 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1366 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1367 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1368 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1371 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
1372 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
1375 #ifndef HAVE_STRLCAT
1377 strlcat(char *dst, const char *src, size_t siz)
1379 register char *d = dst;
1380 register const char *s = src;
1381 register size_t n = siz;
1384 /* Find the end of dst and adjust bytes left but don't go past end */
1385 while (n-- != 0 && *d != '\0')
1391 return(dlen + strlen(s));
1392 while (*s != '\0') {
1401 return(dlen + (s - src)); /* count does not include NUL */
1403 #endif // #ifndef HAVE_STRLCAT
1406 #ifndef HAVE_STRLCPY
1408 strlcpy(char *dst, const char *src, size_t siz)
1410 register char *d = dst;
1411 register const char *s = src;
1412 register size_t n = siz;
1414 /* Copy as many bytes as will fit */
1415 if (n != 0 && --n != 0) {
1417 if ((*d++ = *s++) == 0)
1422 /* Not enough room in dst, add NUL and traverse rest of src */
1425 *d = '\0'; /* NUL-terminate dst */
1430 return(s - src - 1); /* count does not include NUL */
1433 #endif // #ifndef HAVE_STRLCPY