Boston, MA 02111-1307, USA
*/
+#ifdef WIN32
+# include <direct.h>
+# include <io.h>
+# include <shlobj.h>
+#endif
+
+// on *x, we MUST include "quakedef.h" before anything that may include IO
+// functions to get _FILE_OFFSET_BITS
#include "quakedef.h"
+#ifdef __APPLE__
+// include SDL for IPHONEOS code
+# include <TargetConditionals.h>
+# if TARGET_OS_IPHONE
+# include <SDL.h>
+# endif
+#endif
+
#include <limits.h>
#include <fcntl.h>
-#ifdef WIN32
-# include <direct.h>
-# include <io.h>
-# include <shlobj.h>
-#else
+#ifndef WIN32
# include <pwd.h>
# include <sys/stat.h>
# include <unistd.h>
#define ZIP_CDIR_CHUNK_BASE_SIZE 46
#define ZIP_LOCAL_CHUNK_BASE_SIZE 30
+#ifdef LINK_TO_ZLIB
+#include <zlib.h>
+
+#define qz_inflate inflate
+#define qz_inflateEnd inflateEnd
+#define qz_inflateInit2_ inflateInit2_
+#define qz_inflateReset inflateReset
+#define qz_deflateInit2_ deflateInit2_
+#define qz_deflateEnd deflateEnd
+#define qz_deflate deflate
+#define Z_MEMLEVEL_DEFAULT 8
+#else
+
// Zlib constants (from zlib.h)
#define Z_SYNC_FLUSH 2
#define MAX_WBITS 15
unsigned long adler; ///< adler32 value of the uncompressed data
unsigned long reserved; ///< reserved for future use
} z_stream;
+#endif
/// inside a package (PAK or PK3)
#define QFILE_FLAG_DEFLATED (1 << 1)
/// file is actually already loaded data
#define QFILE_FLAG_DATA (1 << 2)
+/// real file will be removed on close
+#define QFILE_FLAG_REMOVE (1 << 3)
#define FILE_BUFF_SIZE 2048
typedef struct
ztoolkit_t* ztk; ///< For zipped files.
const unsigned char *data; ///< For data files.
+
+ const char *filename; ///< Kept around for QFILE_FLAG_REMOVE, unused otherwise
};
unsigned int cdir_size; ///< size of the central directory
unsigned int cdir_offset; ///< with respect to the starting disk number
unsigned short comment_size;
+ fs_offset_t prepended_garbage;
} pk3_endOfCentralDir_t;
int handle;
int ignorecase; ///< PK3 ignores case
int numfiles;
+ qboolean vpack;
packfile_t *files;
} pack_t;
//@}
char fs_userdir[MAX_OSPATH];
char fs_gamedir[MAX_OSPATH];
char fs_basedir[MAX_OSPATH];
+static pack_t *fs_selfpack = NULL;
// list of active game directories (empty if not running a mod)
int fs_numgamedirs = 0;
=============================================================================
*/
+#ifndef LINK_TO_ZLIB
// Functions exported from zlib
#if defined(WIN32) && defined(ZLIB_USES_WINAPI)
# define ZEXPORT WINAPI
static int (ZEXPORT *qz_deflateInit2_) (z_stream* strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size);
static int (ZEXPORT *qz_deflateEnd) (z_stream* strm);
static int (ZEXPORT *qz_deflate) (z_stream* strm, int flush);
+#endif
#define qz_inflateInit2(strm, windowBits) \
qz_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
#define qz_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
qz_deflateInit2_((strm), (level), (method), (windowBits), (memLevel), (strategy), ZLIB_VERSION, sizeof(z_stream))
+#ifndef LINK_TO_ZLIB
// qz_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
static dllfunction_t zlibfuncs[] =
/// Handle for Zlib DLL
static dllhandle_t zlib_dll = NULL;
+#endif
#ifdef WIN32
static HRESULT (WINAPI *qSHGetFolderPath) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
*/
void PK3_CloseLibrary (void)
{
+#ifndef LINK_TO_ZLIB
Sys_UnloadLibrary (&zlib_dll);
+#endif
}
*/
qboolean PK3_OpenLibrary (void)
{
+#ifdef LINK_TO_ZLIB
+ return true;
+#else
const char* dllnames [] =
{
-#if defined(WIN64)
- "zlib64.dll",
-#elif defined(WIN32)
+#if defined(WIN32)
# ifdef ZLIB_USES_WINAPI
"zlibwapi.dll",
"zlib.dll",
// Load the DLL
return Sys_LoadLibrary (dllnames, &zlib_dll, zlibfuncs);
+#endif
}
/*
*/
qboolean FS_HasZlib(void)
{
+#ifdef LINK_TO_ZLIB
+ return true;
+#else
PK3_OpenLibrary(); // to be safe
return (zlib_dll != 0);
+#endif
}
/*
eocd->cdir_size = LittleLong (eocd->cdir_size);
eocd->cdir_offset = LittleLong (eocd->cdir_offset);
eocd->comment_size = LittleShort (eocd->comment_size);
+ eocd->prepended_garbage = filesize - (ind + ZIP_END_CDIR_SIZE) - eocd->cdir_offset - eocd->cdir_size; // this detects "SFX" zip files
+ eocd->cdir_offset += eocd->prepended_garbage;
Mem_Free (buffer);
// Load the central directory in memory
central_dir = (unsigned char *)Mem_Alloc (tempmempool, eocd->cdir_size);
lseek (pack->handle, eocd->cdir_offset, SEEK_SET);
- if(read (pack->handle, central_dir, eocd->cdir_size) != (ssize_t) eocd->cdir_size)
+ if(read (pack->handle, central_dir, eocd->cdir_size) != (fs_offset_t) eocd->cdir_size)
{
Mem_Free (central_dir);
return -1;
flags = PACKFILE_FLAG_DEFLATED;
else
flags = 0;
- offset = BuffLittleLong (&ptr[42]);
- packsize = BuffLittleLong (&ptr[20]);
- realsize = BuffLittleLong (&ptr[24]);
+ offset = (unsigned int)(BuffLittleLong (&ptr[42]) + eocd->prepended_garbage);
+ packsize = (unsigned int)BuffLittleLong (&ptr[20]);
+ realsize = (unsigned int)BuffLittleLong (&ptr[24]);
switch(ptr[5]) // C_VERSION_MADE_BY_1
{
Create a package entry associated with a PK3 file
====================
*/
-pack_t *FS_LoadPackPK3 (const char *packfile)
+pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qboolean silent)
{
- int packhandle;
pk3_endOfCentralDir_t eocd;
pack_t *pack;
int real_nb_files;
-#if _MSC_VER >= 1400
- _sopen_s(&packhandle, packfile, O_RDONLY | O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE);
-#else
- packhandle = open (packfile, O_RDONLY | O_BINARY);
-#endif
- if (packhandle < 0)
- return NULL;
-
if (! PK3_GetEndOfCentralDir (packfile, packhandle, &eocd))
{
- Con_Printf ("%s is not a PK3 file\n", packfile);
+ if(!silent)
+ Con_Printf ("%s is not a PK3 file\n", packfile);
close(packhandle);
return NULL;
}
return NULL;
}
- Con_Printf("Added packfile %s (%i files)\n", packfile, real_nb_files);
+ Con_DPrintf("Added packfile %s (%i files)\n", packfile, real_nb_files);
return pack;
}
+pack_t *FS_LoadPackPK3 (const char *packfile)
+{
+ int packhandle;
+#if _MSC_VER >= 1400
+ _sopen_s(&packhandle, packfile, O_RDONLY | O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE);
+#else
+ packhandle = open (packfile, O_RDONLY | O_BINARY);
+#endif
+ if (packhandle < 0)
+ return NULL;
+ return FS_LoadPackPK3FromFD(packfile, packhandle, false);
+}
/*
for (s=fs_searchpaths ; s ; s=s->next)
{
if (s->pack)
- Con_Printf("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
+ {
+ if(s->pack->vpack)
+ Con_Printf("%sdir (virtual pack)\n", s->pack->filename);
+ else
+ Con_Printf("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
+ }
else
Con_Printf("%s\n", s->filename);
}
// parse the directory
for (i = 0;i < numpackfiles;i++)
{
- fs_offset_t offset = LittleLong (info[i].filepos);
- fs_offset_t size = LittleLong (info[i].filelen);
+ fs_offset_t offset = (unsigned int)LittleLong (info[i].filepos);
+ fs_offset_t size = (unsigned int)LittleLong (info[i].filelen);
FS_AddFileToPack (info[i].name, pack, offset, size, size, PACKFILE_FLAG_TRUEOFFS);
}
Mem_Free(info);
- Con_Printf("Added packfile %s (%i files)\n", packfile, numpackfiles);
+ Con_DPrintf("Added packfile %s (%i files)\n", packfile, numpackfiles);
+ return pack;
+}
+
+/*
+====================
+FS_LoadPackVirtual
+
+Create a package entry associated with a directory file
+====================
+*/
+pack_t *FS_LoadPackVirtual (const char *dirname)
+{
+ pack_t *pack;
+ pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
+ pack->vpack = true;
+ pack->ignorecase = false;
+ strlcpy (pack->filename, dirname, sizeof(pack->filename));
+ pack->handle = -1;
+ pack->numfiles = -1;
+ pack->files = NULL;
+ Con_DPrintf("Added packfile %s (virtual pack)\n", dirname);
return pack;
}
searchpath_t *search;
pack_t *pak = NULL;
const char *ext = FS_FileExtension(pakfile);
+ size_t l;
for(search = fs_searchpaths; search; search = search->next)
{
if(already_loaded)
*already_loaded = false;
- if(!strcasecmp(ext, "pak"))
+ if(!strcasecmp(ext, "pk3dir"))
+ pak = FS_LoadPackVirtual (pakfile);
+ else if(!strcasecmp(ext, "pak"))
pak = FS_LoadPackPAK (pakfile);
else if(!strcasecmp(ext, "pk3"))
pak = FS_LoadPackPK3 (pakfile);
else
Con_Printf("\"%s\" does not have a pack extension\n", pakfile);
- if (pak)
+ if(pak)
{
strlcpy(pak->shortname, shortname, sizeof(pak->shortname));
+
//Con_DPrintf(" Registered pack with short name %s\n", shortname);
if(keep_plain_dirs)
{
if(!insertion_point)
{
search = (searchpath_t *)Mem_Alloc(fs_mempool, sizeof(searchpath_t));
- search->pack = pak;
search->next = fs_searchpaths;
fs_searchpaths = search;
}
// otherwise we want to append directly after insertion_point.
{
search = (searchpath_t *)Mem_Alloc(fs_mempool, sizeof(searchpath_t));
- search->pack = pak;
search->next = insertion_point->next;
insertion_point->next = search;
}
else
{
search = (searchpath_t *)Mem_Alloc(fs_mempool, sizeof(searchpath_t));
- search->pack = pak;
search->next = fs_searchpaths;
fs_searchpaths = search;
}
+ search->pack = pak;
+ if(pak->vpack)
+ {
+ dpsnprintf(search->filename, sizeof(search->filename), "%s/", pakfile);
+ // if shortname ends with "pk3dir", strip that suffix to make it just "pk3"
+ // same goes for the name inside the pack structure
+ l = strlen(pak->shortname);
+ if(l >= 7)
+ if(!strcasecmp(pak->shortname + l - 7, ".pk3dir"))
+ pak->shortname[l - 3] = 0;
+ l = strlen(pak->filename);
+ if(l >= 7)
+ if(!strcasecmp(pak->filename + l - 7, ".pk3dir"))
+ pak->filename[l - 3] = 0;
+ }
return true;
}
else
// add any PK3 package in the directory
for (i = 0;i < list.numstrings;i++)
{
- if (!strcasecmp(FS_FileExtension(list.strings[i]), "pk3"))
+ if (!strcasecmp(FS_FileExtension(list.strings[i]), "pk3") || !strcasecmp(FS_FileExtension(list.strings[i]), "pk3dir"))
{
FS_AddPack_Fullpath(list.strings[i], list.strings[i] + strlen(dir), NULL, false);
}
{
searchpath_t *search = fs_searchpaths;
fs_searchpaths = search->next;
- if (search->pack)
+ if (search->pack && search->pack != fs_selfpack)
{
- // close the file
- close(search->pack->handle);
- // free any memory associated with it
- if (search->pack->files)
- Mem_Free(search->pack->files);
+ if(!search->pack->vpack)
+ {
+ // 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);
}
Mem_Free(search);
}
}
+static void FS_AddSelfPack(void)
+{
+ if(fs_selfpack)
+ {
+ searchpath_t *search;
+ search = (searchpath_t *)Mem_Alloc(fs_mempool, sizeof(searchpath_t));
+ search->next = fs_searchpaths;
+ search->pack = fs_selfpack;
+ fs_searchpaths = search;
+ }
+}
+
/*
================
{
int i;
qboolean fs_modified = false;
+ qboolean reset = false;
char gamedirbuf[MAX_INPUTLINE];
+ if (fs_searchpaths)
+ reset = true;
FS_ClearSearchPath();
+ // automatically activate gamemode for the gamedirs specified
+ if (reset)
+ COM_ChangeGameTypeForGameDirs();
+
// add the game-specific paths
// gamedirname1 (typically id1)
FS_AddGameHierarchy (gamedirname1);
}
Cvar_SetQuick(&cvar_fs_gamedir, gamedirbuf); // so QC or console code can query it
+ // add back the selfpack as new first item
+ FS_AddSelfPack();
+
// set the default screenshot name to either the mod name or the
// gamemode screenshot name
if (strcmp(com_modname, gamedirname1))
unlink (va("%s/qconsole.log", fs_gamedir));
// look for the pop.lmp file and set registered to true if it is found
- if ((gamemode == GAME_NORMAL || gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE) && !FS_FileExists("gfx/pop.lmp"))
+ if (FS_FileExists("gfx/pop.lmp"))
+ Cvar_Set ("registered", "1");
+ switch(gamemode)
{
- if (fs_modified)
- Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
+ case GAME_NORMAL:
+ case GAME_HIPNOTIC:
+ case GAME_ROGUE:
+ if (!registered.integer)
+ {
+ if (fs_modified)
+ Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n");
+ else
+ Con_Print("Playing shareware version.\n");
+ }
else
- Con_Print("Playing shareware version.\n");
- }
- else
- {
- Cvar_Set ("registered", "1");
- if (gamemode == GAME_NORMAL || gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
Con_Print("Playing registered version.\n");
+ break;
+ case GAME_STEELSTORM:
+ if (registered.integer)
+ Con_Print("Playing registered version.\n");
+ else
+ Con_Print("Playing shareware version.\n");
+ break;
+ default:
+ break;
}
// unload all wads so that future queries will return the new data
*/
extern void Host_SaveConfig (void);
extern void Host_LoadConfig_f (void);
+extern qboolean vid_opened;
+extern void VID_Stop(void);
qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean complain, qboolean failmissing)
{
int i;
// reinitialize filesystem to detect the new paks
FS_Rescan();
- // exec the new config
- Host_LoadConfig_f();
+ if (cls.demoplayback)
+ {
+ CL_Disconnect_f();
+ cls.demonum = 0;
+ }
// 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();
+ // close down the video subsystem, it will start up again when the config finishes...
+ VID_Stop();
+ vid_opened = false;
+
+ // restart the video subsystem after the config is executed
+ Cbuf_InsertText("\nloadconfig\nvid_restart\n\n");
return true;
}
FS_ChangeGameDirs(numgamedirs, gamedirs, true, true);
}
-static qfile_t* FS_SysOpen (const char* filepath, const char* mode, qboolean nonblocking);
static const char *FS_SysCheckGameDir(const char *gamedir)
{
static char buf[8192];
}
stringlistfreecontents(&list);
- fs_all_gamedirs = Mem_Alloc(fs_mempool, list2.numstrings * sizeof(*fs_all_gamedirs));
+ fs_all_gamedirs = (gamedir_t *)Mem_Alloc(fs_mempool, list2.numstrings * sizeof(*fs_all_gamedirs));
for(i = 0; i < list2.numstrings; ++i)
{
info = FS_CheckGameDir(list2.strings[i]);
}
}
+/*
+================
+FS_Init_SelfPack
+================
+*/
+void FS_Init_SelfPack (void)
+{
+ PK3_OpenLibrary ();
+ fs_mempool = Mem_AllocPool("file management", 0, NULL);
+ if(com_selffd >= 0)
+ {
+ 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))
+ {
+ if(i >= args_left)
+ break;
+ q = (char *)Mem_Alloc(fs_mempool, strlen(com_token) + 1);
+ strlcpy(q, com_token, strlen(com_token) + 1);
+ 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);
+ }
+ }
+}
+
/*
================
FS_Init
size_t homedirlen;
#endif
#endif
+#ifndef __IPHONEOS__
char *homedir;
+#endif
#ifdef WIN32
const char* dllnames [] =
// don't care for the result; if it fails, %USERPROFILE% will be used instead
#endif
- fs_mempool = Mem_AllocPool("file management", 0, NULL);
+ *fs_basedir = 0;
+ *fs_userdir = 0;
+ *fs_gamedir = 0;
+#ifdef __IPHONEOS__
+ // fs_basedir is "" by default, to utilize this you can simply add your gamedir to the Resources in xcode
+ // fs_userdir stores configurations to the Documents folder of the app
+ strlcpy(fs_userdir, "../Documents/", sizeof(fs_userdir));
+#else
// Add the personal game directory
if((i = COM_CheckParm("-userdir")) && i < com_argc - 1)
{
}
#endif
#endif
-
- PK3_OpenLibrary ();
+#endif
// -basedir <path>
// Overrides the system supplied base directory (under GAMENAME)
#endif
}
-/*
-====================
-FS_SysOpen
-
-Internal function used to create a qfile_t and open the relevant non-packed file on disk
-====================
-*/
-static qfile_t* FS_SysOpen (const char* filepath, const char* mode, qboolean nonblocking)
+int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
{
- qfile_t* file;
+ int handle;
int mod, opt;
unsigned int ind;
break;
default:
Con_Printf ("FS_SysOpen(%s, %s): invalid mode\n", filepath, mode);
- return NULL;
+ return -1;
}
for (ind = 1; mode[ind] != '\0'; ind++)
{
if (nonblocking)
opt |= O_NONBLOCK;
- file = (qfile_t *)Mem_Alloc (fs_mempool, sizeof (*file));
- memset (file, 0, sizeof (*file));
- file->ungetc = EOF;
-
#if _MSC_VER >= 1400
- _sopen_s(&file->handle, filepath, mod | opt, _SH_DENYNO, _S_IREAD | _S_IWRITE);
+ _sopen_s(&handle, filepath, mod | opt, _SH_DENYNO, _S_IREAD | _S_IWRITE);
#else
- file->handle = open (filepath, mod | opt, 0666);
+ handle = open (filepath, mod | opt, 0666);
#endif
+ return handle;
+}
+
+/*
+====================
+FS_SysOpen
+
+Internal function used to create a qfile_t and open the relevant non-packed file on disk
+====================
+*/
+qfile_t* FS_SysOpen (const char* filepath, const char* mode, qboolean nonblocking)
+{
+ qfile_t* file;
+
+ file = (qfile_t *)Mem_Alloc (fs_mempool, sizeof (*file));
+ file->ungetc = EOF;
+ file->handle = FS_SysOpenFD(filepath, mode, nonblocking);
if (file->handle < 0)
{
Mem_Free (file);
return NULL;
}
+ file->filename = Mem_strdup(fs_mempool, filepath);
+
file->real_length = lseek (file->handle, 0, SEEK_END);
// For files opened in append mode, we start at the end of the file
- if (mod & O_APPEND)
+ if (mode[0] == 'a')
file->position = file->real_length;
else
lseek (file->handle, 0, SEEK_SET);
if (!PK3_GetTrueFileOffset (pfile, pack))
return NULL;
+#ifndef LINK_TO_ZLIB
// No Zlib DLL = no compressed files
if (!zlib_dll && (pfile->flags & PACKFILE_FLAG_DEFLATED))
{
pfile->name);
return NULL;
}
+#endif
// LordHavoc: lseek 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
if (lseek (pack->handle, pfile->offset, SEEK_SET) == -1)
{
- Con_Printf ("FS_OpenPackedFile: can't lseek to %s in %s (offset: %d)\n",
- pfile->name, pack->filename, (int) pfile->offset);
+ 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;
}
for (search = fs_searchpaths;search;search = search->next)
{
// is the element a pak file?
- if (search->pack)
+ if (search->pack && !search->pack->vpack)
{
int (*strcmp_funct) (const char* str1, const char* str2);
int left, right, middle;
if (fs_empty_files_in_pack_mark_deletions.integer && pak->files[middle].realsize == 0)
{
// yes, but the first one is empty so we treat it as not being there
- if (!quiet && developer.integer >= 10)
- Con_Printf("FS_FindFile: %s is marked as deleted\n", name);
+ if (!quiet && developer_extra.integer)
+ Con_DPrintf("FS_FindFile: %s is marked as deleted\n", name);
if (index != NULL)
*index = -1;
return NULL;
}
- if (!quiet && developer.integer >= 10)
- Con_Printf("FS_FindFile: %s in %s\n",
+ if (!quiet && developer_extra.integer)
+ Con_DPrintf("FS_FindFile: %s in %s\n",
pak->files[middle].name, pak->filename);
if (index != NULL)
dpsnprintf(netpath, sizeof(netpath), "%s%s", search->filename, name);
if (FS_SysFileExists (netpath))
{
- if (!quiet && developer.integer >= 10)
- Con_Printf("FS_FindFile: %s\n", netpath);
+ if (!quiet && developer_extra.integer)
+ Con_DPrintf("FS_FindFile: %s\n", netpath);
if (index != NULL)
*index = -1;
}
}
- if (!quiet && developer.integer >= 10)
- Con_Printf("FS_FindFile: can't find %s\n", name);
+ if (!quiet && developer_extra.integer)
+ Con_DPrintf("FS_FindFile: can't find %s\n", name);
if (index != NULL)
*index = -1;
// Found in the filesystem?
if (pack_ind < 0)
{
+ // this works with vpacks, so we are fine
char path [MAX_OSPATH];
dpsnprintf (path, sizeof (path), "%s%s", search->filename, filename);
return FS_SysOpen (path, "rb", nonblocking);
return NULL;
}
- dpsnprintf (real_path, sizeof (real_path), "%s/%s", fs_gamedir, filepath);
+ dpsnprintf (real_path, sizeof (real_path), "%s/%s", fs_gamedir, filepath); // this is never a vpack
// If the file is opened in "write", "append", or "read/write" mode,
// create directories up to the file.
if (close (file->handle))
return EOF;
+ if (file->filename)
+ {
+ if (file->flags & QFILE_FLAG_REMOVE)
+ remove(file->filename);
+
+ Mem_Free((void *) file->filename);
+ }
+
if (file->ztk)
{
qz_inflateEnd (&file->ztk->zstream);
return 0;
}
+void FS_RemoveOnClose(qfile_t* file)
+{
+ file->flags |= QFILE_FLAG_REMOVE;
+}
/*
====================
The filename will be prefixed by the current game directory
============
*/
-qboolean FS_WriteFile (const char *filename, void *data, fs_offset_t len)
+qboolean FS_WriteFileInBlocks (const char *filename, const void *const *data, const fs_offset_t *len, size_t count)
{
qfile_t *file;
+ size_t i;
+ fs_offset_t lentotal;
file = FS_OpenRealFile(filename, "wb", false);
if (!file)
return false;
}
- Con_DPrintf("FS_WriteFile: %s (%u bytes)\n", filename, (unsigned int)len);
- FS_Write (file, data, len);
+ lentotal = 0;
+ for(i = 0; i < count; ++i)
+ lentotal += len[i];
+ Con_DPrintf("FS_WriteFile: %s (%u bytes)\n", filename, (unsigned int)lentotal);
+ for(i = 0; i < count; ++i)
+ FS_Write (file, data[i], len[i]);
FS_Close (file);
return true;
}
+qboolean FS_WriteFile (const char *filename, const void *data, fs_offset_t len)
+{
+ return FS_WriteFileInBlocks(filename, &data, &len, 1);
+}
+
/*
=============================================================================
if(!search)
return FS_FILETYPE_NONE;
- if(search->pack)
+ if(search->pack && !search->pack->vpack)
return FS_FILETYPE_FILE; // TODO can't check directories in paks yet, maybe later
dpsnprintf(fullpath, sizeof(fullpath), "%s%s", search->filename, filename);
if (stat (path,&buf) == -1)
return FS_FILETYPE_NONE;
+#ifndef S_ISDIR
+#define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
+#endif
if(S_ISDIR(buf.st_mode))
return FS_FILETYPE_DIRECTORY;
for (searchpath = fs_searchpaths;searchpath;searchpath = searchpath->next)
{
// is the element a pak file?
- if (searchpath->pack)
+ if (searchpath->pack && !searchpath->pack->vpack)
{
// look through all the pak file elements
pak = searchpath->pack;
return;
}
if (sp->pack)
- Con_Printf("%s is in package %s\n", filename, sp->pack->shortname);
+ {
+ if(sp->pack->vpack)
+ Con_Printf("%s is in virtual package %sdir\n", filename, sp->pack->shortname);
+ else
+ Con_Printf("%s is in package %s\n", filename, sp->pack->shortname);
+ }
else
Con_Printf("%s is file %s%s\n", filename, sp->filename, filename);
}
// search through the path, one element at a time
for (search = fs_searchpaths;search;search = search->next)
{
- if (search->pack && !strcasecmp(FS_FileWithoutPath(search->filename), name))
+ if (search->pack && !search->pack->vpack && !strcasecmp(FS_FileWithoutPath(search->filename), name))
+ // TODO do we want to support vpacks in here too?
{
int (*strcmp_funct) (const char* str1, const char* str2);
int left, right, middle;
unsigned char *tmp;
*deflated_size = 0;
+#ifndef LINK_TO_ZLIB
if(!zlib_dll)
return NULL;
+#endif
memset(&strm, 0, sizeof(strm));
strm.zalloc = Z_NULL;
sizebuf_t outbuf;
*inflated_size = 0;
+#ifndef LINK_TO_ZLIB
if(!zlib_dll)
return NULL;
+#endif
memset(&outbuf, 0, sizeof(outbuf));
outbuf.data = (unsigned char *) Mem_Alloc(tempmempool, sizeof(tmp));