]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - common.c
(patch from Elric) BloodBath renamed to Transfusion
[xonotic/darkplaces.git] / common.c
index 5c73c036c92cd4accd2f10aede6560ba84b40c4d..1f38d06ca54ac2c341d9fa3af9683a1ea82bb460 100644 (file)
--- a/common.c
+++ b/common.c
@@ -31,32 +31,30 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #define NUM_SAFE_ARGVS  7
 
-static char     *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
-static char     *argvdummy = " ";
+static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
+static char *argvdummy = " ";
 
-static char     *safeargvs[NUM_SAFE_ARGVS] =
+static char *safeargvs[NUM_SAFE_ARGVS] =
        {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-window"};
 
 cvar_t registered = {0, "registered","0"};
 cvar_t cmdline = {0, "cmdline","0"};
 
-qboolean        com_modified;   // set true if using non-id files
+mempool_t *pak_mempool;
 
-//qboolean             proghack;
+qboolean com_modified;   // set true if using non-id files
 
-//int             static_registered = 1;  // only for startup check, then set
-
-qboolean               msg_suppress_1 = 0;
+qboolean msg_suppress_1 = 0;
 
 void COM_InitFilesystem (void);
 
-char   com_token[1024];
-int            com_argc;
-char   **com_argv;
+char com_token[1024];
+int com_argc;
+char **com_argv;
 
 // LordHavoc: made commandline 1024 characters instead of 256
 #define CMDLINE_LENGTH 1024
-char   com_cmdline[CMDLINE_LENGTH];
+char com_cmdline[CMDLINE_LENGTH];
 
 int gamemode;
 char *gamename;
@@ -93,126 +91,6 @@ The file "parms.txt" will be read out of the game directory and appended to the
 ============================================================================
 */
 
-/*
-void Q_memset (void *dest, int fill, int count)
-{
-       int             i;
-
-       if ( (((long)dest | count) & 3) == 0)
-       {
-               count >>= 2;
-               fill = fill | (fill<<8) | (fill<<16) | (fill<<24);
-               for (i=0 ; i<count ; i++)
-                       ((int *)dest)[i] = fill;
-       }
-       else
-               for (i=0 ; i<count ; i++)
-                       ((byte *)dest)[i] = fill;
-}
-
-void Q_memcpy (void *dest, void *src, int count)
-{
-       int             i;
-       
-       if (( ( (long)dest | (long)src | count) & 3) == 0 )
-       {
-               count>>=2;
-               for (i=0 ; i<count ; i++)
-                       ((int *)dest)[i] = ((int *)src)[i];
-       }
-       else
-               for (i=0 ; i<count ; i++)
-                       ((byte *)dest)[i] = ((byte *)src)[i];
-}
-
-int Q_memcmp (void *m1, void *m2, int count)
-{
-       while(count)
-       {
-               count--;
-               if (((byte *)m1)[count] != ((byte *)m2)[count])
-                       return -1;
-       }
-       return 0;
-}
-
-void Q_strcpy (char *dest, char *src)
-{
-       while (*src)
-       {
-               *dest++ = *src++;
-       }
-       *dest++ = 0;
-}
-
-void Q_strncpy (char *dest, char *src, int count)
-{
-       while (*src && count--)
-       {
-               *dest++ = *src++;
-       }
-       if (count)
-               *dest++ = 0;
-}
-
-int Q_strlen (char *str)
-{
-       int             count;
-       
-       count = 0;
-       while (str[count])
-               count++;
-
-       return count;
-}
-
-char *Q_strrchr(char *s, char c)
-{
-    int len = Q_strlen(s);
-    s += len;
-    while (len--)
-       if (*--s == c) return s;
-    return 0;
-}
-
-void Q_strcat (char *dest, char *src)
-{
-       dest += Q_strlen(dest);
-       Q_strcpy (dest, src);
-}
-
-int Q_strcmp (char *s1, char *s2)
-{
-       while (1)
-       {
-               if (*s1 != *s2)
-                       return -1;              // strings not equal    
-               if (!*s1)
-                       return 0;               // strings are equal
-               s1++;
-               s2++;
-       }
-       
-       return -1;
-}
-
-int Q_strncmp (char *s1, char *s2, int count)
-{
-       while (1)
-       {
-               if (!count--)
-                       return 0;
-               if (*s1 != *s2)
-                       return -1;              // strings not equal    
-               if (!*s1)
-                       return 0;               // strings are equal
-               s1++;
-               s2++;
-       }
-       
-       return -1;
-}
-*/
 int Q_strncasecmp (char *s1, char *s2, int n)
 {
        int             c1, c2;
@@ -224,7 +102,7 @@ int Q_strncasecmp (char *s1, char *s2, int n)
 
                if (!n--)
                        return 0;               // strings are equal until end point
-               
+
                if (c1 != c2)
                {
                        if (c1 >= 'a' && c1 <= 'z')
@@ -236,10 +114,8 @@ int Q_strncasecmp (char *s1, char *s2, int n)
                }
                if (!c1)
                        return 0;               // strings are equal
-//              s1++;
-//              s2++;
        }
-       
+
        return -1;
 }
 
