*/
// common.c -- misc functions used in client and server
-#include "quakedef.h"
-
#include <stdlib.h>
#include <fcntl.h>
#ifndef WIN32
#include <unistd.h>
#endif
+#include "quakedef.h"
+
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"};
char com_token[MAX_INPUTLINE];
int com_argc;
const char **com_argv;
+int com_selffd = -1;
gamemode_t gamemode;
const char *gamename;
============================================================================
*/
-short ShortSwap (short l)
-{
- unsigned char b1,b2;
-
- b1 = l&255;
- b2 = (l>>8)&255;
- return (b1<<8) + b2;
+float BuffBigFloat (const unsigned char *buffer)
+{
+ union
+ {
+ float f;
+ unsigned int i;
+ }
+ u;
+ u.i = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
+ return u.f;
}
-int LongSwap (int l)
+int BuffBigLong (const unsigned char *buffer)
{
- unsigned char b1,b2,b3,b4;
-
- b1 = l&255;
- b2 = (l>>8)&255;
- b3 = (l>>16)&255;
- b4 = (l>>24)&255;
+ return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
+}
- return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+short BuffBigShort (const unsigned char *buffer)
+{
+ return (buffer[0] << 8) | buffer[1];
}
-float FloatSwap (float f)
+float BuffLittleFloat (const unsigned char *buffer)
{
union
{
- float f;
- unsigned char b[4];
- } dat1, dat2;
-
-
- dat1.f = f;
- dat2.b[0] = dat1.b[3];
- dat2.b[1] = dat1.b[2];
- dat2.b[2] = dat1.b[1];
- dat2.b[3] = dat1.b[0];
- return dat2.f;
+ float f;
+ unsigned int i;
+ }
+ u;
+ u.i = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
+ return u.f;
}
+int BuffLittleLong (const unsigned char *buffer)
+{
+ return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
+}
-// Extract integers from buffers
-
-unsigned int BuffBigLong (const unsigned char *buffer)
+short BuffLittleShort (const unsigned char *buffer)
{
- return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
+ return (buffer[1] << 8) | buffer[0];
}
-unsigned short BuffBigShort (const unsigned char *buffer)
+void StoreBigLong (unsigned char *buffer, unsigned int i)
{
- return (buffer[0] << 8) | buffer[1];
+ buffer[0] = (i >> 24) & 0xFF;
+ buffer[1] = (i >> 16) & 0xFF;
+ buffer[2] = (i >> 8) & 0xFF;
+ buffer[3] = i & 0xFF;
}
-unsigned int BuffLittleLong (const unsigned char *buffer)
+void StoreBigShort (unsigned char *buffer, unsigned short i)
{
- return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
+ buffer[0] = (i >> 8) & 0xFF;
+ buffer[1] = i & 0xFF;
}
-unsigned short BuffLittleShort (const unsigned char *buffer)
+void StoreLittleLong (unsigned char *buffer, unsigned int i)
{
- return (buffer[1] << 8) | buffer[0];
+ buffer[0] = i & 0xFF;
+ buffer[1] = (i >> 8) & 0xFF;
+ buffer[2] = (i >> 16) & 0xFF;
+ buffer[3] = (i >> 24) & 0xFF;
}
+void StoreLittleShort (unsigned char *buffer, unsigned short i)
+{
+ buffer[0] = i & 0xFF;
+ buffer[1] = (i >> 8) & 0xFF;
+}
/*
============================================================================
// attention, it has been eradicated from here, its only (former) use in
// all of darkplaces.
-static char *hexchar = "0123456789ABCDEF";
+static const char *hexchar = "0123456789ABCDEF";
void Com_HexDumpToConsole(const unsigned char *data, int size)
{
int i, j, n;
*cur++ = STRING_COLOR_TAG;
*cur++ = STRING_COLOR_TAG;
}
- else if (d[j] >= ' ')
+ else if (d[j] >= (unsigned char) ' ')
*cur++ = d[j];
else
*cur++ = '.';
for the char 0 to initialize a clean state, and then once with the string " "
(a space) so the routine knows how long a space is.
+In case no single character fits into the given width, the wordWidth function
+must return the width of exactly one character.
+
Wrapped lines get the isContinuation flag set and are continuationWidth less wide.
The sum of the return values of the processLine function will be returned.
result += processLine(passthroughPL, startOfLine, cursor - startOfLine, spaceUsedInLine, isContinuation);
isContinuation = false;
goto out;
- break;
case '\n': // end of line
result += processLine(passthroughPL, startOfLine, cursor - startOfLine, spaceUsedInLine, isContinuation);
isContinuation = false;
}
out_inner:
spaceUsedForWord = wordWidth(passthroughCW, cursor, &wordLen, maxWidth - continuationWidth); // this may have reduced wordLen when it won't fit - but this is GOOD. TODO fix words that do fit in a non-continuation line
- if(wordLen < 1)
+ if(wordLen < 1) // cannot happen according to current spec of wordWidth
{
wordLen = 1;
spaceUsedForWord = maxWidth + 1; // too high, forces it in a line of itself
// UNIX: \n
// Mac: \r
// Windows: \r\n
- for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
+ for (;ISWHITESPACE(*data) && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
{
if (*data == 0)
{
else
{
// regular word
- for (;*data > ' ';data++)
+ for (;!ISWHITESPACE(*data);data++)
if (len < (int)sizeof(com_token) - 1)
com_token[len++] = *data;
com_token[len] = 0;
// UNIX: \n
// Mac: \r
// Windows: \r\n
- for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
+ for (;ISWHITESPACE(*data) && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
{
if (*data == 0)
{
else
{
// regular word
- for (;*data > ' ' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
+ for (;!ISWHITESPACE(*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;
// UNIX: \n
// Mac: \r
// Windows: \r\n
- for (;*data <= ' ' && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
+ for (;ISWHITESPACE(*data) && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
{
if (*data == 0)
{
else
{
// regular word
- for (;*data > ' ' && *data != ',' && *data != ';' && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
+ for (;!ISWHITESPACE(*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;
// skip whitespace
skipwhite:
- for (;*data <= ' ';data++)
+ for (;ISWHITESPACE(*data);data++)
{
if (*data == 0)
{
else
{
// regular word
- for (;*data > ' ';data++)
+ for (;!ISWHITESPACE(*data);data++)
if (len < (int)sizeof(com_token) - 1)
com_token[len++] = *data;
com_token[len] = 0;
typedef struct gamemode_info_s
{
- const char* prog_name;
- const char* cmdline;
- const char* gamename;
- const char* gamedirname1;
- const char* gamedirname2;
- const char* gamescreenshotname;
- const char* gameuserdirname;
+ const char* prog_name; // not null
+ const char* cmdline; // not null
+ const char* gamename; // not null
+ const char* gamedirname1; // not null
+ const char* gamedirname2; // null
+ const char* gamescreenshotname; // not nul
+ const char* gameuserdirname; // not null
} gamemode_info_t;
-static const gamemode_info_t gamemode_info [] =
-{// prog_name cmdline gamename gamedirname gamescreenshotname
+static const gamemode_info_t gamemode_info [GAME_COUNT] =
+{// prog_name cmdline gamename basegame modgame screenshotprefix userdir
// GAME_NORMAL
// COMMANDLINEOPTION: Game: -quake runs the game Quake (default)
// GAME_NEXUIZ
// COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz
{ "nexuiz", "-nexuiz", "Nexuiz", "data", NULL, "nexuiz", "nexuiz" },
+// GAME_XONOTIC
+// COMMANDLINEOPTION: Game: -xonotic runs the multiplayer game Xonotic
+{ "xonotic", "-xonotic", "Xonotic", "data", NULL, "xonotic", "xonotic" },
// GAME_TRANSFUSION
// COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake)
{ "transfusion", "-transfusion", "Transfusion", "basetf", NULL, "transfusion", "transfusion" },
// GAME_CONTAGIONTHEORY
// COMMANDLINEOPTION: Game: -contagiontheory runs the game Contagion Theory
{ "contagiontheory", "-contagiontheory", "Contagion Theory", "ctdata", NULL, "ct", "contagiontheory" },
+// GAME_EDU2P
+// COMMANDLINEOPTION: Game: -edu2p runs the game Edu2 prototype
+{ "edu2p", "-edu2p", "EDU2 Prototype", "id1", "edu2", "edu2_p", "edu2prototype" },
+// GAME_PROPHECY
+// COMMANDLINEOPTION: Game: -prophecy runs the game Prophecy
+{ "prophecy", "-prophecy", "Prophecy", "data", NULL, "prophecy", "prophecy" },
+// GAME_BLOODOMNICIDE
+// COMMANDLINEOPTION: Game: -omnicide runs the game Blood Omnicide
+{ "omnicide", "-omnicide", "Blood Omnicide", "kain", NULL, "omnicide", "omnicide" },
+// GAME_STEELSTORM
+// COMMANDLINEOPTION: Game: -steelstorm runs the game Steel Storm
+{ "steelstorm", "-steelstorm", "Steel-Storm", "gamedata", NULL, "ss", "steelstorm" },
+// GAME_STRAPBOMB
+// COMMANDLINEOPTION: Game: -strapbomb runs the game Strap-on-bomb Car
+{ "strapbomb", "-strapbomb", "Strap-on-bomb Car", "id1", NULL, "strap", "strapbomb" },
+// GAME_MOONHELM
+// COMMANDLINEOPTION: Game: -moonhelm runs the game MoonHelm
+{ "moonhelm", "-moonhelm", "MoonHelm", "data", NULL, "mh", "moonhelm" },
};
void COM_InitGameType (void)
{
char name [MAX_OSPATH];
unsigned int i;
+ int t;
FS_StripExtension (com_argv[0], name, sizeof (name));
COM_ToLowerString (name, name, sizeof (name));
gamedirname2 = gamemode_info[gamemode].gamedirname2;
gamescreenshotname = gamemode_info[gamemode].gamescreenshotname;
gameuserdirname = gamemode_info[gamemode].gameuserdirname;
+
+ if((t = COM_CheckParm("-customgamename")) && t + 1 < com_argc)
+ gamename = com_argv[t+1];
+ if((t = COM_CheckParm("-customgamedirname1")) && t + 1 < com_argc)
+ gamedirname1 = com_argv[t+1];
+ if((t = COM_CheckParm("-customgamedirname2")) && t + 1 < com_argc)
+ gamedirname2 = *com_argv[t+1] ? com_argv[t+1] : NULL;
+ if((t = COM_CheckParm("-customgamescreenshotname")) && t + 1 < com_argc)
+ gamescreenshotname = com_argv[t+1];
+ if((t = COM_CheckParm("-customgameuserdirname")) && t + 1 < com_argc)
+ gameuserdirname = com_argv[t+1];
}
{
int result;
+#if _MSC_VER >= 1400
+ result = _vsnprintf_s (buffer, buffersize, _TRUNCATE, format, args);
+#else
result = vsnprintf (buffer, buffersize, format, args);
+#endif
if (result < 0 || (size_t)result >= buffersize)
{
buffer[buffersize - 1] = '\0';
commentprefixlength = (int)strlen(commentprefix);
while (*l && *l != '\n' && *l != '\r')
{
- if (*l > ' ')
+ if (!ISWHITESPACE(*l))
{
if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
{
}
else
{
- while (*l > ' ')
+ while (!ISWHITESPACE(*l))
{
if (tokenbuf >= tokenbufend)
return -1;
++s;
switch((s == end) ? 0 : *s)
{
+ case STRING_COLOR_RGB_TAG_CHAR:
+ if (s+1 != end && isxdigit(s[1]) &&
+ s+2 != end && isxdigit(s[2]) &&
+ s+3 != end && isxdigit(s[3]) )
+ {
+ s+=3;
+ break;
+ }
+ ++len; // STRING_COLOR_TAG
+ ++len; // STRING_COLOR_RGB_TAG_CHAR
+ break;
case 0: // ends with unfinished color code!
++len;
if(valid)
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
+strlen(str)+1 bytes, and if escape_carets is true, it can need strlen(str)*1.5+2
bytes. In any case, the function makes sure that the resulting string is
zero terminated.
++in;
switch((in == end) ? 0 : *in)
{
+ case STRING_COLOR_RGB_TAG_CHAR:
+ if (in+1 != end && isxdigit(in[1]) &&
+ in+2 != end && isxdigit(in[2]) &&
+ in+3 != end && isxdigit(in[3]) )
+ {
+ in+=3;
+ break;
+ }
+ APPEND(STRING_COLOR_TAG);
+ if(escape_carets)
+ APPEND(STRING_COLOR_TAG);
+ APPEND(STRING_COLOR_RGB_TAG_CHAR);
+ break;
case 0: // ends with unfinished color code!
APPEND(STRING_COLOR_TAG);
// finish the code by appending another caret when escaping
size_t keylength;
if (!key)
key = "";
- if (!value)
- value = "";
keylength = strlen(key);
if (valuelength < 1 || !value)
{
// set the key/value and append the remaining text
char tempbuffer[4096];
strlcpy(tempbuffer, buffer + pos2, sizeof(tempbuffer));
- sprintf(buffer + pos, "\\%s\\%s%s", key, value, tempbuffer);
+ dpsnprintf(buffer + pos, bufferlength - pos, "\\%s\\%s%s", key, value, tempbuffer);
}
else
{
}
#endif // #ifndef HAVE_STRLCPY
+
+void FindFraction(double val, int *num, int *denom, int denomMax)
+{
+ int i;
+ double bestdiff;
+ // initialize
+ bestdiff = fabs(val);
+ *num = 0;
+ *denom = 1;
+
+ for(i = 1; i <= denomMax; ++i)
+ {
+ int inum = (int) floor(0.5 + val * i);
+ double diff = fabs(val - inum / (double)i);
+ if(diff < bestdiff)
+ {
+ bestdiff = diff;
+ *num = inum;
+ *denom = i;
+ }
+ }
+}
+
+// decodes an XPM from C syntax
+char **XPM_DecodeString(const char *in)
+{
+ static char *tokens[257];
+ static char lines[257][512];
+ size_t line = 0;
+
+ // skip until "{" token
+ while(COM_ParseToken_QuakeC(&in, false) && strcmp(com_token, "{"));
+
+ // now, read in succession: string, comma-or-}
+ while(COM_ParseToken_QuakeC(&in, false))
+ {
+ tokens[line] = lines[line];
+ strlcpy(lines[line++], com_token, sizeof(lines[0]));
+ if(!COM_ParseToken_QuakeC(&in, false))
+ return NULL;
+ if(!strcmp(com_token, "}"))
+ break;
+ if(strcmp(com_token, ","))
+ return NULL;
+ if(line >= sizeof(tokens) / sizeof(tokens[0]))
+ return NULL;
+ }
+
+ return tokens;
+}
+
+static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static void base64_3to4(const unsigned char *in, unsigned char *out, int bytes)
+{
+ unsigned char i0 = (bytes > 0) ? in[0] : 0;
+ unsigned char i1 = (bytes > 1) ? in[1] : 0;
+ unsigned char i2 = (bytes > 2) ? in[2] : 0;
+ unsigned char o0 = base64[i0 >> 2];
+ unsigned char o1 = base64[((i0 << 4) | (i1 >> 4)) & 077];
+ unsigned char o2 = base64[((i1 << 2) | (i2 >> 6)) & 077];
+ unsigned char o3 = base64[i2 & 077];
+ out[0] = (bytes > 0) ? o0 : '?';
+ out[1] = (bytes > 0) ? o1 : '?';
+ out[2] = (bytes > 1) ? o2 : '=';
+ out[3] = (bytes > 2) ? o3 : '=';
+}
+
+size_t base64_encode(unsigned char *buf, size_t buflen, size_t outbuflen)
+{
+ size_t blocks, i;
+ // expand the out-buffer
+ blocks = (buflen + 2) / 3;
+ if(blocks*4 > outbuflen)
+ return 0;
+ for(i = blocks; i > 0; )
+ {
+ --i;
+ base64_3to4(buf + 3*i, buf + 4*i, buflen - 3*i);
+ }
+ return blocks * 4;
+}