]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - common.c
common: Move filematch headers to new filematch.h
[xonotic/darkplaces.git] / common.c
index e0cffe48120f4790c34348817b8f509a3fd87321..8db1f27025ab61c545583f0f2cba1821ab41ff6d 100644 (file)
--- a/common.c
+++ b/common.c
@@ -1,5 +1,6 @@
 /*
 Copyright (C) 1996-1997 Id Software, Inc.
+Copyright (C) 2000-2020 DarkPlaces contributors
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
@@ -19,542 +20,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 // common.c -- misc functions used in client and server
 
-#include "quakedef.h"
-
 #include <stdlib.h>
 #include <fcntl.h>
 #ifndef WIN32
 #include <unistd.h>
 #endif
 
-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;
-
-gamemode_t gamemode;
-const char *gamename;
-const char *gamedirname1;
-const char *gamedirname2;
-const char *gamescreenshotname;
-const char *gameuserdirname;
-char com_modname[MAX_OSPATH] = "";
-
-
-/*
-============================================================================
-
-                                       BYTE ORDER FUNCTIONS
-
-============================================================================
-*/
-
-short   ShortSwap (short l)
-{
-       unsigned char    b1,b2;
-
-       b1 = l&255;
-       b2 = (l>>8)&255;
-
-       return (b1<<8) + b2;
-}
-
-int    LongSwap (int l)
-{
-       unsigned char    b1,b2,b3,b4;
-
-       b1 = l&255;
-       b2 = (l>>8)&255;
-       b3 = (l>>16)&255;
-       b4 = (l>>24)&255;
-
-       return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-float FloatSwap (float f)
-{
-       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;
-}
-
-
-// Extract integers from buffers
-
-unsigned int BuffBigLong (const unsigned char *buffer)
-{
-       return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
-}
-
-unsigned short BuffBigShort (const unsigned char *buffer)
-{
-       return (buffer[0] << 8) | buffer[1];
-}
-
-unsigned int BuffLittleLong (const unsigned char *buffer)
-{
-       return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
-}
-
-unsigned short BuffLittleShort (const unsigned char *buffer)
-{
-       return (buffer[1] << 8) | buffer[0];
-}
-
-
-/*
-============================================================================
-
-                                       CRC FUNCTIONS
-
-============================================================================
-*/
-
-// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
-// and the initial and final xor values shown below...  in other words, the
-// CCITT standard CRC used by XMODEM
-
-#define CRC_INIT_VALUE 0xffff
-#define CRC_XOR_VALUE  0x0000
-
-static unsigned short crctable[256] =
-{
-       0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
-       0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
-       0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
-       0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
-       0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
-       0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
-       0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
-       0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
-       0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
-       0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
-       0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
-       0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
-       0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
-       0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
-       0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
-       0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
-       0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
-       0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
-       0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
-       0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
-       0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
-       0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
-       0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
-       0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
-       0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
-       0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
-       0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
-       0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
-       0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
-       0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
-       0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
-       0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
-};
-
-unsigned short CRC_Block(const unsigned char *data, size_t size)
-{
-       unsigned short crc = CRC_INIT_VALUE;
-       while (size--)
-               crc = (crc << 8) ^ crctable[(crc >> 8) ^ (*data++)];
-       return crc ^ CRC_XOR_VALUE;
-}
-
-unsigned short CRC_Block_CaseInsensitive(const unsigned char *data, size_t size)
-{
-       unsigned short crc = CRC_INIT_VALUE;
-       while (size--)
-               crc = (crc << 8) ^ crctable[(crc >> 8) ^ (tolower(*data++))];
-       return crc ^ CRC_XOR_VALUE;
-}
-
-// QuakeWorld
-static unsigned char chktbl[1024 + 4] =
-{
-       0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01,
-       0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a,
-       0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58,
-       0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3,
-       0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b,
-       0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36,
-       0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8,
-       0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27,
-       0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd,
-       0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63,
-       0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2,
-       0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d,
-       0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65,
-       0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f,
-       0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f,
-       0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42,
-       0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59,
-       0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9,
-       0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69,
-       0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba,
-       0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85,
-       0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4,
-       0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8,
-       0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa,
-       0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05,
-       0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7,
-       0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a,
-       0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb,
-       0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b,
-       0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d,
-       0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce,
-       0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3,
-
-       // map checksum goes here
-       0x00,0x00,0x00,0x00
-};
-
-// QuakeWorld
-unsigned char COM_BlockSequenceCRCByteQW(unsigned char *base, int length, int sequence)
-{
-       unsigned char *p;
-       unsigned char chkb[60 + 4];
-
-       p = chktbl + (sequence % (sizeof(chktbl) - 8));
-
-       if (length > 60)
-               length = 60;
-       memcpy(chkb, base, length);
-
-       chkb[length] = (sequence & 0xff) ^ p[0];
-       chkb[length+1] = p[1];
-       chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2];
-       chkb[length+3] = p[3];
-
-       return CRC_Block(chkb, length + 4) & 0xff;
-}
-
-/*
-==============================================================================
-
-                       MESSAGE IO FUNCTIONS
-
-Handles byte ordering and avoids alignment errors
-==============================================================================
-*/
-
-//
-// writing functions
-//
-
-void MSG_WriteChar (sizebuf_t *sb, int c)
-{
-       unsigned char    *buf;
-
-       buf = SZ_GetSpace (sb, 1);
-       buf[0] = c;
-}
-
-void MSG_WriteByte (sizebuf_t *sb, int c)
-{
-       unsigned char    *buf;
-
-       buf = SZ_GetSpace (sb, 1);
-       buf[0] = c;
-}
-
-void MSG_WriteShort (sizebuf_t *sb, int c)
-{
-       unsigned char    *buf;
-
-       buf = SZ_GetSpace (sb, 2);
-       buf[0] = c&0xff;
-       buf[1] = c>>8;
-}
-
-void MSG_WriteLong (sizebuf_t *sb, int c)
-{
-       unsigned char    *buf;
-
-       buf = SZ_GetSpace (sb, 4);
-       buf[0] = c&0xff;
-       buf[1] = (c>>8)&0xff;
-       buf[2] = (c>>16)&0xff;
-       buf[3] = c>>24;
-}
-
-void MSG_WriteFloat (sizebuf_t *sb, float f)
-{
-       union
-       {
-               float   f;
-               int     l;
-       } dat;
-
-
-       dat.f = f;
-       dat.l = LittleLong (dat.l);
-
-       SZ_Write (sb, (unsigned char *)&dat.l, 4);
-}
-
-void MSG_WriteString (sizebuf_t *sb, const char *s)
-{
-       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 && *s)
-               SZ_Write (sb, (unsigned char *)s, (int)strlen(s));
-}
-
-void MSG_WriteCoord13i (sizebuf_t *sb, float f)
-{
-       if (f >= 0)
-               MSG_WriteShort (sb, (int)(f * 8.0 + 0.5));
-       else
-               MSG_WriteShort (sb, (int)(f * 8.0 - 0.5));
-}
-
-void MSG_WriteCoord16i (sizebuf_t *sb, float f)
-{
-       if (f >= 0)
-               MSG_WriteShort (sb, (int)(f + 0.5));
-       else
-               MSG_WriteShort (sb, (int)(f - 0.5));
-}
-
-void MSG_WriteCoord32f (sizebuf_t *sb, float f)
-{
-       MSG_WriteFloat (sb, f);
-}
-
-void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
-{
-       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);
-       else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
-               MSG_WriteCoord16i (sb, f);
-       else
-               MSG_WriteCoord32f (sb, f);
-}
-
-void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
-{
-       MSG_WriteCoord (sb, v[0], protocol);
-       MSG_WriteCoord (sb, v[1], protocol);
-       MSG_WriteCoord (sb, v[2], protocol);
-}
-
-// LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
-void MSG_WriteAngle8i (sizebuf_t *sb, float f)
-{
-       if (f >= 0)
-               MSG_WriteByte (sb, (int)(f*(256.0/360.0) + 0.5) & 255);
-       else
-               MSG_WriteByte (sb, (int)(f*(256.0/360.0) - 0.5) & 255);
-}
-
-void MSG_WriteAngle16i (sizebuf_t *sb, float f)
-{
-       if (f >= 0)
-               MSG_WriteShort (sb, (int)(f*(65536.0/360.0) + 0.5) & 65535);
-       else
-               MSG_WriteShort (sb, (int)(f*(65536.0/360.0) - 0.5) & 65535);
-}
-
-void MSG_WriteAngle32f (sizebuf_t *sb, float f)
-{
-       MSG_WriteFloat (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_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);
-}
-
-//
-// reading functions
-//
-int msg_readcount;
-qboolean msg_badread;
-
-void MSG_BeginReading (void)
-{
-       msg_readcount = 0;
-       msg_badread = false;
-}
-
-int MSG_ReadLittleShort (void)
-{
-       if (msg_readcount+2 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-       msg_readcount += 2;
-       return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
-}
-
-int MSG_ReadBigShort (void)
-{
-       if (msg_readcount+2 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-       msg_readcount += 2;
-       return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
-}
-
-int MSG_ReadLittleLong (void)
-{
-       if (msg_readcount+4 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-       msg_readcount += 4;
-       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);
-}
-
-int MSG_ReadBigLong (void)
-{
-       if (msg_readcount+4 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-       msg_readcount += 4;
-       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];
-}
-
-float MSG_ReadLittleFloat (void)
-{
-       union
-       {
-               float f;
-               int l;
-       } dat;
-       if (msg_readcount+4 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-       msg_readcount += 4;
-       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);
-       return dat.f;
-}
-
-float MSG_ReadBigFloat (void)
-{
-       union
-       {
-               float f;
-               int l;
-       } dat;
-       if (msg_readcount+4 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-       msg_readcount += 4;
-       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];
-       return dat.f;
-}
-
-char *MSG_ReadString (void)
-{
-       static char string[MAX_INPUTLINE];
-       int l,c;
-       for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadByte()) != -1 && c != 0;l++)
-               string[l] = c;
-       string[l] = 0;
-       return string;
-}
-
-int MSG_ReadBytes (int numbytes, unsigned char *out)
-{
-       int l, c;
-       for (l = 0;l < numbytes && (c = MSG_ReadByte()) != -1;l++)
-               out[l] = c;
-       return l;
-}
-
-float MSG_ReadCoord13i (void)
-{
-       return MSG_ReadLittleShort() * (1.0/8.0);
-}
-
-float MSG_ReadCoord16i (void)
-{
-       return (signed short) MSG_ReadLittleShort();
-}
-
-float MSG_ReadCoord32f (void)
-{
-       return MSG_ReadLittleFloat();
-}
-
-float MSG_ReadCoord (protocolversion_t protocol)
-{
-       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();
-       else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
-               return MSG_ReadCoord16i();
-       else
-               return MSG_ReadCoord32f();
-}
-
-void MSG_ReadVector (float *v, protocolversion_t protocol)
-{
-       v[0] = MSG_ReadCoord(protocol);
-       v[1] = MSG_ReadCoord(protocol);
-       v[2] = MSG_ReadCoord(protocol);
-}
-
-// LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
-float MSG_ReadAngle8i (void)
-{
-       return (signed char) MSG_ReadByte () * (360.0/256.0);
-}
-
-float MSG_ReadAngle16i (void)
-{
-       return (signed short)MSG_ReadShort () * (360.0/65536.0);
-}
+#include "quakedef.h"
+#include "utf8lib.h"
 