@@ -247,141 +123,6 @@ int Q_strcasecmp (char *s1, char *s2)
 {
        return Q_strncasecmp (s1, s2, 99999);
 }
-/*
-int Q_atoi (char *str)
-{
-       int             val;
-       int             sign;
-       int             c;
-
-       if (*str == '-')
-       {
-               sign = -1;
-               str++;
-       }
-       else
-               sign = 1;
-               
-       val = 0;
-
-//
-// check for hex
-//
-       if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
-       {
-               str += 2;
-               while (1)
-               {
-                       c = *str++;
-                       if (c >= '0' && c <= '9')
-                               val = (val<<4) + c - '0';
-                       else if (c >= 'a' && c <= 'f')
-                               val = (val<<4) + c - 'a' + 10;
-                       else if (c >= 'A' && c <= 'F')
-                               val = (val<<4) + c - 'A' + 10;
-                       else
-                               return val*sign;
-               }
-       }
-       
-//
-// check for character
-//
-       if (str[0] == '\'')
-       {
-               return sign * str[1];
-       }
-       
-//
-// assume decimal
-//
-       while (1)
-       {
-               c = *str++;
-               if (c <'0' || c > '9')
-                       return val*sign;
-               val = val*10 + c - '0';
-       }
-       
-       return 0;
-}
-
-
-float Q_atof (char *str)
-{
-       double                  val;
-       int             sign;
-       int             c;
-       int             decimal, total;
-       
-       if (*str == '-')
-       {
-               sign = -1;
-               str++;
-       }
-       else
-               sign = 1;
-               
-       val = 0;
-
-//
-// check for hex
-//
-       if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
-       {
-               str += 2;
-               while (1)
-               {
-                       c = *str++;
-                       if (c >= '0' && c <= '9')
-                               val = (val*16) + c - '0';
-                       else if (c >= 'a' && c <= 'f')
-                               val = (val*16) + c - 'a' + 10;
-                       else if (c >= 'A' && c <= 'F')
-                               val = (val*16) + c - 'A' + 10;
-                       else
-                               return val*sign;
-               }
-       }
-       
-//
-// check for character
-//
-       if (str[0] == '\'')
-       {
-               return sign * str[1];
-       }
-       
-//
-// assume decimal
-//
-       decimal = -1;
-       total = 0;
-       while (1)
-       {
-               c = *str++;
-               if (c == '.')
-               {
-                       decimal = total;
-                       continue;
-               }
-               if (c <'0' || c > '9')
-                       break;
-               val = val*10 + c - '0';
-               total++;
-       }
-
-       if (decimal == -1)
-               return val*sign;
-       while (total > decimal)
-       {
-               val /= 10;
-               total--;
-       }
-
-       return val*sign;
-}
-*/
 
 /*
 ============================================================================
@@ -402,7 +143,7 @@ float   (*LittleFloat) (float l);
 
 short   ShortSwap (short l)
 {
-       byte    b1,b2;
+       qbyte    b1,b2;
 
        b1 = l&255;
        b2 = (l>>8)&255;
@@ -410,14 +151,16 @@ short   ShortSwap (short l)
        return (b1<<8) + b2;
 }
 
+#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
 short   ShortNoSwap (short l)
 {
        return l;
 }
+#endif
 
 int    LongSwap (int l)
 {
-       byte    b1,b2,b3,b4;
+       qbyte    b1,b2,b3,b4;
 
        b1 = l&255;
        b2 = (l>>8)&255;
@@ -427,20 +170,22 @@ int    LongSwap (int l)
        return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
 }
 
+#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
 int     LongNoSwap (int l)
 {
        return l;
 }
+#endif
 
 float FloatSwap (float f)
 {
        union
        {
                float   f;
-               byte    b[4];
+               qbyte    b[4];
        } dat1, dat2;
-       
-       
+
+
        dat1.f = f;
        dat2.b[0] = dat1.b[3];
        dat2.b[1] = dat1.b[2];
@@ -449,10 +194,12 @@ float FloatSwap (float f)
        return dat2.f;
 }
 
+#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
 float FloatNoSwap (float f)
 {
        return f;
 }
+#endif
 
 /*
 ==============================================================================
@@ -469,38 +216,23 @@ Handles byte ordering and avoids alignment errors
 
 void MSG_WriteChar (sizebuf_t *sb, int c)
 {
-       byte    *buf;
+       qbyte    *buf;
        
-//#ifdef PARANOID
-//     if (c < -128 || c > 127)
-//             Sys_Error ("MSG_WriteChar: range error");
-//#endif
-
        buf = SZ_GetSpace (sb, 1);
        buf[0] = c;
 }
 
 void MSG_WriteByte (sizebuf_t *sb, int c)
 {
-       byte    *buf;
+       qbyte    *buf;
        
-//#ifdef PARANOID
-//     if (c < 0 || c > 255)
-//             Sys_Error ("MSG_WriteByte: range error");
-//#endif
-
        buf = SZ_GetSpace (sb, 1);
        buf[0] = c;
 }
 
 void MSG_WriteShort (sizebuf_t *sb, int c)
 {
-       byte    *buf;
-       
-//#ifdef PARANOID
-//     if (c < ((short)0x8000) || c > (short)0x7fff)
-//             Sys_Error ("MSG_WriteShort: range error");
-//#endif
+       qbyte    *buf;
 
        buf = SZ_GetSpace (sb, 2);
        buf[0] = c&0xff;
@@ -509,8 +241,8 @@ void MSG_WriteShort (sizebuf_t *sb, int c)
 
 void MSG_WriteLong (sizebuf_t *sb, int c)
 {
-       byte    *buf;
-       
+       qbyte    *buf;
+
        buf = SZ_GetSpace (sb, 4);
        buf[0] = c&0xff;
        buf[1] = (c>>8)&0xff;
@@ -525,11 +257,11 @@ void MSG_WriteFloat (sizebuf_t *sb, float f)
                float   f;
                int     l;
        } dat;
-       
-       
+
+
        dat.f = f;
        dat.l = LittleLong (dat.l);
-       
+
        SZ_Write (sb, &dat.l, 4);
 }
 
@@ -541,33 +273,30 @@ void MSG_WriteString (sizebuf_t *sb, char *s)
                SZ_Write (sb, s, strlen(s)+1);
 }
 
-// used by server (always dpprotocol)
-// moved to common.h as #define
-/*
-void MSG_WriteFloatCoord (sizebuf_t *sb, float f)
-{
-       MSG_WriteFloat(sb, f);
-}
-*/
-
-// used by client
-void MSG_WriteCoord (sizebuf_t *sb, float f)
+// used by server (always latest dpprotocol)
+void MSG_WriteDPCoord (sizebuf_t *sb, float f)
 {
-       if (dpprotocol)
-               MSG_WriteFloat(sb, f);
+       if (f >= 0)
+               MSG_WriteShort (sb, (int)(f + 0.5f));
        else
-               MSG_WriteShort (sb, (int)(f*8.0f + 0.5f));
+               MSG_WriteShort (sb, (int)(f - 0.5f));
 }
 
 void MSG_WritePreciseAngle (sizebuf_t *sb, float f)
 {
-       MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
+       if (f >= 0)
+               MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
+       else
+               MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) - 0.5f) & 65535);
 }
 
