]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - fs.c
merged CL_MoveParticles, CL_MoveDecals, and R_MoveExplosions into their
[xonotic/darkplaces.git] / fs.c
diff --git a/fs.c b/fs.c
index 74329aaf779185b2c82ce6e165fa21144e357592..64b275485d95ba1b6f6fbefb09b3f4087eb8c2ab 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -22,9 +22,6 @@
                Boston, MA  02111-1307, USA
 */
 
-// on UNIX platforms we need to define this so that video saving does not cause a SIGFSZ (file size) signal when a video clip exceeds 2GB
-#define _FILE_OFFSET_BITS 64
-
 #include "quakedef.h"
 
 #include <limits.h>
@@ -33,6 +30,7 @@
 #ifdef WIN32
 # include <direct.h>
 # include <io.h>
+# include <shlobj.h>
 #else
 # include <pwd.h>
 # include <sys/stat.h>
 # define O_NONBLOCK 0
 #endif
 
+// largefile support for Win32
+#ifdef WIN32
+# define lseek _lseeki64
+#endif
 
 /*
 
@@ -274,7 +276,6 @@ char fs_gamedir[MAX_OSPATH];
 char fs_basedir[MAX_OSPATH];
 
 // list of active game directories (empty if not running a mod)
-#define MAX_GAMEDIRS 16
 int fs_numgamedirs = 0;
 char fs_gamedirs[MAX_GAMEDIRS][MAX_QPATH];
 
@@ -1012,19 +1013,50 @@ FS_AddGameHierarchy
 */
 void FS_AddGameHierarchy (const char *dir)
 {
-#ifndef WIN32
+       int i;
+       char userdir[MAX_QPATH];
+#ifdef WIN32
+       TCHAR mydocsdir[MAX_PATH + 1];
+#else
        const char *homedir;
 #endif
 
        // Add the common game directory
        FS_AddGameDirectory (va("%s%s/", fs_basedir, dir));
 
-#ifndef WIN32
+       *userdir = 0;
+
        // Add the personal game directory
+#ifdef WIN32
+       if(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, mydocsdir) == S_OK)
+               dpsnprintf(userdir, sizeof(userdir), "%s/My Games/%s/", mydocsdir, gameuserdirname);
+       fprintf(stderr, "userdir = %s\n", userdir);
+#else
        homedir = getenv ("HOME");
-       if (homedir != NULL && homedir[0] != '\0')
-               FS_AddGameDirectory (va("%s/.%s/%s/", homedir, gameuserdirname, dir));
+       if(homedir)
+               dpsnprintf(userdir, sizeof(userdir), "%s/.%s/", homedir, gameuserdirname);
+#endif
+
+#ifdef WIN32
+       if(!COM_CheckParm("-mygames"))
+       {
+               int fd = open (va("%s%s/config.cfg", fs_basedir, dir), O_WRONLY | O_CREAT, 0666); // note: no O_TRUNC here!
+               if(fd >= 0)
+               {
+                       close(fd);
+                       *userdir = 0; // we have write access to the game dir, so let's use it
+               }
+       }
 #endif
+
+       if(COM_CheckParm("-nohome"))
+               *userdir = 0;
+       
+       if((i = COM_CheckParm("-userdir")) && i < com_argc - 1)
+               dpsnprintf(userdir, sizeof(userdir), "%s/", com_argv[i+1]);
+
+       if (*userdir)
+               FS_AddGameDirectory(va("%s%s/", userdir, dir));
 }
 
 
@@ -1080,12 +1112,18 @@ FS_ClearSearchPath
 */
 void FS_ClearSearchPath (void)
 {
+       // unload all packs and directory information, close all pack files
+       // (if a qfile is still reading a pack it won't be harmed because it used
+       //  dup() to get its own handle already)
        while (fs_searchpaths)
        {
                searchpath_t *search = fs_searchpaths;
                fs_searchpaths = search->next;
                if (search->pack)
                {
+                       // close the file
+                       close(search->pack->handle);
+                       // free any memory associated with it
                        if (search->pack->files)
                                Mem_Free(search->pack->files);
                        Mem_Free(search->pack);
@@ -1173,7 +1211,7 @@ void FS_Rescan_f(void)
 FS_ChangeGameDirs
 ================
 */
-extern void Host_SaveConfig_f (void);
+extern void Host_SaveConfig (void);
 extern void Host_LoadConfig_f (void);
 qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean complain, qboolean failmissing)
 {
@@ -1216,7 +1254,10 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean
                }
        }
 
-       Host_SaveConfig_f();
+       // halt demo playback to close the file
+       CL_Disconnect();
+
+       Host_SaveConfig();
 
        fs_numgamedirs = numgamedirs;
        for (i = 0;i < fs_numgamedirs;i++)
@@ -1228,8 +1269,8 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean
        // exec the new config
        Host_LoadConfig_f();
 
-       // reinitialize the loaded sounds
-       S_Reload_f();
+       // unload all sounds so they will be reloaded from the new files as needed
+       S_UnloadAllSounds_f();
 
        // reinitialize renderer (this reloads hud/console background/etc)
        R_Modules_Restart();
@@ -1267,11 +1308,7 @@ void FS_GameDir_f (void)
        for (i = 0;i < numgamedirs;i++)
                strlcpy(gamedirs[i], Cmd_Argv(i+1), sizeof(gamedirs[i]));
 
-       // allow gamedir change during demo loop
-       if (cls.demoplayback)
-               CL_Disconnect();
-
-       if (cls.state == ca_connected || sv.active)
+       if ((cls.state == ca_connected && !cls.demoplayback) || sv.active)
        {
                // actually, changing during game would work fine, but would be stupid
                Con_Printf("Can not change gamedir while client is connected or server is running!\n");
@@ -1400,6 +1437,10 @@ FS_Shutdown
 */
 void FS_Shutdown (void)
 {
+       // close all pack files and such
+       // (hopefully there aren't any other open files, but they'll be cleaned up
+       //  by the OS anyway)
+       FS_ClearSearchPath();
        Mem_FreePool (&fs_mempool);
 }
 
@@ -1886,12 +1927,12 @@ fs_offset_t FS_Read (qfile_t* file, void* buffer, size_t buffersize)
        if (file->buff_ind < file->buff_len)
        {
                count = file->buff_len - file->buff_ind;
+               count = ((fs_offset_t)buffersize > count) ? count : (fs_offset_t)buffersize;
+               done += count;
+               memcpy (buffer, &file->buff[file->buff_ind], count);
+               file->buff_ind += count;
 
-               done += ((fs_offset_t)buffersize > count) ? count : (fs_offset_t)buffersize;
-               memcpy (buffer, &file->buff[file->buff_ind], done);
-               file->buff_ind += done;
-
-               buffersize -= done;
+               buffersize -= count;
                if (buffersize == 0)
                        return done;
        }
@@ -2103,7 +2144,7 @@ Get the next character of a file
 */
 int FS_Getc (qfile_t* file)
 {
-       char c;
+       unsigned char c;
 
        if (FS_Read (file, &c, 1) != 1)
                return EOF;
@@ -2160,7 +2201,7 @@ int FS_Seek (qfile_t* file, fs_offset_t offset, int whence)
                default:
                        return -1;
        }
-       if (offset < 0 || offset > (long) file->real_length)
+       if (offset < 0 || offset > file->real_length)
                return -1;
 
        // If we have the data in our read buffer, we don't need to actually seek