]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - fs.c
Tell clients to reconnect before loading the next map. Should fix lag/stutter
[xonotic/darkplaces.git] / fs.c
diff --git a/fs.c b/fs.c
index e961cd1b5ef3d9fbcb32db0cb267f9de38e5e961..c15b8ba00f4f235225ea7c9a650903b5788104d4 100644 (file)
--- a/fs.c
+++ b/fs.c
 # define dup _dup
 #endif
 
 # define dup _dup
 #endif
 
+#if USE_RWOPS
+# include <SDL.h>
+typedef SDL_RWops *filedesc_t;
+# define FILEDESC_INVALID NULL
+# define FILEDESC_ISVALID(fd) ((fd) != NULL)
+# define FILEDESC_READ(fd,buf,count) ((fs_offset_t)SDL_RWread(fd, buf, 1, count))
+# define FILEDESC_WRITE(fd,buf,count) ((fs_offset_t)SDL_RWwrite(fd, buf, 1, count))
+# define FILEDESC_CLOSE SDL_RWclose
+# define FILEDESC_SEEK SDL_RWseek
+static filedesc_t FILEDESC_DUP(const char *filename, filedesc_t fd) {
+       filedesc_t new_fd = SDL_RWFromFile(filename, "rb");
+       if (SDL_RWseek(new_fd, SDL_RWseek(fd, 0, RW_SEEK_CUR), RW_SEEK_SET) < 0) {
+               SDL_RWclose(new_fd);
+               return NULL;
+       }
+       return new_fd;
+}
+# define unlink(name) Con_DPrintf("Sorry, no unlink support when trying to unlink %s.\n", (name))
+#else
+typedef int filedesc_t;
+# define FILEDESC_INVALID -1
+# define FILEDESC_ISVALID(fd) ((fd) != -1)
+# define FILEDESC_READ read
+# define FILEDESC_WRITE write
+# define FILEDESC_CLOSE close
+# define FILEDESC_SEEK lseek
+static filedesc_t FILEDESC_DUP(const char *filename, filedesc_t fd) {
+       return dup(fd);
+}
+#endif
+
 /** \page fs File System
 
 All of Quake's data access is through a hierchal file system, but the contents
 /** \page fs File System
 
 All of Quake's data access is through a hierchal file system, but the contents
@@ -212,7 +243,7 @@ typedef struct
 struct qfile_s
 {
        int                             flags;
 struct qfile_s
 {
        int                             flags;
-       int                             handle;                                 ///< file descriptor
+       filedesc_t                      handle;                                 ///< file descriptor
        fs_offset_t             real_length;                    ///< uncompressed file size (for files opened in "read" mode)
        fs_offset_t             position;                               ///< current position in the file
        fs_offset_t             offset;                                 ///< offset into the package (0 if external file)
        fs_offset_t             real_length;                    ///< uncompressed file size (for files opened in "read" mode)
        fs_offset_t             position;                               ///< current position in the file
        fs_offset_t             offset;                                 ///< offset into the package (0 if external file)
@@ -286,7 +317,7 @@ typedef struct pack_s
 {
        char filename [MAX_OSPATH];
        char shortname [MAX_QPATH];
 {
        char filename [MAX_OSPATH];
        char shortname [MAX_QPATH];
-       int handle;
+       filedesc_t handle;
        int ignorecase;  ///< PK3 ignores case
        int numfiles;
        qboolean vpack;
        int ignorecase;  ///< PK3 ignores case
        int numfiles;
        qboolean vpack;
@@ -312,9 +343,9 @@ FUNCTION PROTOTYPES
 =============================================================================
 */
 
 =============================================================================
 */
 
-void FS_Dir_f(void);
-void FS_Ls_f(void);
-void FS_Which_f(void);
+void FS_Dir_f(cmd_state_t *cmd);
+void FS_Ls_f(cmd_state_t *cmd);
+void FS_Which_f(cmd_state_t *cmd);
 
 static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet);
 static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack,
 
 static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet);
 static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack,
@@ -351,9 +382,9 @@ char fs_gamedirs[MAX_GAMEDIRS][MAX_QPATH];
 gamedir_t *fs_all_gamedirs = NULL;
 int fs_all_gamedirs_count = 0;
 
 gamedir_t *fs_all_gamedirs = NULL;
 int fs_all_gamedirs_count = 0;
 
-cvar_t scr_screenshot_name = {CVAR_NORESETTODEFAULTS, "scr_screenshot_name","dp", "prefix name for saved screenshots (changes based on -game commandline, as well as which game mode is running; the date is encoded using strftime escapes)"};
-cvar_t fs_empty_files_in_pack_mark_deletions = {0, "fs_empty_files_in_pack_mark_deletions", "0", "if enabled, empty files in a pak/pk3 count as not existing but cancel the search in further packs, effectively allowing patch pak/pk3 files to 'delete' files"};
-cvar_t cvar_fs_gamedir = {CVAR_READONLY | CVAR_NORESETTODEFAULTS, "fs_gamedir", "", "the list of currently selected gamedirs (use the 'gamedir' command to change this)"};
+cvar_t scr_screenshot_name = {CVAR_CLIENT | CVAR_NORESETTODEFAULTS, "scr_screenshot_name","dp", "prefix name for saved screenshots (changes based on -game commandline, as well as which game mode is running; the date is encoded using strftime escapes)"};
+cvar_t fs_empty_files_in_pack_mark_deletions = {CVAR_CLIENT | CVAR_SERVER, "fs_empty_files_in_pack_mark_deletions", "0", "if enabled, empty files in a pak/pk3 count as not existing but cancel the search in further packs, effectively allowing patch pak/pk3 files to 'delete' files"};
+cvar_t cvar_fs_gamedir = {CVAR_CLIENT | CVAR_SERVER | CVAR_READONLY | CVAR_NORESETTODEFAULTS, "fs_gamedir", "", "the list of currently selected gamedirs (use the 'gamedir' command to change this)"};
 
 
 /*
 
 
 /*
@@ -532,14 +563,14 @@ PK3_GetEndOfCentralDir
 Extract the end of the central directory from a PK3 package
 ====================
 */
 Extract the end of the central directory from a PK3 package
 ====================
 */