-// LordHavoc: round to nearest value, rather than rounding down, fixes crosshair problem
+// LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
 void MSG_WriteAngle (sizebuf_t *sb, float f)
 {
-       MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
+       if (f >= 0)
+               MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
+       else
+               MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) - 0.5f) & 255);
 }
 
 //
@@ -582,67 +311,28 @@ void MSG_BeginReading (void)
        msg_badread = false;
 }
 
-/*
-// returns -1 and sets msg_badread if no more characters are available
-int MSG_ReadChar (void)
-{
-       int     c;
-       
-       // LordHavoc: minor optimization
-       if (msg_readcount >= net_message.cursize)
-//     if (msg_readcount+1 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-               
-       c = (signed char)net_message.data[msg_readcount];
-       msg_readcount++;
-       
-       return c;
-}
-
-int MSG_ReadByte (void)
-{
-       int     c;
-       
-       // LordHavoc: minor optimization
-       if (msg_readcount >= net_message.cursize)
-//     if (msg_readcount+1 > net_message.cursize)
-       {
-               msg_badread = true;
-               return -1;
-       }
-               
-       c = (unsigned char)net_message.data[msg_readcount];
-       msg_readcount++;
-       
-       return c;
-}
-*/
-
 int MSG_ReadShort (void)
 {
        int     c;
-       
+
        if (msg_readcount+2 > net_message.cursize)
        {
                msg_badread = true;
                return -1;
        }
-               
+
        c = (short)(net_message.data[msg_readcount]
        + (net_message.data[msg_readcount+1]<<8));
-       
+
        msg_readcount += 2;
-       
+
        return c;
 }
 
 int MSG_ReadLong (void)
 {
        int     c;
-       
+
        if (msg_readcount+4 > net_message.cursize)
        {
                msg_badread = true;
@@ -653,9 +343,9 @@ int MSG_ReadLong (void)
        + (net_message.data[msg_readcount+1]<<8)
        + (net_message.data[msg_readcount+2]<<16)
        + (net_message.data[msg_readcount+3]<<24);
-       
+
        msg_readcount += 4;
-       
+
        return c;
 }
 
@@ -663,27 +353,27 @@ float MSG_ReadFloat (void)
 {
        union
        {
-               byte    b[4];
+               qbyte    b[4];
                float   f;
                int     l;
        } dat;
-       
+
        dat.b[0] =      net_message.data[msg_readcount];
        dat.b[1] =      net_message.data[msg_readcount+1];
        dat.b[2] =      net_message.data[msg_readcount+2];
        dat.b[3] =      net_message.data[msg_readcount+3];
        msg_readcount += 4;
-       
+
        dat.l = LittleLong (dat.l);
 
-       return dat.f;   
+       return dat.f;
 }
 
 char *MSG_ReadString (void)
 {
        static char     string[2048];
        int             l,c;
-       
+
        l = 0;
        do
        {
@@ -693,55 +383,38 @@ char *MSG_ReadString (void)
                string[l] = c;
                l++;
        } while (l < sizeof(string)-1);
-       
+
        string[l] = 0;
-       
+
        return string;
 }
 
-// used by server (always dpprotocol)
-// moved to common.h as #define
-/*
-float MSG_ReadFloatCoord (void)
+// used by server (always latest dpprotocol)
+float MSG_ReadDPCoord (void)
 {
-       return MSG_ReadFloat();
+       return (signed short) MSG_ReadShort();
 }
-*/
 
 // used by client
 float MSG_ReadCoord (void)
 {
-       if (dpprotocol)
+       if (dpprotocol == DPPROTOCOL_VERSION2 || dpprotocol == DPPROTOCOL_VERSION3)
+               return (signed short) MSG_ReadShort();
+       else if (dpprotocol == DPPROTOCOL_VERSION1)
                return MSG_ReadFloat();
        else
                return MSG_ReadShort() * (1.0f/8.0f);
 }
 
-/*
-float MSG_ReadCoord (void)
-{
-       return MSG_ReadShort() * (1.0f/8.0f);
-}
-
-float MSG_ReadAngle (void)
-{
-       return MSG_ReadChar() * (360.0f/256.0f);
-}
-
-float MSG_ReadPreciseAngle (void)
-{
-       return MSG_ReadShort() * (360.0f/65536);
-}
-*/
-
 
 //===========================================================================
 
-void SZ_Alloc (sizebuf_t *buf, int startsize)
+void SZ_Alloc (sizebuf_t *buf, int startsize, char *name)
 {
        if (startsize < 256)
                startsize = 256;
-       buf->data = Hunk_AllocName (startsize, "sizebuf");
+       buf->mempool = Mem_AllocPool(name);
+       buf->data = Mem_Alloc(buf->mempool, startsize);
        buf->maxsize = startsize;
        buf->cursize = 0;
 }
@@ -749,9 +422,9 @@ void SZ_Alloc (sizebuf_t *buf, int startsize)
 
 void SZ_Free (sizebuf_t *buf)
 {
-//      Z_Free (buf->data);
-//      buf->data = NULL;
-//      buf->maxsize = 0;
+       Mem_FreePool(&buf->mempool);
+       buf->data = NULL;
+       buf->maxsize = 0;
        buf->cursize = 0;
 }
 
@@ -763,18 +436,18 @@ void SZ_Clear (sizebuf_t *buf)
 void *SZ_GetSpace (sizebuf_t *buf, int length)
 {
        void    *data;
-       
+
        if (buf->cursize + length > buf->maxsize)
        {
                if (!buf->allowoverflow)
-                       Host_Error ("SZ_GetSpace: overflow without allowoverflow set - use -zone on the commandline for more zone memory, default: 128k (quake original default was 48k)");
-               
+                       Host_Error ("SZ_GetSpace: overflow without allowoverflow set");
+
                if (length > buf->maxsize)
                        Host_Error ("SZ_GetSpace: %i is > full buffer size", length);
-                       
+
                buf->overflowed = true;
                Con_Printf ("SZ_GetSpace: overflow");
-               SZ_Clear (buf); 
+               SZ_Clear (buf);
        }
 
        data = buf->data + buf->cursize;
@@ -796,9 +469,9 @@ void SZ_Print (sizebuf_t *buf, char *data)
 
 // byte * cast to keep VC++ happy
        if (buf->data[buf->cursize-1])
-               memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
+               memcpy ((qbyte *)SZ_GetSpace(buf, len),data,len); // no trailing 0
        else
-               memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
+               memcpy ((qbyte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0
 }
 
 
@@ -813,7 +486,7 @@ COM_SkipPath
 char *COM_SkipPath (char *pathname)
 {
        char    *last;
-       
+
        last = pathname;
        while (*pathname)
        {
@@ -836,8 +509,8 @@ void COM_StripExtension (char *in, char *out)
        while (*in)
        {
                if (*in == '.')
-                       last = in;
-               if ((*in == '/') || (*in == '\\') || (*in == ':'))
+                       last = out;
+               else if (*in == '/' || *in == '\\' || *in == ':')
                        last = NULL;
                *out++ = *in++;
        }
@@ -1040,26 +713,16 @@ void COM_CheckRegistered (void)
 {
        Cvar_Set ("cmdline", com_cmdline);
 
-//     static_registered = 0;
-
        if (!Sys_FileTime("gfx/pop.lmp"))
        {
                if (com_modified)
                        Con_Printf ("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
                else
                        Con_Printf ("Playing shareware version.\n");
-//#if WINDED
-//     Sys_Error ("This dedicated server requires a full registered copy of Quake");
-//#endif
-//             Con_Printf ("Playing shareware version.\n");
-//             if (com_modified)
-//                     Sys_Error ("You must have the registered version to use modified games");
                return;
        }
-       
-//     Cvar_Set ("cmdline", com_cmdline);
+
        Cvar_Set ("registered", "1");
-//     static_registered = 1;
        Con_Printf ("Playing registered version.\n");
 }
 
@@ -1121,14 +784,18 @@ void COM_InitArgv (int argc, char **argv)
        largv[com_argc] = argvdummy;
        com_argv = largv;
 
-#if ZYMOTIC
+#if TRANSFUSION
+       gamemode = GAME_TRANSFUSION;
+#elif ZYMOTIC
        gamemode = GAME_ZYMOTIC;
 #elif FIENDARENA
        gamemode = GAME_FIENDARENA;
 #elif NEHAHRA
        gamemode = GAME_NEHAHRA;
 #else
-       if (COM_CheckParm ("-zymotic"))
+       if (COM_CheckParm ("-transfusion"))
+               gamemode = GAME_TRANSFUSION;
+       else if (COM_CheckParm ("-zymotic"))
                gamemode = GAME_ZYMOTIC;
        else if (COM_CheckParm ("-fiendarena"))
                gamemode = GAME_FIENDARENA;
@@ -1159,6 +826,9 @@ void COM_InitArgv (int argc, char **argv)
        case GAME_ZYMOTIC:
                gamename = "Zymotic";
                break;
+       case GAME_TRANSFUSION:
+               gamename = "Transfusion";
+               break;
        default:
                Sys_Error("COM_InitArgv: unknown gamemode %i\n", gamemode);
                break;
@@ -1166,42 +836,6 @@ void COM_InitArgv (int argc, char **argv)
 }
 
 
-unsigned int qmalloctotal_alloc, qmalloctotal_alloccount, qmalloctotal_free, qmalloctotal_freecount;
-
-void *qmalloc(unsigned int size)
-{
-       unsigned int *mem;
-       qmalloctotal_alloc += size;
-       qmalloctotal_alloccount++;
-       mem = malloc(size+sizeof(unsigned int));
-       if (!mem)
-               return mem;
-       *mem = size;
-       return (void *)(mem + 1);
-}
-
-void qfree(void *mem)
-{
-       unsigned int *m;
-       if (!mem)
-               return;
-       m = mem;
-       m--; // back up to size
-       qmalloctotal_free += *m; // size
-       qmalloctotal_freecount++;
-       free(m);
-}
-
-extern void GL_TextureStats_PrintTotal(void);
-extern int hunk_low_used, hunk_high_used, hunk_size;
-void COM_Memstats_f(void)
-{
-       Con_Printf("%i malloc calls totalling %i bytes (%.4gMB)\n%i free calls totalling %i bytes (%.4gMB)\n%i bytes (%.4gMB) currently allocated\n", qmalloctotal_alloccount, qmalloctotal_alloc, qmalloctotal_alloc / 1048576.0, qmalloctotal_freecount, qmalloctotal_free, qmalloctotal_free / 1048576.0, qmalloctotal_alloc - qmalloctotal_free, (qmalloctotal_alloc - qmalloctotal_free) / 1048576.0);
-       GL_TextureStats_PrintTotal();
-       Con_Printf ("%i bytes (%.4gMB) of %.4gMB hunk in use\n", hunk_low_used + hunk_high_used, (hunk_low_used + hunk_high_used) / 1048576.0, hunk_size / 1048576.0);
-}
-
-
 extern void Mathlib_Init(void);
 
 /*
@@ -1209,12 +843,12 @@ extern void Mathlib_Init(void);
 COM_Init
 ================
 */
-void COM_Init (char *basedir)
+void COM_Init (void)
 {
 #if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG)
-       byte    swaptest[2] = {1,0};
+       qbyte    swaptest[2] = {1,0};
 
-// set the byte swapping variables in a portable manner 
+// set the byte swapping variables in a portable manner
        if ( *(short *)swaptest == 1)
        {
                BigShort = ShortSwap;
@@ -1235,10 +869,11 @@ void COM_Init (char *basedir)
        }
 #endif
 
+       pak_mempool = Mem_AllocPool("paks");
+
        Cvar_RegisterVariable (&registered);
        Cvar_RegisterVariable (&cmdline);
        Cmd_AddCommand ("path", COM_Path_f);
-       Cmd_AddCommand ("memstats", COM_Memstats_f);
 
        Mathlib_Init();
 
@@ -1258,28 +893,21 @@ FIXME: make this buffer size safe someday
 */
 char    *va(char *format, ...)
 {
-       va_list         argptr;
-       static char             string[1024];
-       
+       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);
-       vsprintf (string, format,argptr);
+       vsprintf (s, format,argptr);
        va_end (argptr);
 
-       return string;  
+       return s;
 }
 
 
-/// just for debugging
-int     memsearch (byte *start, int count, int search)
-{
-       int             i;
-       
-       for (i=0 ; i<count ; i++)
-               if (start[i] == search)
-                       return i;
-       return -1;
-}
-
 /*
 =============================================================================
 
@@ -1297,16 +925,18 @@ int     com_filesize;
 
 typedef struct
 {
-       char    name[MAX_QPATH];
-       int             filepos, filelen;
+       char name[MAX_QPATH];
+       int filepos, filelen;
 } packfile_t;
 
 typedef struct pack_s
 {
-       char    filename[MAX_OSPATH];
-       int             handle;
-       int             numfiles;
-       packfile_t      *files;
+       char filename[MAX_OSPATH];
+       int handle;
+       int numfiles;
+       packfile_t *files;
+       mempool_t *mempool;
+       struct pack_s *next;
 } pack_t;
 
 //
@@ -1314,19 +944,21 @@ typedef struct pack_s
 //
 typedef struct
 {
-       char    name[56];
-       int             filepos, filelen;
+       char name[56];
+       int filepos, filelen;
 } dpackfile_t;
 
 typedef struct
 {
-       char    id[4];
-       int             dirofs;
-       int             dirlen;
+       char id[4];
+       int dirofs;
+       int dirlen;
 } dpackheader_t;
 
-// LordHavoc: was 2048, increased to 16384 and changed info[MAX_PACK_FILES] to a temporary malloc to avoid stack overflows
-#define MAX_FILES_IN_PACK       16384
+// LordHavoc: was 2048, increased to 65536 and changed info[MAX_PACK_FILES] to a temporary alloc
+#define MAX_FILES_IN_PACK       65536
+
+pack_t *packlist = NULL;
 
 #if CACHEENABLE
 char   com_cachedir[MAX_OSPATH];
@@ -1335,8 +967,8 @@ char       com_gamedir[MAX_OSPATH];
 
 typedef struct searchpath_s
 {
-       char    filename[MAX_OSPATH];
-       pack_t  *pack;          // only one of filename / pack will be used
+       char filename[MAX_OSPATH];
+       pack_t *pack;          // only one of filename / pack will be used
        struct searchpath_s *next;
 } searchpath_t;
 
@@ -1351,7 +983,7 @@ COM_Path_f
 void COM_Path_f (void)
 {
        searchpath_t    *s;
-       
+
        Con_Printf ("Current search path:\n");
        for (s=com_searchpaths ; s ; s=s->next)
        {
@@ -1377,8 +1009,9 @@ void    COM_CreatePath (char *path)
 
        for (ofs = path+1 ; *ofs ; ofs++)
        {
-               if (*ofs == '/' || *ofs == '\\' || *ofs == ':')
-               {       // create the directory
+               if (*ofs == '/' || *ofs == '\\')
+               {
+                       // create the directory
                        save = *ofs;
                        *ofs = 0;
                        Sys_mkdir (path);
@@ -1395,7 +1028,7 @@ COM_WriteFile
 The filename will be prefixed by the current game directory
 ============
 */
-void COM_WriteFile (char *filename, void *data, int len)
+qboolean COM_WriteFile (char *filename, void *data, int len)
 {
        int             handle;
        char    name[MAX_OSPATH];
@@ -1408,13 +1041,14 @@ void COM_WriteFile (char *filename, void *data, int len)
        handle = Sys_FileOpenWrite (name);
        if (handle == -1)
        {
-               Sys_Printf ("COM_WriteFile: failed on %s\n", name);
-               return;
+               Con_Printf ("COM_WriteFile: failed on %s\n", name);
+               return false;
        }
 
-       Con_Printf ("COM_WriteFile: %s\n", name);
+       Con_DPrintf ("COM_WriteFile: %s\n", name);
        Sys_FileWrite (handle, data, len);
        Sys_FileClose (handle);
+       return true;
 }
 
 
@@ -1431,7 +1065,7 @@ void COM_CopyFile (char *netpath, char *cachepath)
        int             in, out;
        int             remaining, count;
        char    buf[4096];
-       
+
        remaining = Sys_FileOpenRead (netpath, &in);            
        COM_CreatePath (cachepath);     // create directories up to the cache file
        out = Sys_FileOpenWrite (cachepath);
@@ -1532,11 +1166,6 @@ int COM_FindFile (char *filename, QFile **file, qboolean quiet, qboolean zip)
 // search through the path, one element at a time
 //
        search = com_searchpaths;
-//     if (proghack)
-//     {       // gross hack to use quake 1 progs with quake 2 maps
-//             if (!strcmp(filename, "progs.dat"))
-//                     search = search->next;
-//     }
 
        for ( ; search ; search = search->next)
        {
@@ -1558,13 +1187,6 @@ int COM_FindFile (char *filename, QFile **file, qboolean quiet, qboolean zip)
                }
                else
                {               
-       // check a file in the directory tree
-//                     if (!static_registered)
-//                     {       // if not a registered version, don't ever go beyond base
-//                             if ( strchr (filename, '/') || strchr (filename,'\\'))
-//                                     continue;
-//                     }
-                       
                        sprintf (netpath, "%s/%s",search->filename, filename);
                        
                        findtime = Sys_FileTime (netpath);
@@ -1631,15 +1253,14 @@ Filename are reletive to the quake directory.
 Always appends a 0 byte.
 ============
 */
-cache_user_t   *loadcache;
-byte                   *loadbuf;
-int                            loadsize;
-byte *COM_LoadFile (char *path, int usehunk, qboolean quiet)
+qbyte *loadbuf;
+int loadsize;
+qbyte *COM_LoadFile (char *path, qboolean quiet)
 {
-       QFile             *h;
-       byte    *buf;
-       char    base[1024];
-       int             len;
+       QFile *h;
+       qbyte *buf;
+       char base[1024];
+       int len;
 
        buf = NULL;     // quiet compiler warning
        loadsize = 0;
@@ -1650,64 +1271,22 @@ byte *COM_LoadFile (char *path, int usehunk, qboolean quiet)
                return NULL;
 
        loadsize = len;
-       
+
 // extract the filename base name for hunk tag
        COM_FileBase (path, base);
-       
-       switch (usehunk)
-       {
-       case 1:
-               buf = Hunk_AllocName (len+1, va("%s (file)", path));
-               if (!buf)
-                       Sys_Error ("COM_LoadFile: not enough hunk space for %s (size %i)", path, len);
-               break;
-//     case 0:
-//             buf = Z_Malloc (len+1);
-//             if (!buf)
-//                     Sys_Error ("COM_LoadFile: not enough zone space for %s (size %i)", path, len);
-//             break;
-//     case 3:
-//             buf = Cache_Alloc (loadcache, len+1, base);
-//             if (!buf)
-//                     Sys_Error ("COM_LoadFile: not enough cache space for %s (size %i)", path, len);
-//             break;
-       case 5:
-               buf = qmalloc (len+1);
-               if (!buf)
-                       Sys_Error ("COM_LoadFile: not enough available memory for %s (size %i)", path, len);
-               break;
-       default:
-               Sys_Error ("COM_LoadFile: bad usehunk");
-               break;
-       }
 
-       ((byte *)buf)[len] = 0;
+       buf = Mem_Alloc(tempmempool, len+1);
+       if (!buf)
+               Sys_Error ("COM_LoadFile: not enough available memory for %s (size %i)", path, len);
 
-       Qread (h, buf, len);                     
+       ((qbyte *)buf)[len] = 0;
+
+       Qread (h, buf, len);
        Qclose (h);
 
        return buf;
 }
 
-byte *COM_LoadHunkFile (char *path, qboolean quiet)
-{
-       return COM_LoadFile (path, 1, quiet);
-}
-
-// LordHavoc: returns malloc'd memory
-byte *COM_LoadMallocFile (char *path, qboolean quiet)
-{
-       return COM_LoadFile (path, 5, quiet);
-}
-
-/*
-void COM_LoadCacheFile (char *path, struct cache_user_s *cu, qboolean quiet)
-{
-       loadcache = cu;
-       COM_LoadFile (path, 3, quiet);
-}
-*/
-
 /*
 =================
 COM_LoadPackFile
@@ -1722,51 +1301,52 @@ pack_t *COM_LoadPackFile (char *packfile)
 {
        dpackheader_t   header;
        int                             i;
-       packfile_t              *newfiles;
        int                             numpackfiles;
        pack_t                  *pack;
        int                             packhandle;
-       // LordHavoc: changed from stack array to temporary malloc, allowing huge pack directories
+       // LordHavoc: changed from stack array to temporary alloc, allowing huge pack directories
        dpackfile_t             *info;
 
        if (Sys_FileOpenRead (packfile, &packhandle) == -1)
-       {
-//              Con_Printf ("Couldn't open %s\n", packfile);
                return NULL;
-       }
+
        Sys_FileRead (packhandle, (void *)&header, sizeof(header));
-       if (header.id[0] != 'P' || header.id[1] != 'A'
-       || header.id[2] != 'C' || header.id[3] != 'K')
+       if (memcmp(header.id, "PACK", 4))
                Sys_Error ("%s is not a packfile", packfile);
        header.dirofs = LittleLong (header.dirofs);
        header.dirlen = LittleLong (header.dirlen);
 
+       if (header.dirlen % sizeof(dpackfile_t))
+               Sys_Error ("%s has an invalid directory size", packfile);
+
        numpackfiles = header.dirlen / sizeof(dpackfile_t);
 
        if (numpackfiles > MAX_FILES_IN_PACK)
                Sys_Error ("%s has %i files", packfile, numpackfiles);
 
-       newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "pack file-table");
+       pack = Mem_Alloc(pak_mempool, sizeof (pack_t));
+       strcpy (pack->filename, packfile);
+       pack->handle = packhandle;
+       pack->numfiles = numpackfiles;
+       pack->mempool = Mem_AllocPool(packfile);
+       pack->files = Mem_Alloc(pack->mempool, numpackfiles * sizeof(packfile_t));
+       pack->next = packlist;
+       packlist = pack;
 
-       info = qmalloc(sizeof(*info)*MAX_FILES_IN_PACK);
+       info = Mem_Alloc(tempmempool, sizeof(*info) * numpackfiles);
        Sys_FileSeek (packhandle, header.dirofs);
        Sys_FileRead (packhandle, (void *)info, header.dirlen);
 
 // parse the directory
-       for (i=0 ; i<numpackfiles ; i++)
+       for (i = 0;i < numpackfiles;i++)
        {
-               strcpy (newfiles[i].name, info[i].name);
-               newfiles[i].filepos = LittleLong(info[i].filepos);
-               newfiles[i].filelen = LittleLong(info[i].filelen);
+               strcpy (pack->files[i].name, info[i].name);
+               pack->files[i].filepos = LittleLong(info[i].filepos);
+               pack->files[i].filelen = LittleLong(info[i].filelen);
        }
-       qfree(info);
 
-       pack = Hunk_AllocName (sizeof (pack_t), packfile);
-       strcpy (pack->filename, packfile);
-       pack->handle = packhandle;
-       pack->numfiles = numpackfiles;
-       pack->files = newfiles;
-       
+       Mem_Free(info);
+
        Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
        return pack;
 }
@@ -1777,45 +1357,46 @@ pack_t *COM_LoadPackFile (char *packfile)
 COM_AddGameDirectory
 
 Sets com_gamedir, adds the directory to the head of the path,
-then loads and adds pak1.pak pak2.pak ... 
+then loads and adds pak1.pak pak2.pak ...
 ================
 */
 void COM_AddGameDirectory (char *dir)
 {
-       int                             i;
-       searchpath_t    *search;
-       pack_t                  *pak;
-       char                    pakfile[MAX_OSPATH];
+       stringlist_t *list, *current;
+       searchpath_t *search;
+       pack_t *pak;
+       char pakfile[MAX_OSPATH];
 
        strcpy (com_gamedir, dir);
 
 //
 // add the directory to the search path
 //
-       search = Hunk_AllocName (sizeof(searchpath_t), "pack info");
+       search = Mem_Alloc(pak_mempool, sizeof(searchpath_t));
        strcpy (search->filename, dir);
        search->next = com_searchpaths;
        com_searchpaths = search;
 
-//
-// add any pak files in the format pak0.pak pak1.pak, ...
-//
-       for (i=0 ; ; i++)
+       // add any paks in the directory
+       list = listdirectory(dir);
+       for (current = list;current;current = current->next)
        {
-               sprintf (pakfile, "%s/pak%i.pak", dir, i);
-               pak = COM_LoadPackFile (pakfile);
-               if (!pak)
-                       break;
-               search = Hunk_AllocName (sizeof(searchpath_t), "pack info");
-               search->pack = pak;
-               search->next = com_searchpaths;
-               com_searchpaths = search;
+               if (matchpattern(current->text, "*.pak"))
+               {
+                       sprintf (pakfile, "%s/%s", dir, current->text);
+                       pak = COM_LoadPackFile (pakfile);
+                       if (pak)
+                       {
+                               search = Mem_Alloc(pak_mempool, sizeof(searchpath_t));
+                               search->pack = pak;
+                               search->next = com_searchpaths;
+                               com_searchpaths = search;
+                       }
+                       else
+                               Con_Printf("unable to load pak \"%s\"\n", pakfile);
+               }
        }
-
-//
-// add the contents of the parms.txt file to the end of the command line
-//
-
+       freedirectory(list);
 }
 
 /*
@@ -1889,6 +1470,9 @@ void COM_InitFilesystem (void)
        case GAME_ZYMOTIC:
                COM_AddGameDirectory (va("%s/zymotic", basedir) );
                break;
+       case GAME_TRANSFUSION:
+               COM_AddGameDirectory (va("%s/transfusion", basedir) );
+               break;
        default:
                Sys_Error("COM_InitFilesystem: unknown gamemode %i\n", gamemode);
                break;
@@ -1919,7 +1503,7 @@ void COM_InitFilesystem (void)
                        if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-')
                                break;
 
-                       search = Hunk_AllocName (sizeof(searchpath_t), "pack info");
+                       search = Mem_Alloc(pak_mempool, sizeof(searchpath_t));
                        if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") )
                        {
                                search->pack = COM_LoadPackFile (com_argv[i]);
@@ -1932,9 +1516,6 @@ void COM_InitFilesystem (void)
                        com_searchpaths = search;
                }
        }
-
-//     if (COM_CheckParm ("-proghack"))
-//             proghack = true;
 }
 
 int COM_FileExists(char *filename)
@@ -1991,3 +1572,4 @@ void COM_ToUpperString(char *in, char *out)
                        *out++ = *in++;
        }
 }
+