From ea14d7facc60851bf24250a2836ecc79b4decd5f Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 15 Mar 2006 20:05:25 +0000 Subject: [PATCH] If someone tries seeking in a compressed file, don't flush and redecompress, just copy it to a temp file instead and work from there (this is primarily for roq files like the one from q3f). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2121 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/common/fs.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/engine/common/fs.c b/engine/common/fs.c index 9c97cb854..2642ddb62 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -901,6 +901,8 @@ int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype) typedef struct { vfsfile_t funcs; + vfsfile_t *defer; + //in case we're forced away. zipfile_t *parent; qboolean iscompressed; @@ -941,6 +943,9 @@ int VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) int read; vfszip_t *vfsz = (vfszip_t*)file; + if (vfsz->defer) + return VFS_READ(vfsz->defer, buffer, bytestoread); + if (vfsz->iscompressed) { VFSZIP_MakeActive(vfsz); @@ -969,11 +974,49 @@ qboolean VFSZIP_Seek (struct vfsfile_s *file, unsigned long pos) { vfszip_t *vfsz = (vfszip_t*)file; + if (vfsz->defer) + return VFS_SEEK(vfsz->defer, pos); + //This is *really* inefficient if (vfsz->parent->currentfile == file) { + if (vfsz->iscompressed) + { //if they're going to seek on a file in a zip, let's just copy it out + char buffer[8192]; + unsigned int chunk; + unsigned int i; + unsigned int length; + + vfsz->defer = FS_OpenTemp(); + if (vfsz->defer) + { + unzCloseCurrentFile(vfsz->parent->handle); + vfsz->parent->currentfile = NULL; //make it not us + + length = vfsz->length; + i = 0; + vfsz->pos = 0; + VFSZIP_MakeActive(vfsz); + while (1) + { + chunk = length - i; + if (chunk > sizeof(buffer)) + chunk = sizeof(buffer); + if (chunk == 0) + break; + unzReadCurrentFile(vfsz->parent->handle, buffer, chunk); + VFS_WRITE(vfsz->defer, buffer, chunk); + + i += chunk; + } + } + } + unzCloseCurrentFile(vfsz->parent->handle); vfsz->parent->currentfile = NULL; //make it not us + + if (vfsz->defer) + return VFS_SEEK(vfsz->defer, pos); } @@ -987,6 +1030,10 @@ qboolean VFSZIP_Seek (struct vfsfile_s *file, unsigned long pos) unsigned long VFSZIP_Tell (struct vfsfile_s *file) { vfszip_t *vfsz = (vfszip_t*)file; + + if (vfsz->defer) + return VFS_TELL(vfsz->defer); + return vfsz->pos; } unsigned long VFSZIP_GetLen (struct vfsfile_s *file) @@ -1001,6 +1048,9 @@ void VFSZIP_Close (struct vfsfile_s *file) if (vfsz->parent->currentfile == file) vfsz->parent->currentfile = NULL; //make it not us + if (vfsz->defer) + VFS_CLOSE(vfsz->defer); + FSZIP_ClosePath(vfsz->parent); Z_Free(vfsz); } @@ -1040,6 +1090,7 @@ vfsfile_t *FSZIP_OpenVFS(void *handle, flocation_t *loc, char *mode) } zip->references++; + return (vfsfile_t*)vfsz; }