#include "quakedef.h"
-cvar_t registered = {0, "registered","0", "indicates if this is running registered quake (whether gfx/qpop.lmp was found)"};
+cvar_t registered = {0, "registered","0", "indicates if this is running registered quake (whether gfx/pop.lmp was found)"};
cvar_t cmdline = {0, "cmdline","0", "contains commandline the engine was launched with"};
-extern qboolean fs_modified; // set true if using non-id files
-
char com_token[MAX_INPUTLINE];
int com_argc;
const char **com_argv;
-char com_cmdline[MAX_INPUTLINE];
-
gamemode_t gamemode;
const char *gamename;
const char *gamedirname1;
void MSG_WriteString (sizebuf_t *sb, const char *s)
{
- if (!s)
- SZ_Write (sb, (unsigned char *)"", 1);
+ if (!s || !*s)
+ MSG_WriteChar (sb, 0);
else
SZ_Write (sb, (unsigned char *)s, (int)strlen(s)+1);
}
void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s)
{
- if (s)
+ if (s && *s)
SZ_Write (sb, (unsigned char *)s, (int)strlen(s));
}
void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
{
- if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_QUAKEWORLD)
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
MSG_WriteCoord13i (sb, f);
else if (protocol == PROTOCOL_DARKPLACES1)
MSG_WriteCoord32f (sb, f);
void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
{
- if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
MSG_WriteAngle8i (sb, f);
else
MSG_WriteAngle16i (sb, f);
float MSG_ReadCoord (protocolversion_t protocol)
{
- if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_QUAKEWORLD)
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
return MSG_ReadCoord13i();
else if (protocol == PROTOCOL_DARKPLACES1)
return MSG_ReadCoord32f();
float MSG_ReadAngle (protocolversion_t protocol)
{
- if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
return MSG_ReadAngle8i ();
else
return MSG_ReadAngle16i ();
{
if (j < n)
{
- if (d[j] >= ' ' && d[j] <= 127)
+ // color change prefix character has to be treated specially
+ if (d[j] == STRING_COLOR_TAG)
+ {
+ *cur++ = STRING_COLOR_TAG;
+ *cur++ = STRING_COLOR_TAG;
+ }
+ else if (d[j] >= ' ')
*cur++ = d[j];
else
*cur++ = '.';
/*
==============
-COM_ParseToken
+COM_ParseToken_Simple
Parse a token out of a string
==============
*/
-int COM_ParseToken(const char **datapointer, int returnnewline)
+int COM_ParseToken_Simple(const char **datapointer, qboolean returnnewline, qboolean parsebackslash)
{
int len;
+ int c;
const char *data = *datapointer;
len = 0;
data++;
while (*data && (data[0] != '*' || data[1] != '/'))
data++;
- data += 2;
+ if (*data)
+ data++;
+ if (*data)
+ data++;
goto skipwhite;
}
else if (*data == '\"')
{
// quoted string
- for (data++;*data != '\"';data++)
+ for (data++;*data && *data != '\"';data++)
{
- if (*data == '\\' && data[1] == '"' )
- data++;
- if (!*data || len >= (int)sizeof(com_token) - 1)
+ c = *data;
+ if (*data == '\\' && parsebackslash)
{
- com_token[0] = 0;
- *datapointer = NULL;
- return false;
+ data++;
+ c = *data;
+ if (c == 'n')
+ c = '\n';
+ else if (c == 't')
+ c = '\t';
}
- com_token[len++] = *data;
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = c;
}
com_token[len] = 0;
- *datapointer = data+1;
+ if (*data == '\"')
+ data++;
+ *datapointer = data;
+ return true;
+ }
+ else if (*data == '\r')
+ {
+ // translate Mac line ending to UNIX
+ com_token[len++] = '\n';data++;
+ com_token[len] = 0;
+ *datapointer = data;
return true;
}
- else if (*data == '\'')
+ else if (*data == '\n')
+ {
+ // single character
+ com_token[len++] = *data++;
+ com_token[len] = 0;
+ *datapointer = data;
+ return true;
+ }
+ else
+ {
+ // regular word
+ for (;*data > ' ';data++)
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = *data;
+ com_token[len] = 0;
+ *datapointer = data;
+ return true;
+ }
+}
+
+/*
+==============
+COM_ParseToken_QuakeC
+
+Parse a token out of a string
+==============
+*/
+int COM_ParseToken_QuakeC(const char **datapointer, qboolean returnnewline)
+{
+ int len;
+ int c;
+ const char *data = *datapointer;
+
+ len = 0;
+ com_token[0] = 0;
+
+ if (!data)
+ {
+ *datapointer = NULL;
+ return false;
+ }
+
+// skip whitespace
+skipwhite:
+ // line endings:
+ // UNIX: \n
+ // Mac: \r
+ // Windows: \r\n
+ for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
+ {
+ if (*data == 0)
+ {
+ // end of file
+ *datapointer = NULL;
+ return false;
+ }
+ }
+
+ // handle Windows line ending
+ if (data[0] == '\r' && data[1] == '\n')
+ data++;
+
+ if (data[0] == '/' && data[1] == '/')
+ {
+ // comment
+ while (*data && *data != '\n' && *data != '\r')
+ data++;
+ goto skipwhite;
+ }
+ else if (data[0] == '/' && data[1] == '*')
+ {
+ // comment
+ data++;
+ while (*data && (data[0] != '*' || data[1] != '/'))
+ data++;
+ if (*data)
+ data++;
+ if (*data)
+ data++;
+ goto skipwhite;
+ }
+ else if (*data == '\"' || *data == '\'')
{
// quoted string
- for (data++;*data != '\'';data++)
+ char quote = *data;
+ for (data++;*data && *data != quote;data++)
{
- if (*data == '\\' && data[1] == '\'' )
- data++;
- if (!*data || len >= (int)sizeof(com_token) - 1)
+ c = *data;
+ if (*data == '\\')
{
- com_token[0] = 0;
- *datapointer = NULL;
- return false;
+ data++;
+ c = *data;
+ if (c == 'n')
+ c = '\n';
+ else if (c == 't')
+ c = '\t';
}
- com_token[len++] = *data;
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = c;
}
com_token[len] = 0;
- *datapointer = data+1;
+ if (*data == quote)
+ data++;
+ *datapointer = data;
return true;
}
else if (*data == '\r')
{
// translate Mac line ending to UNIX
- com_token[len++] = '\n';
+ com_token[len++] = '\n';data++;
com_token[len] = 0;
*datapointer = data;
return true;
}
- else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == '\'' || *data == ':' || *data == ',' || *data == ';')
+ else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == ':' || *data == ',' || *data == ';')
{
// single character
com_token[len++] = *data++;
else
{
// regular word
- for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != '\'' && *data != ':' && *data != ',' && *data != ';' && *data != '\'' && *data != '"';data++)
+ for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = *data;
+ com_token[len] = 0;
+ *datapointer = data;
+ return true;
+ }
+}
+
+/*
+==============
+COM_ParseToken_VM_Tokenize
+
+Parse a token out of a string
+==============
+*/
+int COM_ParseToken_VM_Tokenize(const char **datapointer, qboolean returnnewline)
+{
+ int len;
+ int c;
+ const char *data = *datapointer;
+
+ len = 0;
+ com_token[0] = 0;
+
+ if (!data)
+ {
+ *datapointer = NULL;
+ return false;
+ }
+
+// skip whitespace
+skipwhite:
+ // line endings:
+ // UNIX: \n
+ // Mac: \r
+ // Windows: \r\n
+ for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
+ {
+ if (*data == 0)
{
- if (len >= (int)sizeof(com_token) - 1)
+ // end of file
+ *datapointer = NULL;
+ return false;
+ }
+ }
+
+ // handle Windows line ending
+ if (data[0] == '\r' && data[1] == '\n')
+ data++;
+
+ if (data[0] == '/' && data[1] == '/')
+ {
+ // comment
+ while (*data && *data != '\n' && *data != '\r')
+ data++;
+ goto skipwhite;
+ }
+ else if (data[0] == '/' && data[1] == '*')
+ {
+ // comment
+ data++;
+ while (*data && (data[0] != '*' || data[1] != '/'))
+ data++;
+ if (*data)
+ data++;
+ if (*data)
+ data++;
+ goto skipwhite;
+ }
+ else if (*data == '\"' || *data == '\'')
+ {
+ char quote = *data;
+ // quoted string
+ for (data++;*data && *data != quote;data++)
+ {
+ c = *data;
+ if (*data == '\\')
{
- com_token[0] = 0;
- *datapointer = NULL;
- return false;
+ data++;
+ c = *data;
+ if (c == 'n')
+ c = '\n';
+ else if (c == 't')
+ c = '\t';
}
- com_token[len++] = *data;
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = c;
}
com_token[len] = 0;
+ if (*data == quote)
+ data++;
+ *datapointer = data;
+ return true;
+ }
+ else if (*data == '\r')
+ {
+ // translate Mac line ending to UNIX
+ com_token[len++] = '\n';data++;
+ com_token[len] = 0;
+ *datapointer = data;
+ return true;
+ }
+ else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == ':' || *data == ',' || *data == ';')
+ {
+ // single character
+ com_token[len++] = *data++;
+ com_token[len] = 0;
+ *datapointer = data;
+ return true;
+ }
+ else
+ {
+ // regular word
+ for (;*data > ' ' && *data != ',' && *data != ';' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = *data;
+ com_token[len] = 0;
*datapointer = data;
return true;
}
/*
==============
-COM_ParseTokenConsole
+COM_ParseToken_Console
Parse a token out of a string, behaving like the qwcl console
==============
*/
-int COM_ParseTokenConsole(const char **datapointer)
+int COM_ParseToken_Console(const char **datapointer)
{
int len;
const char *data = *datapointer;
else if (*data == '\"')
{
// quoted string
- for (data++;*data != '\"';data++)
+ for (data++;*data && *data != '\"';data++)
{
- if (!*data || len >= (int)sizeof(com_token) - 1)
- {
- com_token[0] = 0;
- *datapointer = NULL;
- return false;
- }
- com_token[len++] = *data;
+ // allow escaped " and \ case
+ if (*data == '\\' && (data[1] == '\"' || data[1] == '\\'))
+ data++;
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = *data;
}
com_token[len] = 0;
- *datapointer = data+1;
+ if (*data == '\"')
+ data++;
+ *datapointer = data;
}
else
{
// regular word
for (;*data > ' ';data++)
- {
- if (len >= (int)sizeof(com_token) - 1)
- {
- com_token[0] = 0;
- *datapointer = NULL;
- return false;
- }
- com_token[len++] = *data;
- }
+ if (len < (int)sizeof(com_token) - 1)
+ com_token[len++] = *data;
com_token[len] = 0;
*datapointer = data;
}
return 0;
}
-/*
-================
-COM_CheckRegistered
-
-Looks for the pop.txt file and verifies it.
-Sets the "registered" cvar.
-Immediately exits out if an alternate game was attempted to be started without
-being registered.
-================
-*/
-void COM_CheckRegistered (void)
-{
- Cvar_Set ("cmdline", com_cmdline);
-
- if (gamemode == GAME_NORMAL && !FS_FileExists("gfx/pop.lmp"))
- {
- if (fs_modified)
- Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
- else
- Con_Print("Playing shareware version.\n");
- return;
- }
-
- Cvar_Set ("registered", "1");
- Con_Print("Playing registered version.\n");
-}
-
-
-/*
-================
-COM_InitArgv
-================
-*/
-void COM_InitArgv (void)
-{
- int i, j, n;
- // reconstitute the command line for the cmdline externally visible cvar
- n = 0;
- for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
- {
- i = 0;
- if (strstr(com_argv[j], " "))
- {
- // arg contains whitespace, store quotes around it
- com_cmdline[n++] = '\"';
- while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i])
- com_cmdline[n++] = com_argv[j][i++];
- com_cmdline[n++] = '\"';
- }
- else
- {
- while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i])
- com_cmdline[n++] = com_argv[j][i++];
- }
- if (n < ((int)sizeof(com_cmdline) - 1))
- com_cmdline[n++] = ' ';
- else
- break;
- }
- com_cmdline[n] = 0;
-}
-
-
//===========================================================================
// Game mods
// GAME_ZYMOTIC
// COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic
{ "zymotic", "-zymotic", "Zymotic", "basezym", NULL, "zymotic", "zymotic" },
-// GAME_FNIGGIUM
-// COMMANDLINEOPTION: Game: -fniggium runs the post apocalyptic melee RPG Fniggium
-{ "fniggium", "-fniggium", "Fniggium", "data", NULL, "fniggium", "fniggium" },
// GAME_SETHERAL
// COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral
{ "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" },
// GAME_DEFEATINDETAIL2
// COMMANDLINEOPTION: Game: -did2 runs the game Defeat In Detail 2
{ "did2", "-did2", "Defeat In Detail 2", "data", NULL, "did2_", "did2" },
+// GAME_DARSANA
+// COMMANDLINEOPTION: Game: -darsana runs the game Darsana
+{ "darsana", "-darsana", "Darsana", "ddata", NULL, "darsana", "darsana" },
+// GAME_CONTAGIONTHEORY
+// COMMANDLINEOPTION: Game: -contagiontheory runs the game Contagion Theory
+{ "contagiontheory", "-contagiontheory", "Contagion Theory", "ctdata", NULL, "ct", "contagiontheory" },
};
void COM_InitGameType (void)
*/
void COM_Init_Commands (void)
{
+ int i, j, n;
+ char com_cmdline[MAX_INPUTLINE];
+
Cvar_RegisterVariable (®istered);
Cvar_RegisterVariable (&cmdline);
+
+ // reconstitute the command line for the cmdline externally visible cvar
+ n = 0;
+ for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
+ {
+ i = 0;
+ if (strstr(com_argv[j], " "))
+ {
+ // arg contains whitespace, store quotes around it
+ com_cmdline[n++] = '\"';
+ while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i])
+ com_cmdline[n++] = com_argv[j][i++];
+ com_cmdline[n++] = '\"';
+ }
+ else
+ {
+ while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i])
+ com_cmdline[n++] = com_argv[j][i++];
+ }
+ if (n < ((int)sizeof(com_cmdline) - 1))
+ com_cmdline[n++] = ' ';
+ else
+ break;
+ }
+ com_cmdline[n] = 0;
+ Cvar_Set ("cmdline", com_cmdline);
}
/*
return argc;
}
+/*
+============
+COM_StringLengthNoColors
+
+calculates the visible width of a color coded string.
+
+*valid is filled with TRUE if the string is a valid colored string (that is, if
+it does not end with an unfinished color code). If it gets filled with FALSE, a
+fix would be adding a STRING_COLOR_TAG at the end of the string.
+
+valid can be set to NULL if the caller doesn't care.
+
+For size_s, specify the maximum number of characters from s to use, or 0 to use
+all characters until the zero terminator.
+============
+*/
+size_t
+COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid)
+{
+ const char *end = size_s ? (s + size_s) : NULL;
+ size_t len = 0;
+ for(;;)
+ {
+ switch((s == end) ? 0 : *s)
+ {
+ case 0:
+ if(valid)
+ *valid = TRUE;
+ return len;
+ case STRING_COLOR_TAG:
+ ++s;
+ switch((s == end) ? 0 : *s)
+ {
+ case 0: // ends with unfinished color code!
+ ++len;
+ if(valid)
+ *valid = FALSE;
+ return len;
+ case STRING_COLOR_TAG: // escaped ^
+ ++len;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9': // color code
+ break;
+ default: // not a color code
+ ++len; // STRING_COLOR_TAG
+ ++len; // the character
+ break;
+ }
+ break;
+ default:
+ ++len;
+ break;
+ }
+ ++s;
+ }
+ // never get here
+}
+
+/*
+============
+COM_StringDecolorize
+
+removes color codes from a string.
+
+If escape_carets is true, the resulting string will be safe for printing. If
+escape_carets is false, the function will just strip color codes (for logging
+for example).
+
+If the output buffer size did not suffice for converting, the function returns
+FALSE. Generally, if escape_carets is false, the output buffer needs
+strlen(str)+1 bytes, and if escape_carets is true, it can need strlen(str)+2
+bytes. In any case, the function makes sure that the resulting string is
+zero terminated.
+
+For size_in, specify the maximum number of characters from in to use, or 0 to use
+all characters until the zero terminator.
+============
+*/
+qboolean
+COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qboolean escape_carets)
+{
+#define APPEND(ch) do { if(--size_out) { *out++ = (ch); } else { *out++ = 0; return FALSE; } } while(0)
+ const char *end = size_in ? (in + size_in) : NULL;
+ if(size_out < 1)
+ return FALSE;
+ for(;;)
+ {
+ switch((in == end) ? 0 : *in)
+ {
+ case 0:
+ *out++ = 0;
+ return TRUE;
+ case STRING_COLOR_TAG:
+ ++in;
+ switch((in == end) ? 0 : *in)
+ {
+ case 0: // ends with unfinished color code!
+ APPEND(STRING_COLOR_TAG);
+ // finish the code by appending another caret when escaping
+ if(escape_carets)
+ APPEND(STRING_COLOR_TAG);
+ *out++ = 0;
+ return TRUE;
+ case STRING_COLOR_TAG: // escaped ^
+ APPEND(STRING_COLOR_TAG);
+ // append a ^ twice when escaping
+ if(escape_carets)
+ APPEND(STRING_COLOR_TAG);
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9': // color code
+ break;
+ default: // not a color code
+ APPEND(STRING_COLOR_TAG);
+ APPEND(*in);
+ break;
+ }
+ break;
+ default:
+ APPEND(*in);
+ break;
+ }
+ ++in;
+ }
+ // never get here
+#undef APPEND
+}
+
// written by Elric, thanks Elric!
char *SearchInfostring(const char *infostring, const char *key)
{
for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos2++);
for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos2++);
}
- if (bufferlength <= 1 + strlen(key) + 1 + strlen(value) + strlen(buffer + pos2))
+ if (bufferlength <= pos + 1 + strlen(key) + 1 + strlen(value) + strlen(buffer + pos2))
{
Con_Printf("InfoString_SetValue: no room for \"%s\" \"%s\" in infostring\n", key, value);
return;
else
{
// just remove the key from the text
- strcpy(buffer + pos, buffer + pos2);
+ strlcpy(buffer + pos, buffer + pos2, bufferlength - pos);
}
}