-float MSG_ReadAngle32f (void)
-{
-       return MSG_ReadFloat ();
-}
+cvar_t registered = {CF_CLIENT | CF_SERVER, "registered","0", "indicates if this is running registered quake (whether gfx/pop.lmp was found)"};
+cvar_t cmdline = {CF_CLIENT | CF_SERVER, "cmdline","0", "contains commandline the engine was launched with"};
 
-float MSG_ReadAngle (protocolversion_t protocol)
-{
-       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 ();
-}
+// FIXME: Find a better place for these.
+cvar_t cl_playermodel = {CF_CLIENT | CF_SERVER | CF_USERINFO | CF_ARCHIVE, "playermodel", "", "current player model in Nexuiz/Xonotic"};
+cvar_t cl_playerskin = {CF_CLIENT | CF_SERVER | CF_USERINFO | CF_ARCHIVE, "playerskin", "", "current player skin in Nexuiz/Xonotic"};
 
+char com_token[MAX_INPUTLINE];
 
 //===========================================================================
 
@@ -591,11 +73,11 @@ void SZ_Write (sizebuf_t *buf, const unsigned char *data, int length)
        memcpy (SZ_GetSpace(buf,length),data,length);
 }
 
-// LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
+// LadyHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
 // 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;
@@ -643,7 +125,7 @@ void Com_HexDumpToConsole(const unsigned char *data, int size)
                                        *cur++ = STRING_COLOR_TAG;
                                        *cur++ = STRING_COLOR_TAG;
                                }
