]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/common/vfs.c
Merge commit '2b85b7c20c20df677e30541c93b80725dc2277c9' into garux-merge
[xonotic/netradiant.git] / tools / quake3 / common / vfs.c
index ada7ee713c14d8548e51b273e7e119a95401157d..a76d3172af5733dde66351ed77ef4cbb9a386c8d 100644 (file)
 #include "mathlib.h"
 #include "inout.h"
 #include "vfs.h"
-#include "unzip.h"
+#include <minizip/unzip.h>
+#include <glib.h>
+#define BAD_MINIZ
+#ifndef BAD_MINIZ
+#include "miniz.h"
+#endif
 
 typedef struct
 {
        char*   name;
-       unz_s zipinfo;
        unzFile zipfile;
+       unz_file_pos zippos;
        guint32 size;
 } VFS_PAKFILE;
 
@@ -122,6 +127,7 @@ static void vfsInitPakFile( const char *filename ){
        for ( i = 0; i < gi.number_entry; i++ )
        {
                char filename_inzip[NAME_MAX];
+               char *filename_lower;
                unz_file_info file_info;
                VFS_PAKFILE* file;
 
@@ -129,17 +135,23 @@ static void vfsInitPakFile( const char *filename ){
                if ( err != UNZ_OK ) {
                        break;
                }
+               unz_file_pos pos;
+               err = unzGetFilePos( uf, &pos );
+               if ( err != UNZ_OK ) {
+                       break;
+               }
 
                file = (VFS_PAKFILE*)safe_malloc( sizeof( VFS_PAKFILE ) );
                g_pakFiles = g_slist_append( g_pakFiles, file );
 
                vfsFixDOSName( filename_inzip );
-               g_strdown( filename_inzip );
+                //-1 null terminated string
+               filename_lower = g_ascii_strdown( filename_inzip, -1 );
 
-               file->name = strdup( filename_inzip );
+               file->name = strdup( filename_lower );
                file->size = file_info.uncompressed_size;
                file->zipfile = uf;
-               memcpy( &file->zipinfo, uf, sizeof( unz_s ) );
+               file->zippos = pos;
 
                if ( ( i + 1 ) < gi.number_entry ) {
                        err = unzGoToNextFile( uf );
@@ -147,6 +159,7 @@ static void vfsInitPakFile( const char *filename ){
                                break;
                        }
                }
+               g_free( filename_lower );
        }
 }
 
@@ -218,18 +231,18 @@ void vfsInitDirectory( const char *path ){
                                {
                                        char *ext = strrchr( dirlist, '.' );
 
-                                       if ( ext && !Q_stricmp( ext, ".pk3dir" ) ) {
+                                       if ( ext != NULL && ( !Q_stricmp( ext, ".pk3dir" ) || !Q_stricmp( ext, ".dpkdir" ) ) ) {
                                                if ( g_numDirs == VFS_MAXDIRS ) {
                                                        continue;
                                                }
                                                snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s/%s", path, name );
-                                               g_strDirs[g_numDirs][PATH_MAX] = '\0';
+                                               g_strDirs[g_numDirs][PATH_MAX-1] = '\0';
                                                vfsFixDOSName( g_strDirs[g_numDirs] );
                                                vfsAddSlash( g_strDirs[g_numDirs] );
                                                ++g_numDirs;
                                        }
 
-                                       if ( ( ext == NULL ) || ( Q_stricmp( ext, ".pk3" ) != 0 ) ) {
+                                       if ( ext == NULL || ( Q_stricmp( ext, ".pk3" ) != 0 && Q_stricmp( ext, ".dpk" ) != 0 ) ) {
                                                continue;
                                        }
                                }
@@ -244,6 +257,72 @@ void vfsInitDirectory( const char *path ){
        }
 }
 
+
+// lists all .shader files
+void vfsListShaderFiles( char* list, int *num ){
+       //char filename[PATH_MAX];
+       char *dirlist;
+       GDir *dir;
+       int i, k;
+       char path[NAME_MAX];
+/* search in dirs */
+       for ( i = 0; i < g_numDirs; i++ ){
+               strncpy( path, g_strDirs[ i ], NAME_MAX );
+               strcat( path, "scripts/" );
+
+               dir = g_dir_open( path, 0, NULL );
+
+               if ( dir != NULL ) {
+                       while ( 1 )
+                       {
+                               const char* name = g_dir_read_name( dir );
+                               if ( name == NULL ) {
+                                       break;
+                               }
+                               dirlist = g_strdup( name );
+                               char *ext = strrchr( dirlist, '.' );
+
+                               if ( ( ext == NULL ) || ( Q_stricmp( ext, ".shader" ) != 0 ) ) {
+                                       continue;
+                               }
+
+                               for ( k = 0; k < *num; k++ ){
+                                       if ( !Q_stricmp( list + k*65, dirlist ) ) goto shISdouplicate;
+                               }
+                               strcpy( list + (*num)*65, dirlist );
+                               (*num)++;
+shISdouplicate:
+                               g_free( dirlist );
+                       }
+                       g_dir_close( dir );
+               }
+       }
+       /* search in packs */
+       GSList *lst;
+
+       for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
+       {
+               VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
+
+               char *ext = strrchr( file->name, '.' );
+
+               if ( ( ext == NULL ) || ( Q_stricmp( ext, ".shader" ) != 0 ) ) {
+                       continue;
+               }
+               //name + ext this time
+               ext = strrchr( file->name, '/' );
+               ext++;
+
+               for ( k = 0; k < *num; k++ ){
+                       if ( !Q_stricmp( list + k*65, ext ) ) goto shISdouplicate2;
+               }
+               strcpy( list + (*num)*65, ext );
+               (*num)++;
+shISdouplicate2:
+               continue;
+       }
+}
+
 // frees all memory that we allocated
 void vfsShutdown(){
        while ( g_unzFiles )
@@ -265,17 +344,18 @@ void vfsShutdown(){
 int vfsGetFileCount( const char *filename ){
        int i, count = 0;
        char fixed[NAME_MAX], tmp[NAME_MAX];
+       char *lower;
        GSList *lst;
 
        strcpy( fixed, filename );
        vfsFixDOSName( fixed );
-       g_strdown( fixed );
+       lower = g_ascii_strdown( fixed, -1 );
 
        for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
        {
                VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
 
-               if ( strcmp( file->name, fixed ) == 0 ) {
+               if ( strcmp( file->name, lower ) == 0 ) {
                        count++;
                }
        }
@@ -283,12 +363,12 @@ int vfsGetFileCount( const char *filename ){
        for ( i = 0; i < g_numDirs; i++ )
        {
                strcpy( tmp, g_strDirs[i] );
-               strcat( tmp, fixed );
+               strcat( tmp, lower );
                if ( access( tmp, R_OK ) == 0 ) {
                        count++;
                }
        }
-
+       g_free( lower );
        return count;
 }
 
@@ -296,6 +376,7 @@ int vfsGetFileCount( const char *filename ){
 int vfsLoadFile( const char *filename, void **bufferptr, int index ){
        int i, count = 0;
        char tmp[NAME_MAX], fixed[NAME_MAX];
+       char *lower;
        GSList *lst;
 
        // filename is a full path
@@ -333,7 +414,7 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){
        *bufferptr = NULL;
        strcpy( fixed, filename );
        vfsFixDOSName( fixed );
-       g_strdown( fixed );
+       lower = g_ascii_strdown( fixed, -1 );
 
        for ( i = 0; i < g_numDirs; i++ )
        {
@@ -379,13 +460,15 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){
        {
                VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
 
-               if ( strcmp( file->name, fixed ) != 0 ) {
+               if ( strcmp( file->name, lower ) != 0 ) {
                        continue;
                }
 
                if ( count == index ) {
-                       memcpy( file->zipfile, &file->zipinfo, sizeof( unz_s ) );
 
+               if ( unzGoToFilePos( file->zipfile, &file->zippos ) != UNZ_OK ) {
+                       return -1;
+               }
                        if ( unzOpenCurrentFile( file->zipfile ) != UNZ_OK ) {
                                return -1;
                        }
@@ -400,12 +483,105 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){
                                return -1;
                        }
                        else{
+                               g_free( lower );
                                return file->size;
                        }
                }
 
                count++;
        }
-
+       g_free( lower );
        return -1;
 }
+
+
+qboolean vfsPackFile( const char *filename, const char *packname ){
+#ifndef BAD_MINIZ
+       int i;
+       char tmp[NAME_MAX], fixed[NAME_MAX];
+       GSList *lst;
+
+       byte *bufferptr = NULL;
+       strcpy( fixed, filename );
+       vfsFixDOSName( fixed );
+       g_strdown( fixed );
+
+       for ( i = 0; i < g_numDirs; i++ )
+       {
+               strcpy( tmp, g_strDirs[i] );
+               strcat( tmp, filename );
+               if ( access( tmp, R_OK ) == 0 ) {
+                       if ( access( packname, R_OK ) == 0 ) {
+                               mz_zip_archive zip;
+                               memset( &zip, 0, sizeof(zip) );
+                               mz_zip_reader_init_file( &zip, packname, 0 );
+                               mz_zip_writer_init_from_reader( &zip, packname );
+
+                               mz_bool success = MZ_TRUE;
+                               success &= mz_zip_writer_add_file( &zip, filename, tmp, 0, 0, 10 );
+                               if ( !success || !mz_zip_writer_finalize_archive( &zip ) ){
+                                       Error( "Failed creating zip archive \"%s\"!\n", packname );
+                               }
+                               mz_zip_reader_end( &zip);
+                               mz_zip_writer_end( &zip );
+                       }
+                       else{
+                               mz_zip_archive zip;
+                               memset( &zip, 0, sizeof(zip) );
+                               if( !mz_zip_writer_init_file( &zip, packname, 0 ) ){
+                                       Error( "Failed creating zip archive \"%s\"!\n", packname );
+                               }
+                               mz_bool success = MZ_TRUE;
+                               success &= mz_zip_writer_add_file( &zip, filename, tmp, 0, 0, 10 );
+                               if ( !success || !mz_zip_writer_finalize_archive( &zip ) ){
+                                       Error( "Failed creating zip archive \"%s\"!\n", packname );
+                               }
+                               mz_zip_writer_end( &zip );
+                       }
+
+                       return qtrue;
+               }
+       }
+
+       for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
+       {
+               VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
+
+               if ( strcmp( file->name, fixed ) != 0 ) {
+                       continue;
+               }
+
+               memcpy( file->zipfile, &file->zipinfo, sizeof( unz_s ) );
+
+               if ( unzOpenCurrentFile( file->zipfile ) != UNZ_OK ) {
+                       return qfalse;
+               }
+
+               bufferptr = safe_malloc( file->size + 1 );
+               // we need to end the buffer with a 0
+               ( (char*) ( bufferptr ) )[file->size] = 0;
+
+               mz_uint16 DOS_time = (mz_uint16)(((file->zipinfo.cur_file_info.tmu_date.tm_hour) << 11) + ((file->zipinfo.cur_file_info.tmu_date.tm_min) << 5) + ((file->zipinfo.cur_file_info.tmu_date.tm_sec) >> 1));
+               mz_uint16 DOS_date = (mz_uint16)(((file->zipinfo.cur_file_info.tmu_date.tm_year - 1980) << 9) + ((file->zipinfo.cur_file_info.tmu_date.tm_mon + 1) << 5) + file->zipinfo.cur_file_info.tmu_date.tm_mday);
+
+               i = unzReadCurrentFile( file->zipfile, bufferptr, file->size );
+               unzCloseCurrentFile( file->zipfile );
+               if ( i < 0 ) {
+                       return qfalse;
+               }
+               else{
+                       mz_bool success = MZ_TRUE;
+                       success &= mz_zip_add_mem_to_archive_file_in_place_with_time( packname, filename, bufferptr, i, 0, 0, 10, DOS_time, DOS_date );
+                               if ( !success ){
+                                       Error( "Failed creating zip archive \"%s\"!\n", packname );
+                               }
+                       free( bufferptr );
+                       return qtrue;
+               }
+       }
+
+       return qfalse;
+#else
+               Error( "Disabled because of miniz issue" );
+#endif
+}