-static qboolean PK3_GetEndOfCentralDir (const char *packfile, int packhandle, pk3_endOfCentralDir_t *eocd)
+static qboolean PK3_GetEndOfCentralDir (const char *packfile, filedesc_t packhandle, pk3_endOfCentralDir_t *eocd)
 {
        fs_offset_t filesize, maxsize;
        unsigned char *buffer, *ptr;
        int ind;
 
        // Get the package size
 {
        fs_offset_t filesize, maxsize;
        unsigned char *buffer, *ptr;
        int ind;
 
        // Get the package size
-       filesize = lseek (packhandle, 0, SEEK_END);
+       filesize = FILEDESC_SEEK (packhandle, 0, SEEK_END);
        if (filesize < ZIP_END_CDIR_SIZE)
                return false;
 
        if (filesize < ZIP_END_CDIR_SIZE)
                return false;
 
@@ -549,8 +580,8 @@ static qboolean PK3_GetEndOfCentralDir (const char *packfile, int packhandle, pk
        else
                maxsize = ZIP_MAX_COMMENTS_SIZE + ZIP_END_CDIR_SIZE;
        buffer = (unsigned char *)Mem_Alloc (tempmempool, maxsize);
        else
                maxsize = ZIP_MAX_COMMENTS_SIZE + ZIP_END_CDIR_SIZE;
        buffer = (unsigned char *)Mem_Alloc (tempmempool, maxsize);
-       lseek (packhandle, filesize - maxsize, SEEK_SET);
-       if (read (packhandle, buffer, maxsize) != (fs_offset_t) maxsize)
+       FILEDESC_SEEK (packhandle, filesize - maxsize, SEEK_SET);
+       if (FILEDESC_READ (packhandle, buffer, maxsize) != (fs_offset_t) maxsize)
        {
                Mem_Free (buffer);
                return false;
        {
                Mem_Free (buffer);
                return false;
@@ -587,8 +618,8 @@ static qboolean PK3_GetEndOfCentralDir (const char *packfile, int packhandle, pk
        Mem_Free (buffer);
 
        if (
        Mem_Free (buffer);
 
        if (
-                       eocd->cdir_size < 0 || eocd->cdir_size > filesize ||
-                       eocd->cdir_offset < 0 || eocd->cdir_offset >= filesize ||
+                       eocd->cdir_size > filesize ||
+                       eocd->cdir_offset >= filesize ||
                        eocd->cdir_offset + eocd->cdir_size > filesize
           )
        {
                        eocd->cdir_offset + eocd->cdir_size > filesize
           )
        {
@@ -615,12 +646,12 @@ static int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd)
 
        // Load the central directory in memory
        central_dir = (unsigned char *)Mem_Alloc (tempmempool, eocd->cdir_size);
 
        // Load the central directory in memory
        central_dir = (unsigned char *)Mem_Alloc (tempmempool, eocd->cdir_size);
-       if (lseek (pack->handle, eocd->cdir_offset, SEEK_SET) == -1)
+       if (FILEDESC_SEEK (pack->handle, eocd->cdir_offset, SEEK_SET) == -1)
        {
                Mem_Free (central_dir);
                return -1;
        }
        {
                Mem_Free (central_dir);
                return -1;
        }
-       if(read (pack->handle, central_dir, eocd->cdir_size) != (fs_offset_t) eocd->cdir_size)
+       if(FILEDESC_READ (pack->handle, central_dir, eocd->cdir_size) != (fs_offset_t) eocd->cdir_size)
        {
                Mem_Free (central_dir);
                return -1;
        {
                Mem_Free (central_dir);
                return -1;
@@ -657,7 +688,7 @@ static int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd)
                // 1st uint8  : general purpose bit flag
                //    Check bits 0 (encryption), 3 (data descriptor after the file), and 5 (compressed patched data (?))
                //
                // 1st uint8  : general purpose bit flag
                //    Check bits 0 (encryption), 3 (data descriptor after the file), and 5 (compressed patched data (?))
                //
-               // LordHavoc: bit 3 would be a problem if we were scanning the archive
+               // LadyHavoc: bit 3 would be a problem if we were scanning the archive
                // but is not a problem in the central directory where the values are
                // always real.
                //
                // but is not a problem in the central directory where the values are
                // always real.
                //
@@ -731,7 +762,7 @@ FS_LoadPackPK3
 Create a package entry associated with a PK3 file
 ====================
 */
 Create a package entry associated with a PK3 file
 ====================
 */
-static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qboolean silent)
+static pack_t *FS_LoadPackPK3FromFD (const char *packfile, filedesc_t packhandle, qboolean silent)
 {
        pk3_endOfCentralDir_t eocd;
        pack_t *pack;
 {
        pk3_endOfCentralDir_t eocd;
        pack_t *pack;
@@ -741,7 +772,7 @@ static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qbool
        {
                if(!silent)
                        Con_Printf ("%s is not a PK3 file\n", packfile);
        {
                if(!silent)
                        Con_Printf ("%s is not a PK3 file\n", packfile);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
 
                return NULL;
        }
 
@@ -749,7 +780,7 @@ static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qbool
        if (eocd.disknum != 0 || eocd.cdir_disknum != 0)
        {
                Con_Printf ("%s is a multi-volume ZIP archive\n", packfile);
        if (eocd.disknum != 0 || eocd.cdir_disknum != 0)
        {
                Con_Printf ("%s is a multi-volume ZIP archive\n", packfile);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
 
                return NULL;
        }
 
@@ -759,7 +790,7 @@ static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qbool
        if (eocd.nbentries > MAX_FILES_IN_PACK)
        {
                Con_Printf ("%s contains too many files (%hu)\n", packfile, eocd.nbentries);
        if (eocd.nbentries > MAX_FILES_IN_PACK)
        {
                Con_Printf ("%s contains too many files (%hu)\n", packfile, eocd.nbentries);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
 #endif
                return NULL;
        }
 #endif
@@ -776,7 +807,7 @@ static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qbool
        if (real_nb_files < 0)
        {
                Con_Printf ("%s is not a valid PK3 file\n", packfile);
        if (real_nb_files < 0)
        {
                Con_Printf ("%s is not a valid PK3 file\n", packfile);
-               close(pack->handle);
+               FILEDESC_CLOSE(pack->handle);
                Mem_Free(pack);
                return NULL;
        }
                Mem_Free(pack);
                return NULL;
        }
@@ -784,11 +815,13 @@ static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qbool
        Con_DPrintf("Added packfile %s (%i files)\n", packfile, real_nb_files);
        return pack;
 }
        Con_DPrintf("Added packfile %s (%i files)\n", packfile, real_nb_files);
        return pack;
 }
+
+static filedesc_t FS_SysOpenFiledesc(const char *filepath, const char *mode, qboolean nonblocking);
 static pack_t *FS_LoadPackPK3 (const char *packfile)
 {
 static pack_t *FS_LoadPackPK3 (const char *packfile)
 {
-       int packhandle;
-       packhandle = FS_SysOpenFD (packfile, "rb", false);
-       if (packhandle < 0)
+       filedesc_t packhandle;
+       packhandle = FS_SysOpenFiledesc (packfile, "rb", false);
+       if (!FILEDESC_ISVALID(packhandle))
                return NULL;
        return FS_LoadPackPK3FromFD(packfile, packhandle, false);
 }
                return NULL;
        return FS_LoadPackPK3FromFD(packfile, packhandle, false);
 }
@@ -811,12 +844,12 @@ static qboolean PK3_GetTrueFileOffset (packfile_t *pfile, pack_t *pack)
                return true;
 
        // Load the local file description
                return true;
 
        // Load the local file description
-       if (lseek (pack->handle, pfile->offset, SEEK_SET) == -1)
+       if (FILEDESC_SEEK (pack->handle, pfile->offset, SEEK_SET) == -1)
        {
                Con_Printf ("Can't seek in package %s\n", pack->filename);
                return false;
        }
        {
                Con_Printf ("Can't seek in package %s\n", pack->filename);
                return false;
        }
-       count = read (pack->handle, buffer, ZIP_LOCAL_CHUNK_BASE_SIZE);
+       count = FILEDESC_READ (pack->handle, buffer, ZIP_LOCAL_CHUNK_BASE_SIZE);
        if (count != ZIP_LOCAL_CHUNK_BASE_SIZE || BuffBigLong (buffer) != ZIP_DATA_HEADER)
        {
                Con_Printf ("Can't retrieve file %s in package %s\n", pfile->name, pack->filename);
        if (count != ZIP_LOCAL_CHUNK_BASE_SIZE || BuffBigLong (buffer) != ZIP_DATA_HEADER)
        {
                Con_Printf ("Can't retrieve file %s in package %s\n", pfile->name, pack->filename);
@@ -943,7 +976,7 @@ FS_Path_f
 
 ============
 */
 
 ============
 */
-static void FS_Path_f (void)
+static void FS_Path_f(cmd_state_t *cmd)
 {
        searchpath_t *s;
 
 {
        searchpath_t *s;
 
@@ -976,23 +1009,23 @@ static pack_t *FS_LoadPackPAK (const char *packfile)
 {
        dpackheader_t header;
        int i, numpackfiles;
 {
        dpackheader_t header;
        int i, numpackfiles;
-       int packhandle;
+       filedesc_t packhandle;
        pack_t *pack;
        dpackfile_t *info;
 
        pack_t *pack;
        dpackfile_t *info;
 
-       packhandle = FS_SysOpenFD(packfile, "rb", false);
-       if (packhandle < 0)
+       packhandle = FS_SysOpenFiledesc(packfile, "rb", false);
+       if (!FILEDESC_ISVALID(packhandle))
                return NULL;
                return NULL;
-       if(read (packhandle, (void *)&header, sizeof(header)) != sizeof(header))
+       if(FILEDESC_READ (packhandle, (void *)&header, sizeof(header)) != sizeof(header))
        {
                Con_Printf ("%s is not a packfile\n", packfile);
        {
                Con_Printf ("%s is not a packfile\n", packfile);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
        if (memcmp(header.id, "PACK", 4))
        {
                Con_Printf ("%s is not a packfile\n", packfile);
                return NULL;
        }
        if (memcmp(header.id, "PACK", 4))
        {
                Con_Printf ("%s is not a packfile\n", packfile);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
        header.dirofs = LittleLong (header.dirofs);
                return NULL;
        }
        header.dirofs = LittleLong (header.dirofs);
@@ -1001,26 +1034,26 @@ static pack_t *FS_LoadPackPAK (const char *packfile)
        if (header.dirlen % sizeof(dpackfile_t))
        {
                Con_Printf ("%s has an invalid directory size\n", packfile);
        if (header.dirlen % sizeof(dpackfile_t))
        {
                Con_Printf ("%s has an invalid directory size\n", packfile);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
 
        numpackfiles = header.dirlen / sizeof(dpackfile_t);
 
                return NULL;
        }
 
        numpackfiles = header.dirlen / sizeof(dpackfile_t);
 
-       if (numpackfiles > MAX_FILES_IN_PACK)
+       if (numpackfiles < 0 || numpackfiles > MAX_FILES_IN_PACK)
        {
                Con_Printf ("%s has %i files\n", packfile, numpackfiles);
        {
                Con_Printf ("%s has %i files\n", packfile, numpackfiles);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
 
        info = (dpackfile_t *)Mem_Alloc(tempmempool, sizeof(*info) * numpackfiles);
                return NULL;
        }
 
        info = (dpackfile_t *)Mem_Alloc(tempmempool, sizeof(*info) * numpackfiles);
-       lseek (packhandle, header.dirofs, SEEK_SET);
-       if(header.dirlen != read (packhandle, (void *)info, header.dirlen))
+       FILEDESC_SEEK (packhandle, header.dirofs, SEEK_SET);
+       if(header.dirlen != FILEDESC_READ (packhandle, (void *)info, header.dirlen))
        {
                Con_Printf("%s is an incomplete PAK, not loading\n", packfile);
                Mem_Free(info);
        {
                Con_Printf("%s is an incomplete PAK, not loading\n", packfile);
                Mem_Free(info);
-               close(packhandle);
+               FILEDESC_CLOSE(packhandle);
                return NULL;
        }
 
                return NULL;
        }
 
@@ -1037,6 +1070,9 @@ static pack_t *FS_LoadPackPAK (const char *packfile)
                fs_offset_t offset = (unsigned int)LittleLong (info[i].filepos);
                fs_offset_t size = (unsigned int)LittleLong (info[i].filelen);
 
                fs_offset_t offset = (unsigned int)LittleLong (info[i].filepos);
                fs_offset_t size = (unsigned int)LittleLong (info[i].filelen);
 
+               // Ensure a zero terminated file name (required by format).
+               info[i].name[sizeof(info[i].name) - 1] = 0;
+
                FS_AddFileToPack (info[i].name, pack, offset, size, size, PACKFILE_FLAG_TRUEOFFS);
        }
 
                FS_AddFileToPack (info[i].name, pack, offset, size, size, PACKFILE_FLAG_TRUEOFFS);
        }
 
@@ -1060,7 +1096,7 @@ static pack_t *FS_LoadPackVirtual (const char *dirname)
        pack->vpack = true;
        pack->ignorecase = false;
        strlcpy (pack->filename, dirname, sizeof(pack->filename));
        pack->vpack = true;
        pack->ignorecase = false;
        strlcpy (pack->filename, dirname, sizeof(pack->filename));
-       pack->handle = -1;
+       pack->handle = FILEDESC_INVALID;
        pack->numfiles = -1;
        pack->files = NULL;
        Con_DPrintf("Added packfile %s (virtual pack)\n", dirname);
        pack->numfiles = -1;
        pack->files = NULL;
        Con_DPrintf("Added packfile %s (virtual pack)\n", dirname);
@@ -1176,7 +1212,7 @@ static qboolean FS_AddPack_Fullpath(const char *pakfile, const char *shortname,
        }
        else
        {
        }
        else
        {
-               Con_Printf("unable to load pak \"%s\"\n", pakfile);
+               Con_Printf(CON_ERROR "unable to load pak \"%s\"\n", pakfile);
                return false;
        }
 }
                return false;
        }
 }
@@ -1348,7 +1384,7 @@ static void FS_ClearSearchPath (void)
                        if(!search->pack->vpack)
                        {
                                // close the file
                        if(!search->pack->vpack)
                        {
                                // close the file
-                               close(search->pack->handle);
+                               FILEDESC_CLOSE(search->pack->handle);
                                // free any memory associated with it
                                if (search->pack->files)
                                        Mem_Free(search->pack->files);
                                // free any memory associated with it
                                if (search->pack->files)
                                        Mem_Free(search->pack->files);
@@ -1412,7 +1448,7 @@ void FS_Rescan (void)
 
        // -game <gamedir>
        // Adds basedir/gamedir as an override game
 
        // -game <gamedir>
        // Adds basedir/gamedir as an override game
-       // LordHavoc: now supports multiple -game directories
+       // LadyHavoc: now supports multiple -game directories
        // set the com_modname (reported in server info)
        *gamedirbuf = 0;
        for (i = 0;i < fs_numgamedirs;i++)
        // set the com_modname (reported in server info)
        *gamedirbuf = 0;
        for (i = 0;i < fs_numgamedirs;i++)
@@ -1438,8 +1474,8 @@ void FS_Rescan (void)
        else
                Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
        
        else
                Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
        
-       if((i = COM_CheckParm("-modname")) && i < com_argc - 1)
-               strlcpy(com_modname, com_argv[i+1], sizeof(com_modname));
+       if((i = COM_CheckParm("-modname")) && i < sys.argc - 1)
+               strlcpy(com_modname, sys.argv[i+1], sizeof(com_modname));
 
        // If "-condebug" is in the command line, remove the previous log file
        if (COM_CheckParm ("-condebug") != 0)
 
        // If "-condebug" is in the command line, remove the previous log file
        if (COM_CheckParm ("-condebug") != 0)
@@ -1447,7 +1483,7 @@ void FS_Rescan (void)
 
        // look for the pop.lmp file and set registered to true if it is found
        if (FS_FileExists("gfx/pop.lmp"))
 
        // look for the pop.lmp file and set registered to true if it is found
        if (FS_FileExists("gfx/pop.lmp"))
-               Cvar_Set ("registered", "1");
+               Cvar_SetValueQuick(&registered, 1);
        switch(gamemode)
        {
        case GAME_NORMAL:
        switch(gamemode)
        {
        case GAME_NORMAL:
@@ -1477,7 +1513,7 @@ void FS_Rescan (void)
        W_UnloadAll();
 }
 
        W_UnloadAll();
 }
 
-static void FS_Rescan_f(void)
+static void FS_Rescan_f(cmd_state_t *cmd)
 {
        FS_Rescan();
 }
 {
        FS_Rescan();
 }
@@ -1538,19 +1574,15 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean
 
        if (cls.demoplayback)
        {
 
        if (cls.demoplayback)
        {
-               CL_Disconnect_f();
+               CL_Disconnect_f(&cmd_client);
                cls.demonum = 0;
        }
 
        // unload all sounds so they will be reloaded from the new files as needed
                cls.demonum = 0;
        }
 
        // unload all sounds so they will be reloaded from the new files as needed
-       S_UnloadAllSounds_f();
-
-       // close down the video subsystem, it will start up again when the config finishes...
-       VID_Stop();
-       vid_opened = false;
+       S_UnloadAllSounds_f(&cmd_client);
 
        // restart the video subsystem after the config is executed
 
        // restart the video subsystem after the config is executed
-       Cbuf_InsertText("\nloadconfig\nvid_restart\n\n");
+       Cbuf_InsertText(&cmd_client, "\nloadconfig\nvid_restart\n\n");
 
        return true;
 }
 
        return true;
 }
@@ -1560,13 +1592,13 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean
 FS_GameDir_f
 ================
 */
 FS_GameDir_f
 ================
 */
-static void FS_GameDir_f (void)
+static void FS_GameDir_f(cmd_state_t *cmd)
 {
        int i;
        int numgamedirs;
        char gamedirs[MAX_GAMEDIRS][MAX_QPATH];
 
 {
        int i;
        int numgamedirs;
        char gamedirs[MAX_GAMEDIRS][MAX_QPATH];
 
-       if (Cmd_Argc() < 2)
+       if (Cmd_Argc(cmd) < 2)
        {
                Con_Printf("gamedirs active:");
                for (i = 0;i < fs_numgamedirs;i++)
        {
                Con_Printf("gamedirs active:");
                for (i = 0;i < fs_numgamedirs;i++)
@@ -1575,7 +1607,7 @@ static void FS_GameDir_f (void)
                return;
        }
 
                return;
        }
 
-       numgamedirs = Cmd_Argc() - 1;
+       numgamedirs = Cmd_Argc(cmd) - 1;
        if (numgamedirs > MAX_GAMEDIRS)
        {
                Con_Printf("Too many gamedirs (%i > %i)\n", numgamedirs, MAX_GAMEDIRS);
        if (numgamedirs > MAX_GAMEDIRS)
        {
                Con_Printf("Too many gamedirs (%i > %i)\n", numgamedirs, MAX_GAMEDIRS);
@@ -1583,7 +1615,7 @@ static void FS_GameDir_f (void)
        }
 
        for (i = 0;i < numgamedirs;i++)
        }
 
        for (i = 0;i < numgamedirs;i++)
-               strlcpy(gamedirs[i], Cmd_Argv(i+1), sizeof(gamedirs[i]));
+               strlcpy(gamedirs[i], Cmd_Argv(cmd, i+1), sizeof(gamedirs[i]));
 
        if ((cls.state == ca_connected && !cls.demoplayback) || sv.active)
        {
 
        if ((cls.state == ca_connected && !cls.demoplayback) || sv.active)
        {
@@ -1639,7 +1671,7 @@ FS_CheckGameDir
 const char *FS_CheckGameDir(const char *gamedir)
 {
        const char *ret;
 const char *FS_CheckGameDir(const char *gamedir)
 {
        const char *ret;
-       char buf[8192];
+       static char buf[8192];
        char vabuf[1024];
 
        if (FS_CheckNastyPath(gamedir, true))
        char vabuf[1024];
 
        if (FS_CheckNastyPath(gamedir, true))
@@ -1723,57 +1755,39 @@ static void FS_ListGameDirs(void)
 #endif
 */
 
 #endif
 */
 
-/*
-================
-FS_Init_SelfPack
-================
-*/
-void FS_Init_SelfPack (void)
-{
-       PK3_OpenLibrary ();
-       fs_mempool = Mem_AllocPool("file management", 0, NULL);
-       if(com_selffd >= 0)
+static void COM_InsertFlags(const char *buf) {
+       const char *p;
+       char *q;
+       const char **new_argv;
+       int i = 0;
+       int args_left = 256;
+       new_argv = (const char **)Mem_Alloc(fs_mempool, sizeof(*sys.argv) * (sys.argc + args_left + 2));
+       if(sys.argc == 0)
+               new_argv[0] = "dummy";  // Can't really happen.
+       else
+               new_argv[0] = sys.argv[0];
+       ++i;
+       p = buf;
+       while(COM_ParseToken_Console(&p))
        {
        {
-               fs_selfpack = FS_LoadPackPK3FromFD(com_argv[0], com_selffd, true);
-               if(fs_selfpack)
-               {
-                       char *buf, *q;
-                       const char *p;
-                       FS_AddSelfPack();
-                       buf = (char *) FS_LoadFile("darkplaces.opt", tempmempool, true, NULL);
-                       if(buf)
-                       {
-                               const char **new_argv;
-                               int i = 0;
-                               int args_left = 256;
-                               new_argv = (const char **)Mem_Alloc(fs_mempool, sizeof(*com_argv) * (com_argc + args_left + 2));
-                               if(com_argc == 0)
-                               {
-                                       new_argv[0] = "dummy";
-                                       com_argc = 1;
-                               }
-                               else
-                               {
-                                       memcpy((char *)(&new_argv[0]), &com_argv[0], sizeof(*com_argv) * com_argc);
-                               }
-                               p = buf;
-                               while(COM_ParseToken_Console(&p))
-                               {
-                                       size_t sz = strlen(com_token) + 1; // shut up clang
-                                       if(i >= args_left)
-                                               break;
-                                       q = (char *)Mem_Alloc(fs_mempool, sz);
-                                       strlcpy(q, com_token, sz);
-                                       new_argv[com_argc + i] = q;
-                                       ++i;
-                               }
-                               new_argv[i+com_argc] = NULL;
-                               com_argv = new_argv;
-                               com_argc = com_argc + i;
-                       }
-                       Mem_Free(buf);
-               }
+               size_t sz = strlen(com_token) + 1; // shut up clang
+               if(i > args_left)
+                       break;
+               q = (char *)Mem_Alloc(fs_mempool, sz);
+               strlcpy(q, com_token, sz);
+               new_argv[i] = q;
+               ++i;
        }
        }
+       // Now: i <= args_left + 1.
+       if (sys.argc >= 1)
+       {
+               memcpy((char *)(&new_argv[i]), &sys.argv[1], sizeof(*sys.argv) * (sys.argc - 1));
+               i += sys.argc - 1;
+       }
+       // Now: i <= args_left + (sys.argc || 1).
+       new_argv[i] = NULL;
+       sys.argv = new_argv;
+       sys.argc = i;
 }
 
 static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t userdirsize)
 }
 
 static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t userdirsize)
@@ -1923,15 +1937,15 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
        // see if we can write to this path (note: won't create path)
 #ifdef WIN32
        // no access() here, we must try to open the file for appending
        // see if we can write to this path (note: won't create path)
 #ifdef WIN32
        // no access() here, we must try to open the file for appending
-       fd = FS_SysOpenFD(va(vabuf, sizeof(vabuf), "%s%s/config.cfg", userdir, gamedirname1), "a", false);
+       fd = FS_SysOpenFiledesc(va(vabuf, sizeof(vabuf), "%s%s/config.cfg", userdir, gamedirname1), "a", false);
        if(fd >= 0)
        if(fd >= 0)
-               close(fd);
+               FILEDESC_CLOSE(fd);
 #else
        // on Unix, we don't need to ACTUALLY attempt to open the file
        if(access(va(vabuf, sizeof(vabuf), "%s%s/", userdir, gamedirname1), W_OK | X_OK) >= 0)
                fd = 1;
        else
 #else
        // on Unix, we don't need to ACTUALLY attempt to open the file
        if(access(va(vabuf, sizeof(vabuf), "%s%s/", userdir, gamedirname1), W_OK | X_OK) >= 0)
                fd = 1;
        else
-               fd = 0;
+               fd = -1;
 #endif
        if(fd >= 0)
        {
 #endif
        if(fd >= 0)
        {
@@ -1947,12 +1961,21 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
 #endif
 }
 
 #endif
 }
 
-/*
-================
-FS_Init
-================
-*/
-void FS_Init (void)
+void FS_Init_Commands(void)
+{
+       Cvar_RegisterVariable (&scr_screenshot_name);
+       Cvar_RegisterVariable (&fs_empty_files_in_pack_mark_deletions);
+       Cvar_RegisterVariable (&cvar_fs_gamedir);
+
+       Cmd_AddCommand(CMD_SHARED, "gamedir", FS_GameDir_f, "changes active gamedir list (can take multiple arguments), not including base directory (example usage: gamedir ctf)");
+       Cmd_AddCommand(CMD_SHARED, "fs_rescan", FS_Rescan_f, "rescans filesystem for new pack archives and any other changes");
+       Cmd_AddCommand(CMD_SHARED, "path", FS_Path_f, "print searchpath (game directories and archives)");
+       Cmd_AddCommand(CMD_SHARED, "dir", FS_Dir_f, "list files in searchpath matching an * filename pattern, one per line");
+       Cmd_AddCommand(CMD_SHARED, "ls", FS_Ls_f, "list files in searchpath matching an * filename pattern, multiple per line");
+       Cmd_AddCommand(CMD_SHARED, "which", FS_Which_f, "accepts a file name as argument and reports where the file is taken from");
+}
+
+static void FS_Init_Dir (void)
 {
        const char *p;
        int i;
 {
        const char *p;
        int i;
@@ -1965,9 +1988,9 @@ void FS_Init (void)
        // Overrides the system supplied base directory (under GAMENAME)
 // COMMANDLINEOPTION: Filesystem: -basedir <path> chooses what base directory the game data is in, inside this there should be a data directory for the game (for example id1)
        i = COM_CheckParm ("-basedir");
        // Overrides the system supplied base directory (under GAMENAME)
 // COMMANDLINEOPTION: Filesystem: -basedir <path> chooses what base directory the game data is in, inside this there should be a data directory for the game (for example id1)
        i = COM_CheckParm ("-basedir");
-       if (i && i < com_argc-1)
+       if (i && i < sys.argc-1)
        {
        {
-               strlcpy (fs_basedir, com_argv[i+1], sizeof (fs_basedir));
+               strlcpy (fs_basedir, sys.argv[i+1], sizeof (fs_basedir));
                i = (int)strlen (fs_basedir);
                if (i > 0 && (fs_basedir[i-1] == '\\' || fs_basedir[i-1] == '/'))
                        fs_basedir[i-1] = 0;
                i = (int)strlen (fs_basedir);
                if (i > 0 && (fs_basedir[i-1] == '\\' || fs_basedir[i-1] == '/'))
                        fs_basedir[i-1] = 0;
@@ -1981,10 +2004,10 @@ void FS_Init (void)
                dpsnprintf(fs_basedir, sizeof(fs_basedir), "/sdcard/%s/", gameuserdirname);
 #elif defined(MACOSX)
                // FIXME: is there a better way to find the directory outside the .app, without using Objective-C?
                dpsnprintf(fs_basedir, sizeof(fs_basedir), "/sdcard/%s/", gameuserdirname);
 #elif defined(MACOSX)
                // FIXME: is there a better way to find the directory outside the .app, without using Objective-C?
-               if (strstr(com_argv[0], ".app/"))
+               if (strstr(sys.argv[0], ".app/"))
                {
                        char *split;
                {
                        char *split;
-                       strlcpy(fs_basedir, com_argv[0], sizeof(fs_basedir));
+                       strlcpy(fs_basedir, sys.argv[0], sizeof(fs_basedir));
                        split = strstr(fs_basedir, ".app/");
                        if (split)
                        {
                        split = strstr(fs_basedir, ".app/");
                        if (split)
                        {
@@ -2018,21 +2041,24 @@ void FS_Init (void)
                strlcat(fs_basedir, "/", sizeof(fs_basedir));
 
        // Add the personal game directory
                strlcat(fs_basedir, "/", sizeof(fs_basedir));
 
        // Add the personal game directory
-       if((i = COM_CheckParm("-userdir")) && i < com_argc - 1)
-               dpsnprintf(fs_userdir, sizeof(fs_userdir), "%s/", com_argv[i+1]);
+       if((i = COM_CheckParm("-userdir")) && i < sys.argc - 1)
+               dpsnprintf(fs_userdir, sizeof(fs_userdir), "%s/", sys.argv[i+1]);
        else if (COM_CheckParm("-nohome"))
                *fs_userdir = 0; // user wants roaming installation, no userdir
        else
        {
        else if (COM_CheckParm("-nohome"))
                *fs_userdir = 0; // user wants roaming installation, no userdir
        else
        {
+#ifdef DP_FS_USERDIR
+               strlcpy(fs_userdir, DP_FS_USERDIR, sizeof(fs_userdir));
+#else
                int dirmode;
                int highestuserdirmode = USERDIRMODE_COUNT - 1;
                int preferreduserdirmode = USERDIRMODE_COUNT - 1;
                int userdirstatus[USERDIRMODE_COUNT];
                int dirmode;
                int highestuserdirmode = USERDIRMODE_COUNT - 1;
                int preferreduserdirmode = USERDIRMODE_COUNT - 1;
                int userdirstatus[USERDIRMODE_COUNT];
-#ifdef WIN32
+# ifdef WIN32
                // historical behavior...
                if (!strcmp(gamedirname1, "id1"))
                        preferreduserdirmode = USERDIRMODE_NOHOME;
                // historical behavior...
                if (!strcmp(gamedirname1, "id1"))
                        preferreduserdirmode = USERDIRMODE_NOHOME;
-#endif
+# endif
                // check what limitations the user wants to impose
                if (COM_CheckParm("-home")) preferreduserdirmode = USERDIRMODE_HOME;
                if (COM_CheckParm("-mygames")) preferreduserdirmode = USERDIRMODE_MYGAMES;
                // check what limitations the user wants to impose
                if (COM_CheckParm("-home")) preferreduserdirmode = USERDIRMODE_HOME;
                if (COM_CheckParm("-mygames")) preferreduserdirmode = USERDIRMODE_MYGAMES;
@@ -2064,6 +2090,7 @@ void FS_Init (void)
                // and finally, we picked one...
                FS_ChooseUserDir((userdirmode_t)dirmode, fs_userdir, sizeof(fs_userdir));
                Con_DPrintf("userdir %i is the winner\n", dirmode);
                // and finally, we picked one...
                FS_ChooseUserDir((userdirmode_t)dirmode, fs_userdir, sizeof(fs_userdir));
                Con_DPrintf("userdir %i is the winner\n", dirmode);
+#endif
        }
 
        // if userdir equal to basedir, clear it to avoid confusion later
        }
 
        // if userdir equal to basedir, clear it to avoid confusion later
@@ -2074,32 +2101,32 @@ void FS_Init (void)
 
        p = FS_CheckGameDir(gamedirname1);
        if(!p || p == fs_checkgamedir_missing)
 
        p = FS_CheckGameDir(gamedirname1);
        if(!p || p == fs_checkgamedir_missing)
-               Con_Printf("WARNING: base gamedir %s%s/ not found!\n", fs_basedir, gamedirname1);
+               Con_Printf(CON_WARN "WARNING: base gamedir %s%s/ not found!\n", fs_basedir, gamedirname1);
 
        if(gamedirname2)
        {
                p = FS_CheckGameDir(gamedirname2);
                if(!p || p == fs_checkgamedir_missing)
 
        if(gamedirname2)
        {
                p = FS_CheckGameDir(gamedirname2);
                if(!p || p == fs_checkgamedir_missing)
-                       Con_Printf("WARNING: base gamedir %s%s/ not found!\n", fs_basedir, gamedirname2);
+                       Con_Printf(CON_WARN "WARNING: base gamedir %s%s/ not found!\n", fs_basedir, gamedirname2);
        }
 
        // -game <gamedir>
        // Adds basedir/gamedir as an override game
        }
 
        // -game <gamedir>
        // Adds basedir/gamedir as an override game
-       // LordHavoc: now supports multiple -game directories
-       for (i = 1;i < com_argc && fs_numgamedirs < MAX_GAMEDIRS;i++)
+       // LadyHavoc: now supports multiple -game directories
+       for (i = 1;i < sys.argc && fs_numgamedirs < MAX_GAMEDIRS;i++)
        {
        {
-               if (!com_argv[i])
+               if (!sys.argv[i])
                        continue;
                        continue;
-               if (!strcmp (com_argv[i], "-game") && i < com_argc-1)
+               if (!strcmp (sys.argv[i], "-game") && i < sys.argc-1)
                {
                        i++;
                {
                        i++;
-                       p = FS_CheckGameDir(com_argv[i]);
+                       p = FS_CheckGameDir(sys.argv[i]);
                        if(!p)
                        if(!p)
-                               Sys_Error("Nasty -game name rejected: %s", com_argv[i]);
+                               Sys_Error("Nasty -game name rejected: %s", sys.argv[i]);
                        if(p == fs_checkgamedir_missing)
                        if(p == fs_checkgamedir_missing)
-                               Con_Printf("WARNING: -game %s%s/ not found!\n", fs_basedir, com_argv[i]);
+                               Con_Printf(CON_WARN "WARNING: -game %s%s/ not found!\n", fs_basedir, sys.argv[i]);
                        // add the gamedir to the list of active gamedirs
                        // add the gamedir to the list of active gamedirs
-                       strlcpy (fs_gamedirs[fs_numgamedirs], com_argv[i], sizeof(fs_gamedirs[fs_numgamedirs]));
+                       strlcpy (fs_gamedirs[fs_numgamedirs], sys.argv[i], sizeof(fs_gamedirs[fs_numgamedirs]));
                        fs_numgamedirs++;
                }
        }
                        fs_numgamedirs++;
                }
        }
@@ -2111,18 +2138,69 @@ void FS_Init (void)
                fs_mutex = Thread_CreateMutex();
 }
 
                fs_mutex = Thread_CreateMutex();
 }
 
-void FS_Init_Commands(void)
+/*
+================
+FS_Init_SelfPack
+================
+*/
+void FS_Init_SelfPack (void)
 {
 {
-       Cvar_RegisterVariable (&scr_screenshot_name);
-       Cvar_RegisterVariable (&fs_empty_files_in_pack_mark_deletions);
-       Cvar_RegisterVariable (&cvar_fs_gamedir);
+       char *buf;
 
 
-       Cmd_AddCommand ("gamedir", FS_GameDir_f, "changes active gamedir list (can take multiple arguments), not including base directory (example usage: gamedir ctf)");
-       Cmd_AddCommand ("fs_rescan", FS_Rescan_f, "rescans filesystem for new pack archives and any other changes");
-       Cmd_AddCommand ("path", FS_Path_f, "print searchpath (game directories and archives)");
-       Cmd_AddCommand ("dir", FS_Dir_f, "list files in searchpath matching an * filename pattern, one per line");
-       Cmd_AddCommand ("ls", FS_Ls_f, "list files in searchpath matching an * filename pattern, multiple per line");
-       Cmd_AddCommand ("which", FS_Which_f, "accepts a file name as argument and reports where the file is taken from");
+       // Load darkplaces.opt from the FS.
+       if (!COM_CheckParm("-noopt"))
+       {
+               buf = (char *) FS_SysLoadFile("darkplaces.opt", tempmempool, true, NULL);
+               if(buf)
+               {
+                       COM_InsertFlags(buf);
+                       Mem_Free(buf);
+               }
+       }
+
+#ifndef USE_RWOPS
+       // Provide the SelfPack.
+       if (!COM_CheckParm("-noselfpack") && sys.selffd >= 0)
+       {
+               fs_selfpack = FS_LoadPackPK3FromFD(sys.argv[0], sys.selffd, true);
+               if(fs_selfpack)
+               {
+                       FS_AddSelfPack();
+                       if (!COM_CheckParm("-noopt"))
+                       {
+                               buf = (char *) FS_LoadFile("darkplaces.opt", tempmempool, true, NULL);
+                               if(buf)
+                               {
+                                       COM_InsertFlags(buf);
+                                       Mem_Free(buf);
+                               }
+                       }
+               }
+       }
+#endif
+}
+
+/*
+================
+FS_Init
+================
+*/
+
+void FS_Init(void)
+{
+       fs_mempool = Mem_AllocPool("file management", 0, NULL);
+
+       FS_Init_Commands();
+
+       PK3_OpenLibrary ();
+
+       // initialize the self-pack (must be before COM_InitGameType as it may add command line options)
+       FS_Init_SelfPack();
+
+       // detect gamemode from commandline options or executable name
+       COM_InitGameType();
+
+       FS_Init_Dir();
 }
 
 /*
 }
 
 /*
@@ -2149,9 +2227,9 @@ void FS_Shutdown (void)
                Thread_DestroyMutex(fs_mutex);
 }
 
                Thread_DestroyMutex(fs_mutex);
 }
 
-int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
+static filedesc_t FS_SysOpenFiledesc(const char *filepath, const char *mode, qboolean nonblocking)
 {
 {
-       int handle = -1;
+       filedesc_t handle = FILEDESC_INVALID;
        int mod, opt;
        unsigned int ind;
        qboolean dolock = false;
        int mod, opt;
        unsigned int ind;
        qboolean dolock = false;
@@ -2172,8 +2250,8 @@ int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
                        opt = O_CREAT | O_APPEND;
                        break;
                default:
                        opt = O_CREAT | O_APPEND;
                        break;
                default:
-                       Con_Printf ("FS_SysOpen(%s, %s): invalid mode\n", filepath, mode);
-                       return -1;
+                       Con_Printf(CON_ERROR "FS_SysOpen(%s, %s): invalid mode\n", filepath, mode);
+                       return FILEDESC_INVALID;
        }
        for (ind = 1; mode[ind] != '\0'; ind++)
        {
        }
        for (ind = 1; mode[ind] != '\0'; ind++)
        {
@@ -2189,7 +2267,7 @@ int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
                                dolock = true;
                                break;
                        default:
                                dolock = true;
                                break;
                        default:
-                               Con_Printf ("FS_SysOpen(%s, %s): unknown character in mode (%c)\n",
+                               Con_Printf(CON_ERROR "FS_SysOpen(%s, %s): unknown character in mode (%c)\n",
                                                        filepath, mode, mode[ind]);
                }
        }
                                                        filepath, mode, mode[ind]);
                }
        }
@@ -2198,15 +2276,20 @@ int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
                opt |= O_NONBLOCK;
 
        if(COM_CheckParm("-readonly") && mod != O_RDONLY)
                opt |= O_NONBLOCK;
 
        if(COM_CheckParm("-readonly") && mod != O_RDONLY)
-               return -1;
+               return FILEDESC_INVALID;
 
 
-#ifdef WIN32
-# if _MSC_VER >= 1400
+#if USE_RWOPS
+       if (dolock)
+               return FILEDESC_INVALID;
+       handle = SDL_RWFromFile(filepath, mode);
+#else
+# ifdef WIN32
+#  if _MSC_VER >= 1400
        _sopen_s(&handle, filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
        _sopen_s(&handle, filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
-# else
+#  else
        handle = _sopen (filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
        handle = _sopen (filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
-# endif
-#else
+#  endif
+# else
        handle = open (filepath, mod | opt, 0666);
        if(handle >= 0 && dolock)
        {
        handle = open (filepath, mod | opt, 0666);
        if(handle >= 0 && dolock)
        {
@@ -2217,15 +2300,25 @@ int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
                l.l_len = 0;
                if(fcntl(handle, F_SETLK, &l) == -1)
                {
                l.l_len = 0;
                if(fcntl(handle, F_SETLK, &l) == -1)
                {
-                       close(handle);
+                       FILEDESC_CLOSE(handle);
                        handle = -1;
                }
        }
                        handle = -1;
                }
        }
+# endif
 #endif
 
        return handle;
 }
 
 #endif
 
        return handle;
 }
 
+int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
+{
+#ifdef USE_RWOPS
+       return -1;
+#else
+       return FS_SysOpenFiledesc(filepath, mode, nonblocking);
+#endif
+}
+
 /*
 ====================
 FS_SysOpen
 /*
 ====================
 FS_SysOpen
@@ -2239,8 +2332,8 @@ qfile_t* FS_SysOpen (const char* filepath, const char* mode, qboolean nonblockin
 
        file = (qfile_t *)Mem_Alloc (fs_mempool, sizeof (*file));
        file->ungetc = EOF;
 
        file = (qfile_t *)Mem_Alloc (fs_mempool, sizeof (*file));
        file->ungetc = EOF;
-       file->handle = FS_SysOpenFD(filepath, mode, nonblocking);
-       if (file->handle < 0)
+       file->handle = FS_SysOpenFiledesc(filepath, mode, nonblocking);
+       if (!FILEDESC_ISVALID(file->handle))
        {
                Mem_Free (file);
                return NULL;
        {
                Mem_Free (file);
                return NULL;
@@ -2248,13 +2341,13 @@ qfile_t* FS_SysOpen (const char* filepath, const char* mode, qboolean nonblockin
 
        file->filename = Mem_strdup(fs_mempool, filepath);
 
 
        file->filename = Mem_strdup(fs_mempool, filepath);
 
-       file->real_length = lseek (file->handle, 0, SEEK_END);
+       file->real_length = FILEDESC_SEEK (file->handle, 0, SEEK_END);
 
        // For files opened in append mode, we start at the end of the file
        if (mode[0] == 'a')
                file->position = file->real_length;
        else
 
        // For files opened in append mode, we start at the end of the file
        if (mode[0] == 'a')
                file->position = file->real_length;
        else
-               lseek (file->handle, 0, SEEK_SET);
+               FILEDESC_SEEK (file->handle, 0, SEEK_SET);
 
        return file;
 }
 
        return file;
 }
@@ -2270,7 +2363,7 @@ Open a packed file using its package file descriptor
 static qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
 {
        packfile_t *pfile;
 static qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
 {
        packfile_t *pfile;
-       int dup_handle;
+       filedesc_t dup_handle;
        qfile_t* file;
 
        pfile = &pack->files[pack_ind];
        qfile_t* file;
 
        pfile = &pack->files[pack_ind];
@@ -2284,24 +2377,24 @@ static qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
        // No Zlib DLL = no compressed files
        if (!zlib_dll && (pfile->flags & PACKFILE_FLAG_DEFLATED))
        {
        // No Zlib DLL = no compressed files
        if (!zlib_dll && (pfile->flags & PACKFILE_FLAG_DEFLATED))
        {
-               Con_Printf("WARNING: can't open the compressed file %s\n"
+               Con_Printf(CON_WARN "WARNING: can't open the compressed file %s\n"
                                        "You need the Zlib DLL to use compressed files\n",
                                        pfile->name);
                return NULL;
        }
 #endif
 
                                        "You need the Zlib DLL to use compressed files\n",
                                        pfile->name);
                return NULL;
        }
 #endif
 
-       // LordHavoc: lseek affects all duplicates of a handle so we do it before
+       // LadyHavoc: FILEDESC_SEEK affects all duplicates of a handle so we do it before
        // the dup() call to avoid having to close the dup_handle on error here
        // the dup() call to avoid having to close the dup_handle on error here
-       if (lseek (pack->handle, pfile->offset, SEEK_SET) == -1)
+       if (FILEDESC_SEEK (pack->handle, pfile->offset, SEEK_SET) == -1)
        {
                Con_Printf ("FS_OpenPackedFile: can't lseek to %s in %s (offset: %08x%08x)\n",
                                        pfile->name, pack->filename, (unsigned int)(pfile->offset >> 32), (unsigned int)(pfile->offset));
                return NULL;
        }
 
        {
                Con_Printf ("FS_OpenPackedFile: can't lseek to %s in %s (offset: %08x%08x)\n",
                                        pfile->name, pack->filename, (unsigned int)(pfile->offset >> 32), (unsigned int)(pfile->offset));
                return NULL;
        }
 
-       dup_handle = dup (pack->handle);
-       if (dup_handle < 0)
+       dup_handle = FILEDESC_DUP (pack->filename, pack->handle);
+       if (!FILEDESC_ISVALID(dup_handle))
        {
                Con_Printf ("FS_OpenPackedFile: can't dup package's handle (pack: %s)\n", pack->filename);
                return NULL;
        {
                Con_Printf ("FS_OpenPackedFile: can't dup package's handle (pack: %s)\n", pack->filename);
                return NULL;
@@ -2343,7 +2436,7 @@ static qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
                if (qz_inflateInit2 (&ztk->zstream, -MAX_WBITS) != Z_OK)
                {
                        Con_Printf ("FS_OpenPackedFile: inflate init error (file: %s)\n", pfile->name);
                if (qz_inflateInit2 (&ztk->zstream, -MAX_WBITS) != Z_OK)
                {
                        Con_Printf ("FS_OpenPackedFile: inflate init error (file: %s)\n", pfile->name);
-                       close(dup_handle);
+                       FILEDESC_CLOSE(dup_handle);
                        Mem_Free(file);
                        return NULL;
                }
                        Mem_Free(file);
                        return NULL;
                }
@@ -2706,13 +2799,21 @@ int FS_Close (qfile_t* file)
                return 0;
        }
 
                return 0;
        }
 
-       if (close (file->handle))
+       if (FILEDESC_CLOSE (file->handle))
                return EOF;
 
        if (file->filename)
        {
                if (file->flags & QFILE_FLAG_REMOVE)
                return EOF;
 
        if (file->filename)
        {
                if (file->flags & QFILE_FLAG_REMOVE)
-                       remove(file->filename);
+               {
+                       if (remove(file->filename) == -1)
+                       {
+                               // No need to report this. If removing a just
+                               // written file failed, this most likely means
+                               // someone else deleted it first - which we
+                               // like.
+                       }
+               }
 
                Mem_Free((void *) file->filename);
        }
 
                Mem_Free((void *) file->filename);
        }
@@ -2746,9 +2847,9 @@ fs_offset_t FS_Write (qfile_t* file, const void* data, size_t datasize)
        // If necessary, seek to the exact file position we're supposed to be
        if (file->buff_ind != file->buff_len)
        {
        // If necessary, seek to the exact file position we're supposed to be
        if (file->buff_ind != file->buff_len)
        {
-               if (lseek (file->handle, file->buff_ind - file->buff_len, SEEK_CUR) == -1)
+               if (FILEDESC_SEEK (file->handle, file->buff_ind - file->buff_len, SEEK_CUR) == -1)
                {
                {
-                       Con_Printf("WARNING: could not seek in %s.\n");
+                       Con_Printf(CON_WARN "WARNING: could not seek in %s.\n", file->filename);
                }
        }
 
                }
        }
 
@@ -2756,13 +2857,13 @@ fs_offset_t FS_Write (qfile_t* file, const void* data, size_t datasize)
        FS_Purge (file);
 
        // Write the buffer and update the position
        FS_Purge (file);
 
        // Write the buffer and update the position
-       // LordHavoc: to hush a warning about passing size_t to an unsigned int parameter on Win64 we do this as multiple writes if the size would be too big for an integer (we never write that big in one go, but it's a theory)
+       // LadyHavoc: to hush a warning about passing size_t to an unsigned int parameter on Win64 we do this as multiple writes if the size would be too big for an integer (we never write that big in one go, but it's a theory)
        while (written < (fs_offset_t)datasize)
        {
                // figure out how much to write in one chunk
                fs_offset_t maxchunk = 1<<30; // 1 GiB
                int chunk = (int)min((fs_offset_t)datasize - written, maxchunk);
        while (written < (fs_offset_t)datasize)
        {
                // figure out how much to write in one chunk
                fs_offset_t maxchunk = 1<<30; // 1 GiB
                int chunk = (int)min((fs_offset_t)datasize - written, maxchunk);
-               int result = (int)write (file->handle, (const unsigned char *)data + written, chunk);
+               int result = (int)FILEDESC_WRITE (file->handle, (const unsigned char *)data + written, chunk);
                // if at least some was written, add it to our accumulator
                if (result > 0)
                        written += result;
                // if at least some was written, add it to our accumulator
                if (result > 0)
                        written += result;
@@ -2770,7 +2871,7 @@ fs_offset_t FS_Write (qfile_t* file, const void* data, size_t datasize)
                if (result != chunk)
                        break;
        }
                if (result != chunk)
                        break;
        }
-       file->position = lseek (file->handle, 0, SEEK_CUR);
+       file->position = FILEDESC_SEEK (file->handle, 0, SEEK_CUR);
        if (file->real_length < file->position)
                file->real_length = file->position;
 
        if (file->real_length < file->position)
                file->real_length = file->position;
 
@@ -2790,7 +2891,7 @@ fs_offset_t FS_Read (qfile_t* file, void* buffer, size_t buffersize)
 {
        fs_offset_t count, done;
 
 {
        fs_offset_t count, done;
 
-       if (buffersize == 0)
+       if (buffersize == 0 || !buffer)
                return 0;
 
        // Get rid of the ungetc character
                return 0;
 
        // Get rid of the ungetc character
@@ -2843,13 +2944,13 @@ fs_offset_t FS_Read (qfile_t* file, void* buffer, size_t buffersize)
                {
                        if (count > (fs_offset_t)buffersize)
                                count = (fs_offset_t)buffersize;
                {
                        if (count > (fs_offset_t)buffersize)
                                count = (fs_offset_t)buffersize;
-                       if (lseek (file->handle, file->offset + file->position, SEEK_SET) == -1)
+                       if (FILEDESC_SEEK (file->handle, file->offset + file->position, SEEK_SET) == -1)
                        {
                                // Seek failed. When reading from a pipe, and
                                // the caller never called FS_Seek, this still
                                // works fine.  So no reporting this error.
                        }
                        {
                                // Seek failed. When reading from a pipe, and
                                // the caller never called FS_Seek, this still
                                // works fine.  So no reporting this error.
                        }
-                       nb = read (file->handle, &((unsigned char*)buffer)[done], count);
+                       nb = FILEDESC_READ (file->handle, &((unsigned char*)buffer)[done], count);
                        if (nb > 0)
                        {
                                done += nb;
                        if (nb > 0)
                        {
                                done += nb;
@@ -2863,13 +2964,13 @@ fs_offset_t FS_Read (qfile_t* file, void* buffer, size_t buffersize)
                {
                        if (count > (fs_offset_t)sizeof (file->buff))
                                count = (fs_offset_t)sizeof (file->buff);
                {
                        if (count > (fs_offset_t)sizeof (file->buff))
                                count = (fs_offset_t)sizeof (file->buff);
-                       if (lseek (file->handle, file->offset + file->position, SEEK_SET) == -1)
+                       if (FILEDESC_SEEK (file->handle, file->offset + file->position, SEEK_SET) == -1)
                        {
                                // Seek failed. When reading from a pipe, and
                                // the caller never called FS_Seek, this still
                                // works fine.  So no reporting this error.
                        }
                        {
                                // Seek failed. When reading from a pipe, and
                                // the caller never called FS_Seek, this still
                                // works fine.  So no reporting this error.
                        }
-                       nb = read (file->handle, file->buff, count);
+                       nb = FILEDESC_READ (file->handle, file->buff, count);
                        if (nb > 0)
                        {
                                file->buff_len = nb;
                        if (nb > 0)
                        {
                                file->buff_len = nb;
@@ -2905,8 +3006,8 @@ fs_offset_t FS_Read (qfile_t* file, void* buffer, size_t buffersize)
                        count = (fs_offset_t)(ztk->comp_length - ztk->in_position);
                        if (count > (fs_offset_t)sizeof (ztk->input))
                                count = (fs_offset_t)sizeof (ztk->input);
                        count = (fs_offset_t)(ztk->comp_length - ztk->in_position);
                        if (count > (fs_offset_t)sizeof (ztk->input))
                                count = (fs_offset_t)sizeof (ztk->input);
-                       lseek (file->handle, file->offset + (fs_offset_t)ztk->in_position, SEEK_SET);
-                       if (read (file->handle, ztk->input, count) != count)
+                       FILEDESC_SEEK (file->handle, file->offset + (fs_offset_t)ztk->in_position, SEEK_SET);
+                       if (FILEDESC_READ (file->handle, ztk->input, count) != count)
                        {
                                Con_Printf ("FS_Read: unexpected end of file\n");
                                break;
                        {
                                Con_Printf ("FS_Read: unexpected end of file\n");
                                break;
@@ -3029,7 +3130,7 @@ int FS_VPrintf (qfile_t* file, const char* format, va_list ap)
                buff_size *= 2;
        }
 
                buff_size *= 2;
        }
 
-       len = write (file->handle, tempbuff, len);
+       len = FILEDESC_WRITE (file->handle, tempbuff, len);
        Mem_Free (tempbuff);
 
        return len;
        Mem_Free (tempbuff);
 
        return len;
@@ -3124,7 +3225,7 @@ int FS_Seek (qfile_t* file, fs_offset_t offset, int whence)
        // Unpacked or uncompressed files can seek directly
        if (! (file->flags & QFILE_FLAG_DEFLATED))
        {
        // Unpacked or uncompressed files can seek directly
        if (! (file->flags & QFILE_FLAG_DEFLATED))
        {
-               if (lseek (file->handle, file->offset + offset, SEEK_SET) == -1)
+               if (FILEDESC_SEEK (file->handle, file->offset + offset, SEEK_SET) == -1)
                        return -1;
                file->position = offset;
                return 0;
                        return -1;
                file->position = offset;
                return 0;
@@ -3141,7 +3242,7 @@ int FS_Seek (qfile_t* file, fs_offset_t offset, int whence)
                ztk->in_len = 0;
                ztk->in_position = 0;
                file->position = 0;
                ztk->in_len = 0;
                ztk->in_position = 0;
                file->position = 0;
-               if (lseek (file->handle, file->offset, SEEK_SET) == -1)
+               if (FILEDESC_SEEK (file->handle, file->offset, SEEK_SET) == -1)
                        Con_Printf("IMPOSSIBLE: couldn't seek in already opened pk3 file.\n");
 
                // Reset the Zlib stream
                        Con_Printf("IMPOSSIBLE: couldn't seek in already opened pk3 file.\n");
 
                // Reset the Zlib stream
@@ -3155,9 +3256,9 @@ int FS_Seek (qfile_t* file, fs_offset_t offset, int whence)
        buffer = (unsigned char *)Mem_Alloc (tempmempool, buffersize);
 
        // Skip all data until we reach the requested offset
        buffer = (unsigned char *)Mem_Alloc (tempmempool, buffersize);
 
        // Skip all data until we reach the requested offset
-       while (offset > file->position)
+       while (offset > (file->position - file->buff_len + file->buff_ind))
        {
        {
-               fs_offset_t diff = offset - file->position;
+               fs_offset_t diff = offset - (file->position - file->buff_len + file->buff_ind);
                fs_offset_t count, len;
 
                count = (diff > buffersize) ? buffersize : diff;
                fs_offset_t count, len;
 
                count = (diff > buffersize) ? buffersize : diff;
@@ -3217,19 +3318,17 @@ void FS_Purge (qfile_t* file)
 
 /*
 ============
 
 /*
 ============
-FS_LoadFile
+FS_LoadAndCloseQFile
 
 
-Filename are relative to the quake directory.
+Loads full content of a qfile_t and closes it.
 Always appends a 0 byte.
 ============
 */
 Always appends a 0 byte.
 ============
 */
-unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+static unsigned char *FS_LoadAndCloseQFile (qfile_t *file, const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
 {
 {
-       qfile_t *file;
        unsigned char *buf = NULL;
        fs_offset_t filesize = 0;
 
        unsigned char *buf = NULL;
        fs_offset_t filesize = 0;
 
-       file = FS_OpenVirtualFile(path, quiet);
        if (file)
        {
                filesize = file->real_length;
        if (file)
        {
                filesize = file->real_length;
@@ -3254,6 +3353,36 @@ unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, f
 }
 
 
 }
 
 
+/*
+============
+FS_LoadFile
+
+Filename are relative to the quake directory.
+Always appends a 0 byte.
+============
+*/
+unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+{
+       qfile_t *file = FS_OpenVirtualFile(path, quiet);
+       return FS_LoadAndCloseQFile(file, path, pool, quiet, filesizepointer);
+}
+
+
+/*
+============
+FS_SysLoadFile
+
+Filename are OS paths.
+Always appends a 0 byte.
+============
+*/
+unsigned char *FS_SysLoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer)
+{
+       qfile_t *file = FS_SysOpen(path, "rb", false);
+       return FS_LoadAndCloseQFile(file, path, pool, quiet, filesizepointer);
+}
+
+
 /*
 ============
 FS_WriteFile
 /*
 ============
 FS_WriteFile
@@ -3339,7 +3468,7 @@ void FS_DefaultExtension (char *path, const char *extension, size_t size_path)
 
        // if path doesn't have a .EXT, append extension
        // (extension should include the .)
 
        // if path doesn't have a .EXT, append extension
        // (extension should include the .)
-       src = path + strlen(path) - 1;
+       src = path + strlen(path);
 
        while (*src != '/' && src != path)
        {
 
        while (*src != '/' && src != path)
        {
@@ -3451,7 +3580,6 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet)
        stringlist_t dirlist;
        const char *slash, *backslash, *colon, *separator;
        char *basepath;
        stringlist_t dirlist;
        const char *slash, *backslash, *colon, *separator;
        char *basepath;
-       char temp[MAX_OSPATH];
 
        for (i = 0;pattern[i] == '.' || pattern[i] == ':' || pattern[i] == '/' || pattern[i] == '\\';i++)
                ;
 
        for (i = 0;pattern[i] == '.' || pattern[i] == ':' || pattern[i] == '/' || pattern[i] == '\\';i++)
                ;
@@ -3486,6 +3614,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet)
                        pak = searchpath->pack;
                        for (i = 0;i < pak->numfiles;i++)
                        {
                        pak = searchpath->pack;
                        for (i = 0;i < pak->numfiles;i++)
                        {
+                               char temp[MAX_OSPATH];
                                strlcpy(temp, pak->files[i].name, sizeof(temp));
                                while (temp[0])
                                {
                                strlcpy(temp, pak->files[i].name, sizeof(temp));
                                while (temp[0])
                                {
@@ -3569,6 +3698,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet)
 
                                // for each entry in matchedSet try to open the subdirectories specified in subpath
                                for( dirlistindex = 0 ; dirlistindex < matchedSet.numstrings ; dirlistindex++ ) {
 
                                // for each entry in matchedSet try to open the subdirectories specified in subpath
                                for( dirlistindex = 0 ; dirlistindex < matchedSet.numstrings ; dirlistindex++ ) {
+                                       char temp[MAX_OSPATH];
                                        strlcpy( temp, matchedSet.strings[ dirlistindex ], sizeof(temp) );
                                        strlcat( temp, subpath, sizeof(temp) );
                                        listdirectory( &foundSet, searchpath->filename, temp );
                                        strlcpy( temp, matchedSet.strings[ dirlistindex ], sizeof(temp) );
                                        strlcat( temp, subpath, sizeof(temp) );
                                        listdirectory( &foundSet, searchpath->filename, temp );
@@ -3592,17 +3722,17 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet)
 
                        for (dirlistindex = 0;dirlistindex < matchedSet.numstrings;dirlistindex++)
                        {
 
                        for (dirlistindex = 0;dirlistindex < matchedSet.numstrings;dirlistindex++)
                        {
-                               const char *temp = matchedSet.strings[dirlistindex];
-                               if (matchpattern(temp, (char *)pattern, true))
+                               const char *matchtemp = matchedSet.strings[dirlistindex];
+                               if (matchpattern(matchtemp, (char *)pattern, true))
                                {
                                        for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++)
                                {
                                        for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++)
-                                               if (!strcmp(resultlist.strings[resultlistindex], temp))
+                                               if (!strcmp(resultlist.strings[resultlistindex], matchtemp))
                                                        break;
                                        if (resultlistindex == resultlist.numstrings)
                                        {
                                                        break;
                                        if (resultlistindex == resultlist.numstrings)
                                        {
-                                               stringlistappend(&resultlist, temp);
+                                               stringlistappend(&resultlist, matchtemp);
                                                if (!quiet && developer_loading.integer)
                                                if (!quiet && developer_loading.integer)
-                                                       Con_Printf("SearchDirFile: %s\n", temp);
+                                                       Con_Printf("SearchDirFile: %s\n", matchtemp);
                                        }
                                }
                        }
                                        }
                                }
                        }
@@ -3713,43 +3843,43 @@ static int FS_ListDirectory(const char *pattern, int oneperline)
        return (int)numfiles;
 }
 
        return (int)numfiles;
 }
 
-static void FS_ListDirectoryCmd (const char* cmdname, int oneperline)
+static void FS_ListDirectoryCmd (cmd_state_t *cmd, const char* cmdname, int oneperline)
 {
        const char *pattern;
 {
        const char *pattern;
-       if (Cmd_Argc() >= 3)
+       if (Cmd_Argc(cmd) >= 3)
        {
                Con_Printf("usage:\n%s [path/pattern]\n", cmdname);
                return;
        }
        {
                Con_Printf("usage:\n%s [path/pattern]\n", cmdname);
                return;
        }
-       if (Cmd_Argc() == 2)
-               pattern = Cmd_Argv(1);
+       if (Cmd_Argc(cmd) == 2)
+               pattern = Cmd_Argv(cmd, 1);
        else
                pattern = "*";
        if (!FS_ListDirectory(pattern, oneperline))
                Con_Print("No files found.\n");
 }
 
        else
                pattern = "*";
        if (!FS_ListDirectory(pattern, oneperline))
                Con_Print("No files found.\n");
 }
 
-void FS_Dir_f(void)
+void FS_Dir_f(cmd_state_t *cmd)
 {
 {
-       FS_ListDirectoryCmd("dir", true);
+       FS_ListDirectoryCmd(cmd, "dir", true);
 }
 
 }
 
-void FS_Ls_f(void)
+void FS_Ls_f(cmd_state_t *cmd)
 {
 {
-       FS_ListDirectoryCmd("ls", false);
+       FS_ListDirectoryCmd(cmd, "ls", false);
 }
 
 }
 
-void FS_Which_f(void)
+void FS_Which_f(cmd_state_t *cmd)
 {
        const char *filename;
        int index;
        searchpath_t *sp;
 {
        const char *filename;
        int index;
        searchpath_t *sp;
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
        {
-               Con_Printf("usage:\n%s <file>\n", Cmd_Argv(0));
+               Con_Printf("usage:\n%s <file>\n", Cmd_Argv(cmd, 0));
                return;
        }  
                return;
        }  
-       filename = Cmd_Argv(1);
+       filename = Cmd_Argv(cmd, 1);
        sp = FS_FindFile(filename, &index, true);
        if (!sp) {
                Con_Printf("%s isn't anywhere\n", filename);
        sp = FS_FindFile(filename, &index, true);
        if (!sp) {
                Con_Printf("%s isn't anywhere\n", filename);
@@ -3813,7 +3943,7 @@ qboolean FS_IsRegisteredQuakePack(const char *name)
                                int diff;
 
                                middle = (left + right) / 2;
                                int diff;
 
                                middle = (left + right) / 2;
-                               diff = !strcmp_funct (pak->files[middle].name, "gfx/pop.lmp");
+                               diff = strcmp_funct (pak->files[middle].name, "gfx/pop.lmp");
 
                                // Found it
                                if (!diff)
 
                                // Found it
                                if (!diff)
@@ -3924,8 +4054,7 @@ unsigned char *FS_Deflate(const unsigned char *data, size_t size, size_t *deflat
                return NULL;
        }
 
                return NULL;
        }
 
-       if(deflated_size)
-               *deflated_size = (size_t)strm.total_out;
+       *deflated_size = (size_t)strm.total_out;
 
        memcpy(out, tmp, strm.total_out);
        Mem_Free(tmp);
 
        memcpy(out, tmp, strm.total_out);
        Mem_Free(tmp);
@@ -4039,8 +4168,7 @@ unsigned char *FS_Inflate(const unsigned char *data, size_t size, size_t *inflat
        memcpy(out, outbuf.data, outbuf.cursize);
        Mem_Free(outbuf.data);
 
        memcpy(out, outbuf.data, outbuf.cursize);
        Mem_Free(outbuf.data);
 
-       if(inflated_size)
-               *inflated_size = (size_t)outbuf.cursize;
+       *inflated_size = (size_t)outbuf.cursize;
        
        return out;
 }
        
        return out;
 }