-                               else if (d[j] >= ' ')
+                               else if (d[j] >= (unsigned char) ' ')
                                        *cur++ = d[j];
                                else
                                        *cur++ = '.';
@@ -680,6 +162,9 @@ would be good for any more. At the beginning of the string, it will be called
 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.
@@ -696,7 +181,7 @@ int COM_Wordwrap(const char *string, size_t length, float continuationWidth, flo
        //     If it fits, append it. Continue.
        //     If it doesn't fit, output current line, advance to next line. Append the word. This is a continuation. Continue.
 
-       qboolean isContinuation = false;
+       qbool isContinuation = false;
        float spaceWidth;
        const char *startOfLine = string;
        const char *cursor = string;
@@ -719,9 +204,7 @@ int COM_Wordwrap(const char *string, size_t length, float continuationWidth, flo
                {
                        case 0: // end of string
                                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;
@@ -749,7 +232,7 @@ int COM_Wordwrap(const char *string, size_t length, float continuationWidth, flo
                                }
                                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
@@ -776,7 +259,7 @@ int COM_Wordwrap(const char *string, size_t length, float continuationWidth, flo
        return result;
 
 /*
-       qboolean isContinuation = false;
+       qbool isContinuation = false;
        float currentWordSpace = 0;
        const char *currentWord = 0;
        float minReserve = 0;
@@ -975,7 +458,7 @@ COM_ParseToken_Simple
 Parse a token out of a string
 ==============
 */
-int COM_ParseToken_Simple(const char **datapointer, qboolean returnnewline, qboolean parsebackslash)
+int COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
 {
        int len;
        int c;
@@ -996,7 +479,7 @@ skipwhite:
        // 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)
                {
@@ -1010,14 +493,14 @@ skipwhite:
        if (data[0] == '\r' && data[1] == '\n')
                data++;
 
-       if (data[0] == '/' && data[1] == '/')
+       if (parsecomments && data[0] == '/' && data[1] == '/')
        {
                // comment
                while (*data && *data != '\n' && *data != '\r')
                        data++;
                goto skipwhite;
        }
-       else if (data[0] == '/' && data[1] == '*')
+       else if (parsecomments && data[0] == '/' && data[1] == '*')
        {
                // comment
                data++;
@@ -1072,7 +555,7 @@ skipwhite:
        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;
@@ -1088,7 +571,7 @@ COM_ParseToken_QuakeC
 Parse a token out of a string
 ==============
 */
-int COM_ParseToken_QuakeC(const char **datapointer, qboolean returnnewline)
+int COM_ParseToken_QuakeC(const char **datapointer, qbool returnnewline)
 {
        int len;
        int c;
@@ -1109,7 +592,7 @@ skipwhite:
        // 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)
                {
@@ -1186,7 +669,7 @@ skipwhite:
        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;
@@ -1202,7 +685,7 @@ COM_ParseToken_VM_Tokenize
 Parse a token out of a string
 ==============
 */
-int COM_ParseToken_VM_Tokenize(const char **datapointer, qboolean returnnewline)
+int COM_ParseToken_VM_Tokenize(const char **datapointer, qbool returnnewline)
 {
        int len;
        int c;
@@ -1223,7 +706,7 @@ skipwhite:
        // 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)
                {
@@ -1300,7 +783,7 @@ skipwhite:
        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;
@@ -1332,7 +815,7 @@ int COM_ParseToken_Console(const char **datapointer)
 
 // skip whitespace
 skipwhite:
-       for (;*data <= ' ';data++)
+       for (;ISWHITESPACE(*data);data++)
        {
                if (*data == 0)
                {
@@ -1368,7 +851,7 @@ skipwhite:
        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;
@@ -1378,154 +861,34 @@ skipwhite:
        return true;
 }
 
-
 /*
-================
-COM_CheckParm
+===============
+Com_CalcRoll
 
-Returns the position (1 to argc-1) in the program's argument list
-where the given parameter apears, or 0 if not present
-================
+Used by view and sv_user
+===============
 */
-int COM_CheckParm (const char *parm)
+float Com_CalcRoll (const vec3_t angles, const vec3_t velocity, const vec_t angleval, const vec_t velocityval)
 {
-       int i;
-
-       for (i=1 ; i<com_argc ; i++)
-       {
-               if (!com_argv[i])
-                       continue;               // NEXTSTEP sometimes clears appkit vars.
-               if (!strcmp (parm,com_argv[i]))
-                       return i;
-       }
+       vec3_t  forward, right, up;
+       float   sign;
+       float   side;
 
-       return 0;
-}
+       AngleVectors (angles, forward, right, up);
+       side = DotProduct (velocity, right);
+       sign = side < 0 ? -1 : 1;
+       side = fabs(side);
 
-//===========================================================================
-
-// Game mods
-
-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;
-} gamemode_info_t;
-
-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)
-{ "",                          "-quake",               "DarkPlaces-Quake",             "id1",          NULL,                   "dp",                   "darkplaces" },
-// GAME_HIPNOTIC
-// COMMANDLINEOPTION: Game: -hipnotic runs Quake mission pack 1: The Scourge of Armagon
-{ "hipnotic",          "-hipnotic",    "Darkplaces-Hipnotic",  "id1",          "hipnotic",             "dp",                   "darkplaces" },
-// GAME_ROGUE
-// COMMANDLINEOPTION: Game: -rogue runs Quake mission pack 2: The Dissolution of Eternity
-{ "rogue",                     "-rogue",               "Darkplaces-Rogue",             "id1",          "rogue",                "dp",                   "darkplaces" },
-// GAME_NEHAHRA
-// COMMANDLINEOPTION: Game: -nehahra runs The Seal of Nehahra movie and game
-{ "nehahra",           "-nehahra",             "DarkPlaces-Nehahra",   "id1",          "nehahra",              "dp",                   "darkplaces" },
-// GAME_NEXUIZ
-// COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz
-{ "nexuiz",                    "-nexuiz",              "Nexuiz",                               "data",         NULL,                   "nexuiz",               "nexuiz" },
-// GAME_TRANSFUSION
-// COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake)
-{ "transfusion",       "-transfusion", "Transfusion",                  "basetf",       NULL,                   "transfusion",  "transfusion" },
-// GAME_GOODVSBAD2
-// COMMANDLINEOPTION: Game: -goodvsbad2 runs the psychadelic RTS FPS game Good Vs Bad 2
-{ "gvb2",                      "-goodvsbad2",  "GoodVs.Bad2",                  "rts",          NULL,                   "gvb2",                 "gvb2" },
-// GAME_TEU
-// COMMANDLINEOPTION: Game: -teu runs The Evil Unleashed (this option is obsolete as they are not using darkplaces)
-{ "teu",                       "-teu",                 "TheEvilUnleashed",             "baseteu",      NULL,                   "teu",                  "teu" },
-// GAME_BATTLEMECH
-// COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech
-{ "battlemech",                "-battlemech",  "Battlemech",                   "base",         NULL,                   "battlemech",   "battlemech" },
-// GAME_ZYMOTIC
-// COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic
-{ "zymotic",           "-zymotic",             "Zymotic",                              "basezym",              NULL,                   "zymotic",              "zymotic" },
-// GAME_SETHERAL
-// COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral
-{ "setheral",          "-setheral",    "Setheral",                             "data",         NULL,                   "setheral",             "setheral" },
-// GAME_SOM
-// COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man
-{ "som",                       "-som",                 "Son of Man",                   "id1",          "sonofman",             "som",                  "darkplaces" },
-// GAME_TENEBRAE
-// COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented)
-{ "tenebrae",          "-tenebrae",    "DarkPlaces-Tenebrae",  "id1",          "tenebrae",             "dp",                   "darkplaces" },
-// GAME_NEOTERIC
-// COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric
-{ "neoteric",          "-neoteric",    "Neoteric",                             "id1",          "neobase",              "neo",                  "darkplaces" },
-// GAME_OPENQUARTZ
-// COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content
-{ "openquartz",                "-openquartz",  "OpenQuartz",                   "id1",          NULL,                   "openquartz",   "darkplaces" },
-// GAME_PRYDON
-// COMMANDLINEOPTION: Game: -prydon runs the topdown point and click action-RPG Prydon Gate
-{ "prydon",                    "-prydon",              "PrydonGate",                   "id1",          "prydon",               "prydon",               "darkplaces" },
-// GAME_DELUXEQUAKE
-// COMMANDLINEOPTION: Game: -dq runs the game Deluxe Quake
-{ "dq",        "-dq",  "Deluxe Quake",         "basedq",               "extradq",              "basedq",               "dq" },
-// GAME_THEHUNTED
-// COMMANDLINEOPTION: Game: -thehunted runs the game The Hunted
-{ "thehunted",         "-thehunted",   "The Hunted",                   "thdata",       NULL,                   "th",                   "thehunted" },
-// 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" },
-// GAME_EDU2P
-// COMMANDLINEOPTION: Game: -edu2p runs the game Edu2 prototype
-{ "edu2p", "-edu2p", "EDU2 Prototype", "id1", "edu2", "edu2_p", "edu2prototype" },
-// GAME_BLADEMASTER
-// COMMANDLINEOPTION: Game: -blademaster runs the game Prophecy: Return of the BladeMaster
-{ "blademaster", "-blademaster", "Prophecy: Return of the BladeMaster", "basebm", NULL, "blademaster", "blademaster" },
-// GAME_PROPHECY
-// COMMANDLINEOPTION: Game: -prophecy runs the game Quake (default)
-{ "prophecy",                          "-prophecy",            "Prophecy",             "data",         NULL,                   "prophecy",                     "prophecy" },
-};
-
-void COM_InitGameType (void)
-{
-       char name [MAX_OSPATH];
-       unsigned int i;
-
-       FS_StripExtension (com_argv[0], name, sizeof (name));
-       COM_ToLowerString (name, name, sizeof (name));
-
-       // Check the binary name; default to GAME_NORMAL (0)
-       gamemode = GAME_NORMAL;
-       for (i = 1; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
-               if (strstr (name, gamemode_info[i].prog_name))
-               {
-                       gamemode = (gamemode_t)i;
-                       break;
-               }
+       if (side < velocityval)
+               side = side * angleval / velocityval;
+       else
+               side = angleval;
 
-       // Look for a command-line option
-       for (i = 0; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++)
-               if (COM_CheckParm (gamemode_info[i].cmdline))
-               {
-                       gamemode = (gamemode_t)i;
-                       break;
-               }
+       return side*sign;
 
-       gamename = gamemode_info[gamemode].gamename;
-       gamedirname1 = gamemode_info[gamemode].gamedirname1;
-       gamedirname2 = gamemode_info[gamemode].gamedirname2;
-       gamescreenshotname = gamemode_info[gamemode].gamescreenshotname;
-       gameuserdirname = gamemode_info[gamemode].gameuserdirname;
 }
 
+//===========================================================================
 
 /*
 ================
@@ -1539,24 +902,37 @@ void COM_Init_Commands (void)
 
        Cvar_RegisterVariable (&registered);
        Cvar_RegisterVariable (&cmdline);
+       Cvar_RegisterVariable(&cl_playermodel);
+       Cvar_RegisterVirtual(&cl_playermodel, "_cl_playermodel");
+       Cvar_RegisterVariable(&cl_playerskin);
+       Cvar_RegisterVirtual(&cl_playerskin, "_cl_playerskin");
 
        // reconstitute the command line for the cmdline externally visible cvar
        n = 0;
-       for (j = 0;(j < MAX_NUM_ARGVS) && (j < com_argc);j++)
+       for (j = 0;(j < MAX_NUM_ARGVS) && (j < sys.argc);j++)
        {
                i = 0;
-               if (strstr(com_argv[j], " "))
+               if (strstr(sys.argv[j], " "))
                {
                        // arg contains whitespace, store quotes around it
+                       // This condition checks whether we can allow to put
+                       // in two quote characters.
+                       if (n >= ((int)sizeof(com_cmdline) - 2))
+                               break;
                        com_cmdline[n++] = '\"';
-                       while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i])
-                               com_cmdline[n++] = com_argv[j][i++];
+                       // This condition checks whether we can allow one
+                       // more character and a quote character.
+                       while ((n < ((int)sizeof(com_cmdline) - 2)) && sys.argv[j][i])
+                               // FIXME: Doesn't quote special characters.
+                               com_cmdline[n++] = sys.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++];
+                       // This condition checks whether we can allow one
+                       // more character.
+                       while ((n < ((int)sizeof(com_cmdline) - 1)) && sys.argv[j][i])
+                               com_cmdline[n++] = sys.argv[j][i++];
                }
                if (n < ((int)sizeof(com_cmdline) - 1))
                        com_cmdline[n++] = ' ';
@@ -1564,32 +940,25 @@ void COM_Init_Commands (void)
                        break;
        }
        com_cmdline[n] = 0;
-       Cvar_Set ("cmdline", com_cmdline);
+       Cvar_SetQuick(&cmdline, com_cmdline);
 }
 
 /*
 ============
 va
 
-does a varargs printf into a temp buffer, so I don't need to have
-varargs versions of all text functions.
-FIXME: make this buffer size safe someday
+varargs print into provided buffer, returns buffer (so that it can be called in-line, unlike dpsnprintf)
 ============
 */
-char *va(const char *format, ...)
+char *va(char *buf, size_t buflen, const char *format, ...)
 {
        va_list argptr;
-       // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
-       static char string[8][1024], *s;
-       static int stringindex = 0;
 
-       s = string[stringindex];
-       stringindex = (stringindex + 1) & 7;
        va_start (argptr, format);
-       dpvsnprintf (s, sizeof (string[0]), format,argptr);
+       dpvsnprintf (buf, buflen, format,argptr);
        va_end (argptr);
 
-       return s;
+       return buf;
 }
 
 
@@ -1645,6 +1014,23 @@ void COM_ToLowerString (const char *in, char *out, size_t size_out)
        if (size_out == 0)
                return;
 
+       if(utf8_enable.integer)
+       {
+               *out = 0;
+               while(*in && size_out > 1)
+               {
+                       int n;
+                       Uchar ch = u8_getchar_utf8_enabled(in, &in);
+                       ch = u8_tolower(ch);
+                       n = u8_fromchar(ch, out, size_out);
+                       if(n <= 0)
+                               break;
+                       out += n;
+                       size_out -= n;
+               }
+               return;
+       }
+
        while (*in && size_out > 1)
        {
                if (*in >= 'A' && *in <= 'Z')
@@ -1661,6 +1047,23 @@ void COM_ToUpperString (const char *in, char *out, size_t size_out)
        if (size_out == 0)
                return;
 
+       if(utf8_enable.integer)
+       {
+               *out = 0;
+               while(*in && size_out > 1)
+               {
+                       int n;
+                       Uchar ch = u8_getchar_utf8_enabled(in, &in);
+                       ch = u8_toupper(ch);
+                       n = u8_fromchar(ch, out, size_out);
+                       if(n <= 0)
+                               break;
+                       out += n;
+                       size_out -= n;
+               }
+               return;
+       }
+
        while (*in && size_out > 1)
        {
                if (*in >= 'a' && *in <= 'z')
@@ -1693,7 +1096,7 @@ int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *t
                commentprefixlength = (int)strlen(commentprefix);
        while (*l && *l != '\n' && *l != '\r')
        {
-               if (*l > ' ')
+               if (!ISWHITESPACE(*l))
                {
                        if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
                        {
@@ -1718,7 +1121,7 @@ int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *t
                        }
                        else
                        {
-                               while (*l > ' ')
+                               while (!ISWHITESPACE(*l))
                                {
                                        if (tokenbuf >= tokenbufend)
                                                return -1;
@@ -1761,7 +1164,7 @@ all characters until the zero terminator.
 ============
 */
 size_t
-COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid)
+COM_StringLengthNoColors(const char *s, size_t size_s, qbool *valid)
 {
        const char *end = size_s ? (s + size_s) : NULL;
        size_t len = 0;
@@ -1771,13 +1174,13 @@ COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid)
                {
                        case 0:
                                if(valid)
-                                       *valid = TRUE;
+                                       *valid = true;
                                return len;
                        case STRING_COLOR_TAG:
                                ++s;
                                switch((s == end) ? 0 : *s)
                                {
-                                       case STRING_COLOR_RGB_DEFAULT:
+                                       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]) )
@@ -1786,21 +1189,12 @@ COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid)
                                                        break;
                                                }
                                                ++len; // STRING_COLOR_TAG
-                                               ++len; // STRING_COLOR_RGB_DEFAULT
+                                               ++len; // STRING_COLOR_RGB_TAG_CHAR
                                                break;
-                                       /*case 'a':
-                                               if ( s+1 != end && ( isxdigit(s[1]) || (s[1] == '+' || s[1] == '-') ) )
-                                               {
-                                                       s++;
-                                                       break;
-                                               }
-                                               ++len; // STRING_COLOR_TAG
-                                               ++len; // STRING_COLOR_RGB_DEFAULT
-                                               break;*/
                                        case 0: // ends with unfinished color code!
                                                ++len;
                                                if(valid)
-                                                       *valid = FALSE;
+                                                       *valid = false;
                                                return len;
                                        case STRING_COLOR_TAG: // escaped ^
                                                ++len;
@@ -1835,7 +1229,7 @@ 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
+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.
 
@@ -1843,25 +1237,25 @@ For size_in, specify the maximum number of characters from in to use, or 0 to us
 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)
+qbool
+COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets)
 {
-#define APPEND(ch) do { if(--size_out) { *out++ = (ch); } else { *out++ = 0; return FALSE; } } while(0)
+#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;
+               return false;
        for(;;)
        {
                switch((in == end) ? 0 : *in)
                {
                        case 0:
                                *out++ = 0;
-                               return TRUE;
+                               return true;
                        case STRING_COLOR_TAG:
                                ++in;
                                switch((in == end) ? 0 : *in)
                                {
-                                       case STRING_COLOR_RGB_DEFAULT:
+                                       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]) )
@@ -1869,19 +1263,18 @@ COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out,
                                                        in+=3;
                                                        break;
                                                }
-                                       /*case 'a':
-                                               if ( in+1 != end && ( isxdigit(in[1]) || (in[1] == '+' || in[1] == '-') ) )
-                                               {
-                                                       in++;
-                                                       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
                                                if(escape_carets)
                                                        APPEND(STRING_COLOR_TAG);
                                                *out++ = 0;
-                                               return TRUE;
+                                               return true;
                                        case STRING_COLOR_TAG: // escaped ^
                                                APPEND(STRING_COLOR_TAG);
                                                // append a ^ twice when escaping
@@ -1907,207 +1300,11 @@ COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out,
 #undef APPEND
 }
 
-// written by Elric, thanks Elric!
-char *SearchInfostring(const char *infostring, const char *key)
-{
-       static char value [MAX_INPUTLINE];
-       char crt_key [MAX_INPUTLINE];
-       size_t value_ind, key_ind;
-       char c;
-
-       if (*infostring++ != '\\')
-               return NULL;
-
-       value_ind = 0;
-       for (;;)
-       {
-               key_ind = 0;
-
-               // Get the key name
-               for (;;)
-               {
-                       c = *infostring++;
-
-                       if (c == '\0')
-                               return NULL;
-                       if (c == '\\' || key_ind == sizeof (crt_key) - 1)
-                       {
-                               crt_key[key_ind] = '\0';
-                               break;
-                       }
-
-                       crt_key[key_ind++] = c;
-               }
-
-               // If it's the key we are looking for, save it in "value"
-               if (!strcmp(crt_key, key))
-               {
-                       for (;;)
-                       {
-                               c = *infostring++;
-
-                               if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
-                               {
-                                       value[value_ind] = '\0';
-                                       return value;
-                               }
-
-                               value[value_ind++] = c;
-                       }
-               }
-
-               // Else, skip the value
-               for (;;)
-               {
-                       c = *infostring++;
-
-                       if (c == '\0')
-                               return NULL;
-                       if (c == '\\')
-                               break;
-               }
-       }
-}
-
-void InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength)
-{
-       int pos = 0, j;
-       size_t keylength;
-       if (!key)
-               key = "";
-       if (!value)
-               value = "";
-       keylength = strlen(key);
-       if (valuelength < 1 || !value)
-       {
-               Con_Printf("InfoString_GetValue: no room in value\n");
-               return;
-       }
-       value[0] = 0;
-       if (strchr(key, '\\'))
-       {
-               Con_Printf("InfoString_GetValue: key name \"%s\" contains \\ which is not possible in an infostring\n", key);
-               return;
-       }
-       if (strchr(key, '\"'))
-       {
-               Con_Printf("InfoString_SetValue: key name \"%s\" contains \" which is not allowed in an infostring\n", key);
-               return;
-       }
-       if (!key[0])
-       {
-               Con_Printf("InfoString_GetValue: can not look up a key with no name\n");
-               return;
-       }
-       while (buffer[pos] == '\\')
-       {
-               if (!memcmp(buffer + pos+1, key, keylength))
-               {
-                       for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
-                       pos++;
-                       for (j = 0;buffer[pos+j] && buffer[pos+j] != '\\' && j < (int)valuelength - 1;j++)
-                               value[j] = buffer[pos+j];
-                       value[j] = 0;
-                       return;
-               }
-               for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
-               for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
-       }
-       // if we reach this point the key was not found
-}
-
-void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value)
-{
-       int pos = 0, pos2;
-       size_t keylength;
-       if (!key)
-               key = "";
-       if (!value)
-               value = "";
-       keylength = strlen(key);
-       if (strchr(key, '\\') || strchr(value, '\\'))
-       {
-               Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \\ which is not possible to store in an infostring\n", key, value);
-               return;
-       }
-       if (strchr(key, '\"') || strchr(value, '\"'))
-       {
-               Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \" which is not allowed in an infostring\n", key, value);
-               return;
-       }
-       if (!key[0])
-       {
-               Con_Printf("InfoString_SetValue: can not set a key with no name\n");
-               return;
-       }
-       while (buffer[pos] == '\\')
-       {
-               if (!memcmp(buffer + pos+1, key, keylength))
-                       break;
-               for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
-               for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
-       }
-       // if we found the key, find the end of it because we will be replacing it
-       pos2 = pos;
-       if (buffer[pos] == '\\')
-       {
-               for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos2++);
-               for (pos2++;buffer[pos2] && buffer[pos2] != '\\';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;
-       }
-       if (value && value[0])
-       {
-               // set the key/value and append the remaining text
-               char tempbuffer[4096];
-               strlcpy(tempbuffer, buffer + pos2, sizeof(tempbuffer));
-               dpsnprintf(buffer + pos, bufferlength - pos, "\\%s\\%s%s", key, value, tempbuffer);
-       }
-       else
-       {
-               // just remove the key from the text
-               strlcpy(buffer + pos, buffer + pos2, bufferlength - pos);
-       }
-}
-
-void InfoString_Print(char *buffer)
-{
-       int i;
-       char key[2048];
-       char value[2048];
-       while (*buffer)
-       {
-               if (*buffer != '\\')
-               {
-                       Con_Printf("InfoString_Print: corrupt string\n");
-                       return;
-               }
-               for (buffer++, i = 0;*buffer && *buffer != '\\';buffer++)
-                       if (i < (int)sizeof(key)-1)
-                               key[i++] = *buffer;
-               key[i] = 0;
-               if (*buffer != '\\')
-               {
-                       Con_Printf("InfoString_Print: corrupt string\n");
-                       return;
-               }
-               for (buffer++, i = 0;*buffer && *buffer != '\\';buffer++)
-                       if (i < (int)sizeof(value)-1)
-                               value[i++] = *buffer;
-               value[i] = 0;
-               // empty value is an error case
-               Con_Printf("%20s %s\n", key, value[0] ? value : "NO VALUE");
-       }
-}
-
 //========================================================
 // strlcat and strlcpy, from OpenBSD
 
 /*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -2122,66 +1319,146 @@ void InfoString_Print(char *buffer)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*     $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $    */
-/*     $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $     */
+/*     $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $    */
+/*     $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $    */
 
 
 #ifndef HAVE_STRLCAT
 size_t
-strlcat(char *dst, const char *src, size_t siz)
+strlcat(char *dst, const char *src, size_t dsize)
 {
-       register char *d = dst;
-       register const char *s = src;
-       register size_t n = siz;
+       const char *odst = dst;
+       const char *osrc = src;
+       size_t n = dsize;
        size_t dlen;
 
-       /* Find the end of dst and adjust bytes left but don't go past end */
-       while (n-- != 0 && *d != '\0')
-               d++;
-       dlen = d - dst;
-       n = siz - dlen;
-
-       if (n == 0)
-               return(dlen + strlen(s));
-       while (*s != '\0') {
-               if (n != 1) {
-                       *d++ = *s;
+       /* Find the end of dst and adjust bytes left but don't go past end. */
+       while (n-- != 0 && *dst != '\0')
+               dst++;
+       dlen = dst - odst;
+       n = dsize - dlen;
+
+       if (n-- == 0)
+               return(dlen + strlen(src));
+       while (*src != '\0') {
+               if (n != 0) {
+                       *dst++ = *src;
                        n--;
                }
-               s++;
+               src++;
        }
-       *d = '\0';
+       *dst = '\0';
 
-       return(dlen + (s - src));       /* count does not include NUL */
+       return(dlen + (src - osrc));    /* count does not include NUL */
 }
 #endif  // #ifndef HAVE_STRLCAT
 
 
 #ifndef HAVE_STRLCPY
 size_t
-strlcpy(char *dst, const char *src, size_t siz)
+strlcpy(char *dst, const char *src, size_t dsize)
 {
-       register char *d = dst;
-       register const char *s = src;
-       register size_t n = siz;
-
-       /* Copy as many bytes as will fit */
-       if (n != 0 && --n != 0) {
-               do {
-                       if ((*d++ = *s++) == 0)
+       const char *osrc = src;
+       size_t nleft = dsize;
+
+       /* Copy as many bytes as will fit. */
+       if (nleft != 0) {
+               while (--nleft != 0) {
+                       if ((*dst++ = *src++) == '\0')
                                break;
-               } while (--n != 0);
+               }
        }
 
-       /* Not enough room in dst, add NUL and traverse rest of src */
-       if (n == 0) {
-               if (siz != 0)
-                       *d = '\0';              /* NUL-terminate dst */
-               while (*s++)
+       /* Not enough room in dst, add NUL and traverse rest of src. */
+       if (nleft == 0) {
+               if (dsize != 0)
+                       *dst = '\0';            /* NUL-terminate dst */
+               while (*src++)
                        ;
        }
 
-       return(s - src - 1);    /* count does not include NUL */
+       return(src - osrc - 1); /* count does not include NUL */
 }
 
 #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, (int)(buflen - 3*i));
+       }
+       return blocks * 4;
+}