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, int 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, 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);
287 // Host_Error("MSG_WriteCoord: unknown protocol\n");
290 void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
292 MSG_WriteCoord (sb, v[0], protocol);
293 MSG_WriteCoord (sb, v[1], protocol);
294 MSG_WriteCoord (sb, v[2], protocol);
297 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
298 void MSG_WriteAngle8i (sizebuf_t *sb, float f)
301 MSG_WriteByte (sb, (int)(f*(256.0/360.0) + 0.5) & 255);
303 MSG_WriteByte (sb, (int)(f*(256.0/360.0) - 0.5) & 255);
306 void MSG_WriteAngle16i (sizebuf_t *sb, float f)
309 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) + 0.5) & 65535);
311 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) - 0.5) & 65535);
314 void MSG_WriteAngle32f (sizebuf_t *sb, float f)
316 MSG_WriteFloat (sb, f);
319 void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
321 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
322 MSG_WriteAngle8i (sb, f);
324 MSG_WriteAngle16i (sb, f);
331 qboolean msg_badread;
333 void MSG_BeginReading (void)
339 int MSG_ReadLittleShort (void)
341 if (msg_readcount+2 > net_message.cursize)
347 return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
350 int MSG_ReadBigShort (void)
352 if (msg_readcount+2 > net_message.cursize)
358 return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
361 int MSG_ReadLittleLong (void)
363 if (msg_readcount+4 > net_message.cursize)
369 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);
372 int MSG_ReadBigLong (void)
374 if (msg_readcount+4 > net_message.cursize)
380 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];
383 float MSG_ReadLittleFloat (void)
390 if (msg_readcount+4 > net_message.cursize)
396 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);
400 float MSG_ReadBigFloat (void)
407 if (msg_readcount+4 > net_message.cursize)
413 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];
417 char *MSG_ReadString (void)
419 static char string[2048];
421 for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadChar()) != -1 && c != 0;l++)
427 int MSG_ReadBytes (int numbytes, unsigned char *out)
430 for (l = 0;l < numbytes && (c = MSG_ReadChar()) != -1;l++)
435 float MSG_ReadCoord13i (void)
437 return MSG_ReadLittleShort() * (1.0/8.0);
440 float MSG_ReadCoord16i (void)
442 return (signed short) MSG_ReadLittleShort();
445 float MSG_ReadCoord32f (void)
447 return MSG_ReadLittleFloat();
450 float MSG_ReadCoord (protocolversion_t protocol)
452 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE)
453 return MSG_ReadCoord13i();
454 else if (protocol == PROTOCOL_DARKPLACES1)
455 return MSG_ReadCoord32f();
456 else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
457 return MSG_ReadCoord16i();
459 return MSG_ReadCoord32f();
462 void MSG_ReadVector (float *v, protocolversion_t protocol)
464 v[0] = MSG_ReadCoord(protocol);
465 v[1] = MSG_ReadCoord(protocol);
466 v[2] = MSG_ReadCoord(protocol);
469 // LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
470 float MSG_ReadAngle8i (void)
472 return (signed char) MSG_ReadByte () * (360.0/256.0);
475 float MSG_ReadAngle16i (void)
477 return (signed short)MSG_ReadShort () * (360.0/65536.0);
480 float MSG_ReadAngle32f (void)
482 return MSG_ReadFloat ();
485 float MSG_ReadAngle (protocolversion_t protocol)
487 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
488 return MSG_ReadAngle8i ();
490 return MSG_ReadAngle16i ();
494 //===========================================================================
496 void SZ_Clear (sizebuf_t *buf)
501 void *SZ_GetSpace (sizebuf_t *buf, int length)
505 if (buf->cursize + length > buf->maxsize)
507 if (!buf->allowoverflow)
508 Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n");
510 if (length > buf->maxsize)
511 Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length);
513 buf->overflowed = true;
514 Con_Print("SZ_GetSpace: overflow\n");
518 data = buf->data + buf->cursize;
519 buf->cursize += length;
524 void SZ_Write (sizebuf_t *buf, const void *data, int length)
526 memcpy (SZ_GetSpace(buf,length),data,length);
529 // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
530 // attention, it has been eradicated from here, its only (former) use in
531 // all of darkplaces.
533 static char *hexchar = "0123456789ABCDEF";
534 void Com_HexDumpToConsole(const qbyte *data, int size)
538 char *cur, *flushpointer;
541 flushpointer = text + 512;
542 for (i = 0;i < size;)
549 *cur++ = hexchar[(i >> 12) & 15];
550 *cur++ = hexchar[(i >> 8) & 15];
551 *cur++ = hexchar[(i >> 4) & 15];
552 *cur++ = hexchar[(i >> 0) & 15];
555 for (j = 0;j < 16;j++)
559 *cur++ = hexchar[(d[j] >> 4) & 15];
560 *cur++ = hexchar[(d[j] >> 0) & 15];
571 for (j = 0;j < 16;j++)
575 if (d[j] >= ' ' && d[j] <= 127)
585 if (cur >= flushpointer || i >= size)
594 void SZ_HexDumpToConsole(const sizebuf_t *buf)
596 Com_HexDumpToConsole(buf->data, buf->cursize);
600 //============================================================================
607 Parse a token out of a string
610 int COM_ParseToken(const char **datapointer, int returnnewline)
613 const char *data = *datapointer;
630 for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
640 // handle Windows line ending
641 if (data[0] == '\r' && data[1] == '\n')
644 if (data[0] == '/' && data[1] == '/')
647 while (*data && *data != '\n' && *data != '\r')
651 else if (data[0] == '/' && data[1] == '*')
655 while (*data && (data[0] != '*' || data[1] != '/'))
660 else if (*data == '\"')
663 for (data++;*data != '\"';data++)
665 if (*data == '\\' && data[1] == '"' )
667 if (!*data || len >= (int)sizeof(com_token) - 1)
673 com_token[len++] = *data;
676 *datapointer = data+1;
679 else if (*data == '\'')
682 for (data++;*data != '\'';data++)
684 if (*data == '\\' && data[1] == '\'' )
686 if (!*data || len >= (int)sizeof(com_token) - 1)
692 com_token[len++] = *data;
695 *datapointer = data+1;
698 else if (*data == '\r')
700 // translate Mac line ending to UNIX
701 com_token[len++] = '\n';
706 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == '\'' || *data == ':' || *data == ',' || *data == ';')
709 com_token[len++] = *data++;
717 for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != '\'' && *data != ':' && *data != ',' && *data != ';' && *data != '\'' && *data != '"';data++)
719 if (len >= (int)sizeof(com_token) - 1)
725 com_token[len++] = *data;
735 COM_ParseTokenConsole
737 Parse a token out of a string, behaving like the qwcl console
740 int COM_ParseTokenConsole(const char **datapointer)
743 const char *data = *datapointer;
756 for (;*data <= ' ';data++)
766 if (*data == '/' && data[1] == '/')
769 while (*data && *data != '\n' && *data != '\r')
773 else if (*data == '\"')
776 for (data++;*data != '\"';data++)
778 if (!*data || len >= (int)sizeof(com_token) - 1)
784 com_token[len++] = *data;
787 *datapointer = data+1;
793 for (;*data > ' ';data++)
795 if (len >= (int)sizeof(com_token) - 1)
801 com_token[len++] = *data;
814 Returns the position (1 to argc-1) in the program's argument list
815 where the given parameter apears, or 0 if not present
818 int COM_CheckParm (const char *parm)
822 for (i=1 ; i<com_argc ; i++)
825 continue; // NEXTSTEP sometimes clears appkit vars.
826 if (!strcmp (parm,com_argv[i]))
837 Looks for the pop.txt file and verifies it.
838 Sets the "registered" cvar.
839 Immediately exits out if an alternate game was attempted to be started without
843 void COM_CheckRegistered (void)
845 Cvar_Set ("cmdline", com_cmdline);
847 if (gamemode == GAME_NORMAL && !FS_FileExists("gfx/pop.lmp"))
850 Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
852 Con_Print("Playing shareware version.\n");
856 Cvar_Set ("registered", "1");
857 Con_Print("Playing registered version.\n");
866 void COM_InitArgv (void)
869 // reconstitute the command line for the cmdline externally visible cvar
871 for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
874 if (strstr(com_argv[j], " "))
876 // arg contains whitespace, store quotes around it
877 com_cmdline[n++] = '\"';
878 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
879 com_cmdline[n++] = com_argv[j][i++];
880 com_cmdline[n++] = '\"';
884 while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i])
885 com_cmdline[n++] = com_argv[j][i++];
887 if (n < (CMDLINE_LENGTH - 1))
888 com_cmdline[n++] = ' ';
896 //===========================================================================
902 const char* prog_name;
904 const char* gamename;
905 const char* gamedirname1;
906 const char* gamedirname2;
907 const char* gamescreenshotname;
908 const char* gameuserdirname;
911 static const gamemode_info_t gamemode_info [] =
912 {// prog_name cmdline gamename gamedirname gamescreenshotname
915 // COMMANDLINEOPTION: Game: -quake runs the game Quake (default)
916 { "", "-quake", "DarkPlaces-Quake", "id1", NULL, "dp", "darkplaces" },
918 // COMMANDLINEOPTION: Game: -hipnotic runs Quake mission pack 1: The Scourge of Armagon
919 { "hipnotic", "-hipnotic", "Darkplaces-Hipnotic", "id1", "hipnotic", "dp", "darkplaces" },
921 // COMMANDLINEOPTION: Game: -rogue runs Quake mission pack 2: The Dissolution of Eternity
922 { "rogue", "-rogue", "Darkplaces-Rogue", "id1", "rogue", "dp", "darkplaces" },
924 // COMMANDLINEOPTION: Game: -nehahra runs The Seal of Nehahra movie and game
925 { "nehahra", "-nehahra", "DarkPlaces-Nehahra", "id1", "nehahra", "dp", "darkplaces" },
927 // COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz
928 { "nexuiz", "-nexuiz", "Nexuiz", "data", NULL, "nexuiz", "nexuiz" },
930 // COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake)
931 { "transfusion", "-transfusion", "Transfusion", "basetf", NULL, "transfusion", "transfusion" },
933 // COMMANDLINEOPTION: Game: -goodvsbad2 runs the psychadelic RTS FPS game Good Vs Bad 2
934 { "gvb2", "-goodvsbad2", "GoodVs.Bad2", "rts", NULL, "gvb2", "gvb2" },
936 // COMMANDLINEOPTION: Game: -teu runs The Evil Unleashed (this option is obsolete as they are not using darkplaces)
937 { "teu", "-teu", "TheEvilUnleashed", "baseteu", NULL, "teu", "teu" },
939 // COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech
940 { "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" },
942 // COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic
943 { "zymotic", "-zymotic", "Zymotic", "data", NULL, "zymotic", "zymotic" },
945 // COMMANDLINEOPTION: Game: -fniggium runs the post apocalyptic melee RPG Fniggium
946 { "fniggium", "-fniggium", "Fniggium", "data", NULL, "fniggium", "fniggium" },
948 // COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral
949 { "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" },
951 // COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man
952 { "som", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" },
954 // COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented)
955 { "tenebrae", "-tenebrae", "DarkPlaces-Tenebrae", "id1", "tenebrae", "dp", "darkplaces" },
957 // COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric
958 { "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" },
960 // COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content
961 { "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces"},
963 // COMMANDLINEOPTION: Game: -prydon runs the topdown point and click action-RPG Prydon Gate
964 { "prydon", "-prydon", "PrydonGate", "id1", "prydon", "prydon", "darkplaces"},
966 // COMMANDLINEOPTION: Game: -netherworld runs the game Netherworld: Dark Masters
967 { "netherworld", "-netherworld", "Dark Masters", "id1", "netherworld", "nw", "darkplaces"},
969 // COMMANDLINEOPTION: Game: -netherworld runs the game The Hunted
970 { "thehunted", "-thehunted", "The Hunted", "thdata", NULL, "th", "thehunted"},
973 void COM_InitGameType (void)
975 char name [MAX_OSPATH];
978 FS_StripExtension (com_argv[0], name, sizeof (name));
979 COM_ToLowerString (name, name, sizeof (name));
981 // Check the binary name; default to GAME_NORMAL (0)
982 gamemode = GAME_NORMAL;
983 for (i = 1; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
984 if (strstr (name, gamemode_info[i].prog_name))
990 // Look for a command-line option
991 for (i = 0; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
992 if (COM_CheckParm (gamemode_info[i].cmdline))
998 gamename = gamemode_info[gamemode].gamename;
999 gamedirname1 = gamemode_info[gamemode].gamedirname1;
1000 gamedirname2 = gamemode_info[gamemode].gamedirname2;
1001 gamescreenshotname = gamemode_info[gamemode].gamescreenshotname;
1002 gameuserdirname = gamemode_info[gamemode].gameuserdirname;
1011 void COM_Init_Commands (void)
1013 Cvar_RegisterVariable (®istered);
1014 Cvar_RegisterVariable (&cmdline);
1021 does a varargs printf into a temp buffer, so I don't need to have
1022 varargs versions of all text functions.
1023 FIXME: make this buffer size safe someday
1026 char *va(const char *format, ...)
1029 // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
1030 static char string[8][1024], *s;
1031 static int stringindex = 0;
1033 s = string[stringindex];
1034 stringindex = (stringindex + 1) & 7;
1035 va_start (argptr, format);
1036 dpvsnprintf (s, sizeof (string[0]), format,argptr);
1043 //======================================
1045 // snprintf and vsnprintf are NOT portable. Use their DP counterparts instead
1051 # define snprintf _snprintf
1052 # define vsnprintf _vsnprintf
1056 int dpsnprintf (char *buffer, size_t buffersize, const char *format, ...)
1061 va_start (args, format);
1062 result = dpvsnprintf (buffer, buffersize, format, args);
1069 int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list args)
1073 result = vsnprintf (buffer, buffersize, format, args);
1074 if (result < 0 || (size_t)result >= buffersize)
1076 buffer[buffersize - 1] = '\0';
1084 //======================================
1086 void COM_ToLowerString (const char *in, char *out, size_t size_out)
1091 while (*in && size_out > 1)
1093 if (*in >= 'A' && *in <= 'Z')
1094 *out++ = *in++ + 'a' - 'A';
1102 void COM_ToUpperString (const char *in, char *out, size_t size_out)
1107 while (*in && size_out > 1)
1109 if (*in >= 'a' && *in <= 'z')
1110 *out++ = *in++ + 'A' - 'a';
1118 int COM_StringBeginsWith(const char *s, const char *match)
1120 for (;*s && *match;s++, match++)
1126 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
1128 int argc, commentprefixlength;
1132 tokenbufend = tokenbuf + tokenbufsize;
1134 commentprefixlength = 0;
1136 commentprefixlength = strlen(commentprefix);
1137 while (*l && *l != '\n' && *l != '\r')
1141 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
1143 while (*l && *l != '\n' && *l != '\r')
1147 if (argc >= maxargc)
1149 argv[argc++] = tokenbuf;
1153 while (*l && *l != '"')
1155 if (tokenbuf >= tokenbufend)
1166 if (tokenbuf >= tokenbufend)
1171 if (tokenbuf >= tokenbufend)
1190 // written by Elric, thanks Elric!
1191 char *SearchInfostring(const char *infostring, const char *key)
1193 static char value [256];
1195 size_t value_ind, key_ind;
1198 if (*infostring++ != '\\')
1213 if (c == '\\' || key_ind == sizeof (crt_key) - 1)
1215 crt_key[key_ind] = '\0';
1219 crt_key[key_ind++] = c;
1222 // If it's the key we are looking for, save it in "value"
1223 if (!strcmp(crt_key, key))
1229 if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
1231 value[value_ind] = '\0';
1235 value[value_ind++] = c;
1239 // Else, skip the value
1253 //========================================================
1254 // strlcat and strlcpy, from OpenBSD
1257 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1259 * Permission to use, copy, modify, and distribute this software for any
1260 * purpose with or without fee is hereby granted, provided that the above
1261 * copyright notice and this permission notice appear in all copies.
1263 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1264 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1265 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1266 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1267 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1268 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1269 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1272 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
1273 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
1276 #ifndef HAVE_STRLCAT
1278 strlcat(char *dst, const char *src, size_t siz)
1280 register char *d = dst;
1281 register const char *s = src;
1282 register size_t n = siz;
1285 /* Find the end of dst and adjust bytes left but don't go past end */
1286 while (n-- != 0 && *d != '\0')
1292 return(dlen + strlen(s));
1293 while (*s != '\0') {
1302 return(dlen + (s - src)); /* count does not include NUL */
1304 #endif // #ifndef HAVE_STRLCAT
1307 #ifndef HAVE_STRLCPY
1309 strlcpy(char *dst, const char *src, size_t siz)
1311 register char *d = dst;
1312 register const char *s = src;
1313 register size_t n = siz;
1315 /* Copy as many bytes as will fit */
1316 if (n != 0 && --n != 0) {
1318 if ((*d++ = *s++) == 0)
1323 /* Not enough room in dst, add NUL and traverse rest of src */
1326 *d = '\0'; /* NUL-terminate dst */
1331 return(s - src - 1); /* count does not include NUL */
1334 #endif // #ifndef HAVE_STRLCPY