mirror of
https://github.com/UberGames/GtkRadiant.git
synced 2024-11-21 19:40:56 +00:00
Quake Live PK3 support
This commit is contained in:
parent
d71d86a7a4
commit
ef1697925f
13 changed files with 6322 additions and 9 deletions
11
plugins/vfsqlpk3/.cvsignore
Normal file
11
plugins/vfsqlpk3/.cvsignore
Normal file
|
@ -0,0 +1,11 @@
|
|||
*.d
|
||||
*.o
|
||||
*.so
|
||||
Debug
|
||||
Release
|
||||
*.aps
|
||||
*.plg
|
||||
*.bak
|
||||
*.BAK
|
||||
*.opt
|
||||
*.ncb
|
170
plugins/vfsqlpk3/qlvfs.cpp
Normal file
170
plugins/vfsqlpk3/qlvfs.cpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
#include "stdio.h"
|
||||
#include "qlvfs.h"
|
||||
|
||||
/* Luigi Auriemma's quakelivedec.c */
|
||||
static unsigned char quakelive_xor[] =
|
||||
"\xcf\x8e\x8e\x4c\xd0\xd9\x30\xce\x07\x32\x27\x64\xed\x16\x06\x12"
|
||||
"\x20\x99\x55\x21\x7b\x10\xef\x57\x8b\xbf\x2e\x09\xee\x6b\xaa\x7c"
|
||||
"\xcc\x3c\x95\xee\xba\xd7\x4b\x88\x84\x88\xd2\x70\x4c\x09\x30\xf2"
|
||||
"\xaf\xb0\x99\x0d\x1f\x5f\xa7\xc5\xaf\x61\xc1\x18\xed\x16\xb0\x32"
|
||||
"\xf5\x07\x2f\x72\xb1\x23\x66\x1f\xf5\x18\xef\xb3\x9d\xf0\x4a\x02"
|
||||
"\x8f\x37\xff\xb0\xd7\xaf\xd3\x09\xb4\x4a\x2c\x63\xa3\x24\x1e\x52"
|
||||
"\xdf\x12\x9c\x8e\xff\x31\x2f\x0e\x48\xfa\x25\xc5\x43\xe4\x71\x69"
|
||||
"\xf4\x84\x91\x84\x0c\xc2\x3f\x7d\xb0\xe1\xe6\x03\x36\xbb\xed\x22"
|
||||
"\x89\xe9\x81\x6c\x4e\xfb\x41\x84\xba\xf1\x5b\x1e\xbf\x30\xbf\x77"
|
||||
"\x0e\x47\x1c\x84\xe9\xa0\x9e\x5b\x35\xa7\xee\x3c\x40\x0d\xb9\x70"
|
||||
"\x2a\x11\xf8\xc9\x41\x33\x89\x9c\x51\xf2\x40\xf0\xe5\xe8\xd7\x1e"
|
||||
"\x77\xde\x19\x46\x00\x57\xf0\x02\x5c\x1d\x64\xb9\x40\xc8\x1a\x99"
|
||||
"\x5f\xa7\x4d\x5a\x72\x3e\x80\xc3\xa1\x1a\x6e\x1e\xd0\x79\x06\x6b"
|
||||
"\xee\x50\x76\x81\x71\xa4\xb1\xdb\xab\x40\x1a\xa7\x8a\xee\x06\xb9"
|
||||
"\xf2\x22\x13\x30\x43\x19\xe1\xe3\x34\xce\x1e\x03\x1a\x04\xe7\xa4"
|
||||
"\x4a\xc7\x6a\x8e\x6f\xad\x7f\x3d\x89\x11\x97\xad\x95\x20\xe8\x35"
|
||||
"\xc7\xd1\x02\x00\x0a\xe5\x81\x25\x91\x2c\xa2\x87\x16\xc3\xcc\xc9"
|
||||
"\x1f\x6d\x56\x64\x82\xd6\x69\x97\x7d\xcb\x58\x40\xd0\x00\x16\xc3"
|
||||
"\xee\xb7\x19\xd6\x06\x6f\x39\x7b\x60\xba\x7b\xef\xfb\xc0\x79\x3c"
|
||||
"\xe7\x0b\x6f\x67\x36\xaf\xa9\x3a\x3f\xc2\x31\x72\x09\xa3\xfd\x4e"
|
||||
"\xc8\x52\x96\xda\x67\xf1\xb9\x79\xa9\xcc\xd3\x6f\xe7\xf6\xa0\x80"
|
||||
"\x0f\xcf\x7c\xb5\x9a\x89\xe6\xfa\xd3\xec\xc9\xf5\xcc\x53\x65\x73"
|
||||
"\x05\xd3\xd7\x83\x56\x84\x68\x94\xa3\x52\x1a\x0a\xcb\xe7\xcf\xed"
|
||||
"\x22\xfe\xd6\x3c\xf7\x84\x03\xbf\xeb\x77\x82\x5b\x8a\x35\x67\x2b"
|
||||
"\x97\x75\x5a\x81\xc9\x37\x6b\xe3\x77\x4f\x82\x5c\x75\x3f\xc3\xa1"
|
||||
"\x84\xe4\x2c\x43\x33\x8b\xec\xd6\x32\xf2\xfa\x3a\x65\x06\xb7\x51"
|
||||
"\x88\x85\x5b\xab\x0f\x36\x41\xc5\x2f\x6d\x34\x31\x70\x59\xb5\x2e"
|
||||
"\x44\x31\x62\xb9\x38\x39\xf7\xb6\x6e\xcf\xf2\x7f\x78\xdd\xf0\x8e"
|
||||
"\xc4\x23\x5a\x48\xd0\xa5\xa8\x90\x69\xa9\x53\xec\x45\xd6\x97\x9b"
|
||||
"\x92\x3e\x0a\x50\x90\x3f\xe9\x92\xdc\x85\xaa\xab\x57\xa7\x0e\xe8"
|
||||
"\xff\xcf\xfc\x4d\x9a\xc6\x36\xe3\x5a\x0d\x83\x12\xc5\x84\x85\x8a"
|
||||
"\x74\xcf\x42\x33\x8c\xeb\xd3\x49\x4d\x60\x15\xbe\xad\x73\x92\x37"
|
||||
"\x29\x3e\x63\x83\x1f\xd1\xc6\x9a\xbc\xb8\xc6\xac\x34\x34\x87\xd2"
|
||||
"\xe7\x0b\x77\xf9\x2f\x52\x37\xbb\x10\xa8\xe1\xde\x33\xf2\x52\x2e"
|
||||
"\xe5\x56\x7e\xff\x5c\xec\x82\x50\xe1\xb0\x4e\xa1\x23\x86\x08\x22"
|
||||
"\xa6\x56\x2b\x40\x99\xf4\x8e\x3d\xe2\x10\x05\xf1\xdd\x21\x69\x77"
|
||||
"\x07\x59\x90\x2f\xf1\xbb\xb8\x03\x5a\x21\xe1\xe5\x0c\xaa\x52\xda"
|
||||
"\xa1\x73\x31\x18\x12\xb2\x85\x52\x07\xf6\x8f\x23\xb0\xf7\x4a\x9a"
|
||||
"\x6f\x0a\x6c\x1f\xbe\x3f\x88\xad\xe9\x55\x4a\xb7\x44\xfb\xf8\x25"
|
||||
"\x6a\x2a\xf1\xd9\xfe\xb8\x62\xc5\xae\xed\x5c\x8b\x0f\x4b\x8a\xfe"
|
||||
"\x01\x68\x8b\xe1\x3f\x84\x3c\x6f\x10\xbf\xb5\x0f\x82\x41\x97\x39"
|
||||
"\x64\x18\x3d\xef\xa4\x3a\x5f\x33\x9d\x4b\x6e\xa3\x77\x97\x06\xfb"
|
||||
"\x1b\x8f\xf0\xed\xe3\x84\x1b\x73\x51\x72\x0b\x2d\xf1\x78\x59\xd9"
|
||||
"\x16\x50\x97\x1b\xe0\x5d\x27\xc3\xbb\x77\x2e\x15\xd2\xd2\x33\x68"
|
||||
"\xee\xd8\x0f\x28\xf5\x0c\x1b\x98\x1b\xda\x1d\x75\xc4\x2b\xb8\x45"
|
||||
"\x8b\xc0\x6e\x88\x88\xad\x61\xf8\x09\x1c\xb1\x46\xeb\xbb\xa2\xf5"
|
||||
"\xbc\x5c\x7b\x02\xdb\xcc\xad\x97\x1c\x5b\xa9\x97\x0e\x49\xea\x6d"
|
||||
"\x13\xba\x6f\x11\xcf\x2c\x2f\xc7\x9b\xb4\x80\x49\x18\x9e\x4c\x94"
|
||||
"\x5a\x55\x06\x4d\x42\x75\xb6\xa2\x61\xdb\xfa\x41\xca\x92\x70\xcc"
|
||||
"\x7e\x52\x66\x01\x13\x53\xef\xae\x40\xbd\xb7\xb6\xf2\xc7\xdd\x28"
|
||||
"\xb1\x11\xd4\x78\x79\xc2\x22\xbf\x29\xa0\x3a\x83\xc5\x76\x17\xe6"
|
||||
"\x94\x1e\xee\x63\xd2\x1e\x52\xfd\x24\x9f\x40\xa7\x0c\x0a\xe7\xeb"
|
||||
"\x9d\x12\x2a\xf3\xe3\x5f\x70\xe9\x31\x51\x6f\xe2\xac\xe7\xfc\xf2"
|
||||
"\x23\xe4\x6d\xe3\x85\xe3\xb8\x4c\x7f\xa1\x2c\x8c\xd7\xbb\x34\x70"
|
||||
"\x12\x7b\x6c\xe7\x8b\x4d\xb5\xdf\x52\xbb\x48\x5a\x21\x81\x16\x62"
|
||||
"\xdd\x8a\xbf\xa7\xe3\x12\x02\x52\x30\x6e\x7d\x76\x52\x1d\x43\x71"
|
||||
"\xf3\x6b\x1c\xa0\xd3\xd8\x59\xb0\x2d\xb9\x66\x9a\xb5\x00\xd9\xa6"
|
||||
"\xeb\x3f\x8a\x26\x90\x98\xb3\x69\x5f\x9f\x85\x53\x28\x3c\x9e\xce"
|
||||
"\x93\x7e\xab\x17\x76\x3d\x67\x0c\x4e\x21\x46\x3c\x94\x53\xba\xdc"
|
||||
"\xdf\x2a\x87\x09\x24\x76\x38\x39\x2e\xc0\x58\x1f\x99\x1a\xee\x9a"
|
||||
"\xaf\xc4\xc4\x3e\xfc\xeb\x4c\xfa\x5f\x43\x4f\x97\xe9\xac\xa9\x03"
|
||||
"\x29\x0e\x64\xeb\x24\x27\x87\xe3\xf2\xc3\xc6\x5d\xde\xe5\x3f\x46"
|
||||
"\xba\xd9\x75\x31\xda\x9c\xb2\xfd\x2b\xa5\x7e\x78\x3a\xaf\x22\xc4"
|
||||
"\x80\x90\x31\xf4\xd5\x9b\x04\x19\x09\xa2\x26\x91\xd2\xfe\x44\xb6";
|
||||
|
||||
FILE* fopen_ql (const char* filename, const char* mode) {
|
||||
FILE* file = NULL;
|
||||
|
||||
if ((filename!=NULL) && (mode != NULL))
|
||||
file = fopen(filename, mode);
|
||||
|
||||
if (file) {
|
||||
int i;
|
||||
char magic[4];
|
||||
int useXor = 1;
|
||||
//int foundPlace = 0;
|
||||
|
||||
fread(magic, 1, 4, file);
|
||||
if (magic[0] == 'P' && magic[1] == 'K' && magic[2] == '\x03') {
|
||||
useXor = 0;
|
||||
}
|
||||
fseek(file, 0, SEEK_SET);
|
||||
if (!useXor) {
|
||||
//printf("opened %p not xored\n", file);
|
||||
return file;
|
||||
}
|
||||
for (i = 0; i < MAX_FILE_HANDLES; i++) {
|
||||
//for (i = 0; i <= xor_max_pos; i++) {
|
||||
// assuming we don't open files more than once
|
||||
if (xored_open_files[i] == NULL) {
|
||||
xored_open_files[i] = file;
|
||||
//printf("opend %p xored\n", file);
|
||||
if (i > xor_max_pos) {
|
||||
xor_max_pos = i;
|
||||
}
|
||||
return file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("error couldn't find a spot for %p\n", file);
|
||||
return NULL; //exit
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
size_t fread_ql (void *ptr, size_t size, size_t nmeb, FILE *stream)
|
||||
{
|
||||
size_t r;
|
||||
long pos;
|
||||
long bytesRead;
|
||||
int i;
|
||||
unsigned char *cptr;
|
||||
int useXor = 0;
|
||||
|
||||
pos = ftell(stream);
|
||||
|
||||
cptr = (unsigned char *)ptr;
|
||||
|
||||
for (i = 0; i <= xor_max_pos; i++) {
|
||||
if (xored_open_files[i] == stream) {
|
||||
useXor = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
r = fread(ptr, size, nmeb, stream);
|
||||
|
||||
//printf("%p read\n", stream);
|
||||
if (!useXor) {
|
||||
return r;
|
||||
}
|
||||
|
||||
//printf("%p xor\n", stream);
|
||||
|
||||
bytesRead = ftell(stream) - pos;
|
||||
|
||||
for (i = 0; i < bytesRead; i++) {
|
||||
cptr[i] ^= quakelive_xor[(i + pos) % (sizeof(quakelive_xor) - 1)];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int fclose_ql (FILE* stream) {
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
//printf("close %p ", stream);
|
||||
//for (i = 0; i < MAX_FILE_HANDLES; i++) {
|
||||
for (i = 0; i <= xor_max_pos; i++) {
|
||||
if (xored_open_files[i] == stream) {
|
||||
xored_open_files[i] = NULL;
|
||||
if (i == xor_max_pos) {
|
||||
xor_max_pos--;
|
||||
}
|
||||
//printf("xor");
|
||||
break;
|
||||
}
|
||||
}
|
||||
//printf("\n");
|
||||
|
||||
ret = fclose((FILE *)stream);
|
||||
return ret;
|
||||
}
|
7
plugins/vfsqlpk3/qlvfs.h
Normal file
7
plugins/vfsqlpk3/qlvfs.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#define MAX_FILE_HANDLES 8192 //64 // qcommon.h
|
||||
static FILE *xored_open_files[MAX_FILE_HANDLES];
|
||||
static int xor_max_pos = 0;
|
||||
|
||||
FILE* fopen_ql (const char* filename, const char* mode);
|
||||
size_t fread_ql (void *ptr, size_t size, size_t nmeb, FILE *stream);
|
||||
int fclose_ql (FILE* stream);
|
301
plugins/vfsqlpk3/unzip-vfsqlpk3.h
Normal file
301
plugins/vfsqlpk3/unzip-vfsqlpk3.h
Normal file
|
@ -0,0 +1,301 @@
|
|||
#if defined( STRICTUNZIP ) || defined( STRICTZIPUNZIP )
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef void* unzFile;
|
||||
#endif
|
||||
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
unsigned int tm_sec; /* seconds after the minute - [0,59] */
|
||||
unsigned int tm_min; /* minutes after the hour - [0,59] */
|
||||
unsigned int tm_hour; /* hours since midnight - [0,23] */
|
||||
unsigned int tm_mday; /* day of the month - [1,31] */
|
||||
unsigned int tm_mon; /* months since January - [0,11] */
|
||||
unsigned int tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
unsigned long number_entry; /* total number of entries in the central dir on this disk */
|
||||
unsigned long size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info;
|
||||
|
||||
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
typedef struct unz_file_info_s
|
||||
{
|
||||
unsigned long version; /* version made by 2 unsigned chars */
|
||||
unsigned long version_needed; /* version needed to extract 2 unsigned chars */
|
||||
unsigned long flag; /* general purpose bit flag 2 unsigned chars */
|
||||
unsigned long compression_method; /* compression method 2 unsigned chars */
|
||||
unsigned long dosDate; /* last mod file date in Dos fmt 4 unsigned chars */
|
||||
unsigned long crc; /* crc-32 4 unsigned chars */
|
||||
unsigned long compressed_size; /* compressed size 4 unsigned chars */
|
||||
unsigned long uncompressed_size; /* uncompressed size 4 unsigned chars */
|
||||
unsigned long size_filename; /* filename length 2 unsigned chars */
|
||||
unsigned long size_file_extra; /* extra field length 2 unsigned chars */
|
||||
unsigned long size_file_comment; /* file comment length 2 unsigned chars */
|
||||
|
||||
unsigned long disk_num_start; /* disk number start 2 unsigned chars */
|
||||
unsigned long internal_fa; /* internal file attributes 2 unsigned chars */
|
||||
unsigned long external_fa; /* external file attributes 4 unsigned chars */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
/* unz_file_info_interntal contain internal info about a file in zipfile*/
|
||||
typedef struct unz_file_info_internal_s
|
||||
{
|
||||
unsigned long offset_curfile; /* relative offset of static header 4 unsigned chars */
|
||||
} unz_file_info_internal;
|
||||
|
||||
typedef void* ( *alloc_func )( void* opaque, unsigned int items, unsigned int size );
|
||||
typedef void ( *free_func )( void* opaque, void* address );
|
||||
|
||||
struct internal_state;
|
||||
|
||||
typedef struct z_stream_s {
|
||||
unsigned char *next_in; /* next input unsigned char */
|
||||
unsigned int avail_in; /* number of unsigned chars available at next_in */
|
||||
unsigned long total_in; /* total nb of input unsigned chars read so */
|
||||
|
||||
unsigned char *next_out; /* next output unsigned char should be put there */
|
||||
unsigned int avail_out; /* remaining free space at next_out */
|
||||
unsigned long total_out; /* total nb of unsigned chars output so */
|
||||
|
||||
char *msg; /* last error message, NULL if no error */
|
||||
struct internal_state *state; /* not visible by applications */
|
||||
|
||||
alloc_func zalloc; /* used to allocate the internal state */
|
||||
free_func zfree; /* used to free the internal state */
|
||||
unsigned char* opaque; /* private data object passed to zalloc and zfree */
|
||||
|
||||
int data_type; /* best guess about the data type: ascii or binary */
|
||||
unsigned long adler; /* adler32 value of the uncompressed data */
|
||||
unsigned long reserved; /* reserved for future use */
|
||||
} z_stream;
|
||||
|
||||
typedef z_stream *z_streamp;
|
||||
|
||||
|
||||
/* file_in_zip_read_info_s contain internal information about a file in zipfile,
|
||||
when reading and decompress it */
|
||||
typedef struct
|
||||
{
|
||||
char *read_buffer; /* internal buffer for compressed data */
|
||||
z_stream stream; /* zLib stream structure for inflate */
|
||||
|
||||
unsigned long pos_in_zipfile; /* position in unsigned char on the zipfile, for fseek*/
|
||||
unsigned long stream_initialised; /* flag set if stream structure is initialised*/
|
||||
|
||||
unsigned long offset_local_extrafield; /* offset of the static extra field */
|
||||
unsigned int size_local_extrafield; /* size of the static extra field */
|
||||
unsigned long pos_local_extrafield; /* position in the static extra field in read*/
|
||||
|
||||
unsigned long crc32; /* crc32 of all data uncompressed */
|
||||
unsigned long crc32_wait; /* crc32 we must obtain after decompress all */
|
||||
unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
|
||||
unsigned long rest_read_uncompressed; /*number of unsigned char to be obtained after decomp*/
|
||||
FILE* file; /* io structore of the zipfile */
|
||||
unsigned long compression_method; /* compression method (0==store) */
|
||||
unsigned long byte_before_the_zipfile; /* unsigned char before the zipfile, (>0 for sfx)*/
|
||||
} file_in_zip_read_info_s;
|
||||
|
||||
|
||||
/* unz_s contain internal information about the zipfile
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
FILE* file; /* io structore of the zipfile */
|
||||
unz_global_info gi; /* public global information */
|
||||
unsigned long byte_before_the_zipfile; /* unsigned char before the zipfile, (>0 for sfx)*/
|
||||
unsigned long num_file; /* number of the current file in the zipfile*/
|
||||
unsigned long pos_in_central_dir; /* pos of the current file in the central dir*/
|
||||
unsigned long current_file_ok; /* flag about the usability of the current file*/
|
||||
unsigned long central_pos; /* position of the beginning of the central dir*/
|
||||
|
||||
unsigned long size_central_dir; /* size of the central directory */
|
||||
unsigned long offset_central_dir; /* offset of start of central directory with
|
||||
respect to the starting disk number */
|
||||
|
||||
unz_file_info cur_file_info; /* public info about the current file in zip*/
|
||||
unz_file_info_internal cur_file_info_internal; /* private info about it*/
|
||||
file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
|
||||
file if we are decompressing it */
|
||||
} unz_s;
|
||||
|
||||
#define UNZ_OK ( 0 )
|
||||
#define UNZ_END_OF_LIST_OF_FILE ( -100 )
|
||||
#define UNZ_ERRNO ( Z_ERRNO )
|
||||
#define UNZ_EOF ( 0 )
|
||||
#define UNZ_PARAMERROR ( -102 )
|
||||
#define UNZ_BADZIPFILE ( -103 )
|
||||
#define UNZ_INTERNALERROR ( -104 )
|
||||
#define UNZ_CRCERROR ( -105 )
|
||||
|
||||
#define UNZ_CASESENSITIVE 1
|
||||
#define UNZ_NOTCASESENSITIVE 2
|
||||
#define UNZ_OSDEFAULTCASE 0
|
||||
|
||||
extern int unzStringFileNameCompare( const char* fileName1, const char* fileName2, int iCaseSensitivity );
|
||||
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
or strcasecmp)
|
||||
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
|
||||
(like 1 on Unix, 2 on Windows)
|
||||
*/
|
||||
|
||||
extern unzFile unzOpen( const char *path );
|
||||
extern unzFile unzReOpen( const char* path, unzFile file );
|
||||
|
||||
/*
|
||||
Open a Zip file. path contain the full pathname (by example,
|
||||
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
|
||||
"zlib/zlib111.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
return value is NULL.
|
||||
Else, the return value is a unzFile Handle, usable with other function
|
||||
of this unzip package.
|
||||
*/
|
||||
|
||||
extern int unzClose( unzFile file );
|
||||
|
||||
/*
|
||||
Close a ZipFile opened with unzipOpen.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int unzGetGlobalInfo( unzFile file, unz_global_info *pglobal_info );
|
||||
|
||||
/*
|
||||
Write info about the ZipFile in the *pglobal_info structure.
|
||||
No preparation of the structure is needed
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
|
||||
extern int unzGetGlobalComment( unzFile file, char *szComment, unsigned long uSizeBuf );
|
||||
|
||||
/*
|
||||
Get the global comment string of the ZipFile, in the szComment buffer.
|
||||
uSizeBuf is the size of the szComment buffer.
|
||||
return the number of unsigned char copied or an error code <0
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Unzip package allow you browse the directory of the zipfile */
|
||||
|
||||
extern int unzGoToFirstFile( unzFile file );
|
||||
|
||||
/*
|
||||
Set the current file of the zipfile to the first file.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int unzGoToNextFile( unzFile file );
|
||||
|
||||
/*
|
||||
Set the current file of the zipfile to the next file.
|
||||
return UNZ_OK if there is no problem
|
||||
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
|
||||
*/
|
||||
|
||||
extern int unzLocateFile( unzFile file, const char *szFileName, int iCaseSensitivity );
|
||||
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
return value :
|
||||
UNZ_OK if the file is found. It becomes the current file.
|
||||
UNZ_END_OF_LIST_OF_FILE if the file is not found
|
||||
*/
|
||||
|
||||
|
||||
extern int unzGetCurrentFileInfo( unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize );
|
||||
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize is the size of the buffer).
|
||||
This is the Central-header version of the extra field
|
||||
if szComment!=NULL, the comment string of the file will be copied in szComment
|
||||
(commentBufferSize is the size of the buffer)
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* for reading the content of the current zipfile, you can open it, read data
|
||||
from it, and close it (you can close it before reading all the file)
|
||||
*/
|
||||
|
||||
extern int unzOpenCurrentFile( unzFile file );
|
||||
|
||||
/*
|
||||
Open for reading data the current file in the zipfile.
|
||||
If there is no error, the return value is UNZ_OK.
|
||||
*/
|
||||
|
||||
extern int unzCloseCurrentFile( unzFile file );
|
||||
|
||||
/*
|
||||
Close the file in zip opened with unzOpenCurrentFile
|
||||
Return UNZ_CRCERROR if all the file was read but the CRC is not good
|
||||
*/
|
||||
|
||||
|
||||
extern int unzReadCurrentFile( unzFile file, void* buf, unsigned len );
|
||||
|
||||
/*
|
||||
Read unsigned chars from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of unsigned char copied if somes unsigned chars are copied
|
||||
return 0 if the end of file was reached
|
||||
return <0 with error code if there is an error
|
||||
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
|
||||
*/
|
||||
|
||||
extern long unztell( unzFile file );
|
||||
|
||||
/*
|
||||
Give the current position in uncompressed data
|
||||
*/
|
||||
|
||||
extern int unzeof( unzFile file );
|
||||
|
||||
/*
|
||||
return 1 if the end of file was reached, 0 elsewhere
|
||||
*/
|
||||
|
||||
extern int unzGetLocalExtrafield( unzFile file, void* buf, unsigned len );
|
||||
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
This is the local-header version of the extra field (sometimes, there is
|
||||
more info in the local-header version than in the central-header)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
buf.
|
||||
the return value is the number of unsigned chars copied in buf, or (if <0)
|
||||
the error code
|
||||
*/
|
||||
|
||||
|
4538
plugins/vfsqlpk3/unzip.cpp
Normal file
4538
plugins/vfsqlpk3/unzip.cpp
Normal file
File diff suppressed because it is too large
Load diff
841
plugins/vfsqlpk3/vfs.cpp
Normal file
841
plugins/vfsqlpk3/vfs.cpp
Normal file
|
@ -0,0 +1,841 @@
|
|||
/*
|
||||
Copyright (c) 2001, Loki software, inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
Neither the name of Loki software nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//
|
||||
// Rules:
|
||||
//
|
||||
// - Directories should be searched in the following order: ~/.q3a/baseq3,
|
||||
// install dir (/usr/local/games/quake3/baseq3) and cd_path (/mnt/cdrom/baseq3).
|
||||
//
|
||||
// - Pak files are searched first inside the directories.
|
||||
// - Case insensitive.
|
||||
// - Unix-style slashes (/) (windows is backwards .. everyone knows that)
|
||||
//
|
||||
// Leonardo Zide (leo@lokigames.com)
|
||||
//
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined ( __linux__ ) || defined ( __APPLE__ )
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <wtypes.h>
|
||||
#include <io.h>
|
||||
#define R_OK 04
|
||||
#define S_ISDIR( mode ) ( mode & _S_IFDIR )
|
||||
#endif
|
||||
|
||||
// TTimo: String functions
|
||||
// see http://www.qeradiant.com/faq/index.cgi?file=175
|
||||
#include "str.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "vfsqlpk3.h"
|
||||
#include "vfs.h"
|
||||
#include "unzip-vfsqlpk3.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* name;
|
||||
unz_s zipinfo;
|
||||
unzFile zipfile;
|
||||
guint32 size;
|
||||
} VFS_PAKFILE;
|
||||
|
||||
// =============================================================================
|
||||
// Global variables
|
||||
|
||||
static GSList* g_unzFiles;
|
||||
static GSList* g_pakFiles;
|
||||
static char g_strDirs[VFS_MAXDIRS][PATH_MAX];
|
||||
static int g_numDirs;
|
||||
static bool g_bUsePak = true;
|
||||
|
||||
// =============================================================================
|
||||
// Static functions
|
||||
|
||||
static void vfsAddSlash( char *str ){
|
||||
int n = strlen( str );
|
||||
if ( n > 0 ) {
|
||||
if ( str[n - 1] != '\\' && str[n - 1] != '/' ) {
|
||||
strcat( str, "/" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void vfsFixDOSName( char *src ){
|
||||
if ( src == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ( *src )
|
||||
{
|
||||
if ( *src == '\\' ) {
|
||||
*src = '/';
|
||||
}
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
static void vfsInitPakFile( const char *filename ){
|
||||
unz_global_info gi;
|
||||
unzFile uf;
|
||||
guint32 i;
|
||||
int err;
|
||||
|
||||
uf = unzOpen( filename );
|
||||
if ( uf == NULL ) {
|
||||
g_FuncTable.m_pfnSysFPrintf( SYS_WRN, " failed to init pak file %s\n", filename );
|
||||
return;
|
||||
}
|
||||
g_FuncTable.m_pfnSysPrintf( " pak file: %s\n", filename );
|
||||
|
||||
g_unzFiles = g_slist_append( g_unzFiles, uf );
|
||||
|
||||
err = unzGetGlobalInfo( uf,&gi );
|
||||
if ( err != UNZ_OK ) {
|
||||
return;
|
||||
}
|
||||
unzGoToFirstFile( uf );
|
||||
|
||||
for ( i = 0; i < gi.number_entry; i++ )
|
||||
{
|
||||
char filename_inzip[NAME_MAX];
|
||||
unz_file_info file_info;
|
||||
VFS_PAKFILE* file;
|
||||
|
||||
err = unzGetCurrentFileInfo( uf, &file_info, filename_inzip, sizeof( filename_inzip ), NULL, 0, NULL, 0 );
|
||||
if ( err != UNZ_OK ) {
|
||||
break;
|
||||
}
|
||||
|
||||
file = (VFS_PAKFILE*)g_malloc( sizeof( VFS_PAKFILE ) );
|
||||
g_pakFiles = g_slist_append( g_pakFiles, file );
|
||||
|
||||
vfsFixDOSName( filename_inzip );
|
||||
g_strdown( filename_inzip );
|
||||
|
||||
file->name = g_strdup( filename_inzip );
|
||||
file->size = file_info.uncompressed_size;
|
||||
file->zipfile = uf;
|
||||
memcpy( &file->zipinfo, uf, sizeof( unz_s ) );
|
||||
|
||||
if ( ( i + 1 ) < gi.number_entry ) {
|
||||
err = unzGoToNextFile( uf );
|
||||
if ( err != UNZ_OK ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GSList* vfsGetListInternal( const char *refdir, const char *ext, bool directories ){
|
||||
GSList *lst, *lst_aux, *files = NULL;
|
||||
char dirname[NAME_MAX], extension[NAME_MAX], filename[NAME_MAX];
|
||||
char basedir[NAME_MAX];
|
||||
int dirlen;
|
||||
char *ptr;
|
||||
char *dirlist;
|
||||
struct stat st;
|
||||
GDir *diskdir;
|
||||
int i;
|
||||
|
||||
if ( refdir != NULL ) {
|
||||
strcpy( dirname, refdir );
|
||||
g_strdown( dirname );
|
||||
vfsFixDOSName( dirname );
|
||||
vfsAddSlash( dirname );
|
||||
}
|
||||
else{
|
||||
dirname[0] = '\0';
|
||||
}
|
||||
dirlen = strlen( dirname );
|
||||
|
||||
if ( ext != NULL ) {
|
||||
strcpy( extension, ext );
|
||||
}
|
||||
else{
|
||||
extension[0] = '\0';
|
||||
}
|
||||
g_strdown( extension );
|
||||
|
||||
for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
|
||||
{
|
||||
VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
|
||||
gboolean found = FALSE;
|
||||
ptr = file->name;
|
||||
|
||||
// check that the file name begins with dirname
|
||||
for ( i = 0; ( *ptr && i < dirlen ); i++, ptr++ )
|
||||
if ( *ptr != dirname[i] ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( i != dirlen ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( directories ) {
|
||||
char *sep = strchr( ptr, '/' );
|
||||
if ( sep == NULL ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
i = sep - ptr;
|
||||
|
||||
// check for duplicates
|
||||
for ( lst_aux = files; lst_aux; lst_aux = g_slist_next( lst_aux ) )
|
||||
if ( strncmp( (char*)lst_aux->data, ptr, i ) == 0 ) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !found ) {
|
||||
char *name = g_strndup( ptr, i + 1 );
|
||||
name[i] = '\0';
|
||||
files = g_slist_append( files, name );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check extension
|
||||
char *ptr_ext = strrchr( ptr, '.' );
|
||||
if ( ( ext != NULL ) && ( ( ptr_ext == NULL ) || ( strcmp( ptr_ext + 1, extension ) != 0 ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for duplicates
|
||||
for ( lst_aux = files; lst_aux; lst_aux = g_slist_next( lst_aux ) )
|
||||
if ( strcmp( (char*)lst_aux->data, ptr ) == 0 ) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !found ) {
|
||||
files = g_slist_append( files, g_strdup( ptr ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < g_numDirs; i++ )
|
||||
{
|
||||
strcpy( basedir, g_strDirs[i] );
|
||||
strcat( basedir, dirname );
|
||||
|
||||
diskdir = g_dir_open( basedir, 0, NULL );
|
||||
|
||||
if ( diskdir != NULL ) {
|
||||
while ( 1 )
|
||||
{
|
||||
const char* name = g_dir_read_name( diskdir );
|
||||
if ( name == NULL ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( directories && ( name[0] == '.' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf( filename, "%s%s", basedir, name );
|
||||
stat( filename, &st );
|
||||
|
||||
if ( ( S_ISDIR( st.st_mode ) != 0 ) != directories ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gboolean found = FALSE;
|
||||
|
||||
dirlist = g_strdup( name );
|
||||
|
||||
g_strdown( dirlist );
|
||||
|
||||
char *ptr_ext = strrchr( dirlist, '.' );
|
||||
if ( ext == NULL
|
||||
|| ( ext != NULL && ptr_ext != NULL && ptr_ext[0] != '\0' && strcmp( ptr_ext + 1, extension ) == 0 ) ) {
|
||||
|
||||
// check for duplicates
|
||||
for ( lst_aux = files; lst_aux; lst_aux = g_slist_next( lst_aux ) )
|
||||
if ( strcmp( (char*)lst_aux->data, dirlist ) == 0 ) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !found ) {
|
||||
files = g_slist_append( files, g_strdup( dirlist ) );
|
||||
}
|
||||
}
|
||||
|
||||
g_free( dirlist );
|
||||
}
|
||||
g_dir_close( diskdir );
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
/*!
|
||||
This behaves identically to -stricmp(a,b), except that ASCII chars
|
||||
[\]^`_ come AFTER alphabet chars instead of before. This is because
|
||||
it effectively converts all alphabet chars to uppercase before comparison,
|
||||
while stricmp converts them to lowercase.
|
||||
*/
|
||||
//!\todo Analyse the code in rtcw/q3 to see how it behaves.
|
||||
static int vfsPakSort( const void *a, const void *b ){
|
||||
char *s1, *s2;
|
||||
int c1, c2;
|
||||
|
||||
s1 = (char*)a;
|
||||
s2 = (char*)b;
|
||||
|
||||
do {
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if ( c1 >= 'a' && c1 <= 'z' ) {
|
||||
c1 -= ( 'a' - 'A' );
|
||||
}
|
||||
if ( c2 >= 'a' && c2 <= 'z' ) {
|
||||
c2 -= ( 'a' - 'A' );
|
||||
}
|
||||
|
||||
if ( c1 == '\\' || c1 == ':' ) {
|
||||
c1 = '/';
|
||||
}
|
||||
if ( c2 == '\\' || c2 == ':' ) {
|
||||
c2 = '/';
|
||||
}
|
||||
|
||||
// Arnout: note - sort pakfiles in reverse order. This ensures that
|
||||
// later pakfiles override earlier ones. This because the vfs module
|
||||
// returns a filehandle to the first file it can find (while it should
|
||||
// return the filehandle to the file in the most overriding pakfile, the
|
||||
// last one in the list that is).
|
||||
if ( c1 < c2 ) {
|
||||
//return -1; // strings not equal
|
||||
return 1; // strings not equal
|
||||
}
|
||||
if ( c1 > c2 ) {
|
||||
//return 1;
|
||||
return -1;
|
||||
}
|
||||
} while ( c1 );
|
||||
|
||||
return 0; // strings are equal
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Global functions
|
||||
|
||||
// reads all pak files from a dir
|
||||
/*!
|
||||
The gamemode hacks in here will do undefined things with files called zz_*.
|
||||
This is simple to fix by cleaning up the hacks, but may be better left alone
|
||||
if the engine code does the same thing.
|
||||
*/
|
||||
void vfsInitDirectory( const char *path ){
|
||||
char filename[PATH_MAX];
|
||||
GDir *dir;
|
||||
GSList *dirlist = NULL;
|
||||
int iGameMode; // 0: no filtering 1: SP 2: MP
|
||||
|
||||
if ( g_numDirs == ( VFS_MAXDIRS - 1 ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we are in "sp" or "mp" mapping mode
|
||||
const char* gamemode = g_FuncTable.m_pfnReadProjectKey( "gamemode" );
|
||||
|
||||
if ( gamemode ) {
|
||||
if ( strcmp( gamemode, "sp" ) == 0 ) {
|
||||
iGameMode = 1;
|
||||
}
|
||||
else if ( strcmp( gamemode, "mp" ) == 0 ) {
|
||||
iGameMode = 2;
|
||||
}
|
||||
else{
|
||||
iGameMode = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
iGameMode = 0;
|
||||
}
|
||||
|
||||
strcpy( g_strDirs[g_numDirs], path );
|
||||
vfsFixDOSName( g_strDirs[g_numDirs] );
|
||||
vfsAddSlash( g_strDirs[g_numDirs] );
|
||||
g_numDirs++;
|
||||
|
||||
if ( g_bUsePak ) {
|
||||
dir = g_dir_open( path, 0, NULL );
|
||||
|
||||
if ( dir != NULL ) {
|
||||
g_FuncTable.m_pfnSysPrintf( "vfs directory: %s\n", path );
|
||||
|
||||
for (;; )
|
||||
{
|
||||
const char* name = g_dir_read_name( dir );
|
||||
if ( name == NULL ) {
|
||||
break;
|
||||
}
|
||||
|
||||
char *ext = (char*)strrchr( name, '.' );
|
||||
if ( ( ext == NULL ) || ( strcasecmp( ext, ".pk3" ) != 0 ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char* direntry = g_strdup( name );
|
||||
|
||||
// using the same kludge as in engine to ensure consistency
|
||||
switch ( iGameMode )
|
||||
{
|
||||
case 1: // SP
|
||||
if ( strncmp( direntry,"sp_",3 ) == 0 ) {
|
||||
memcpy( direntry,"zz",2 );
|
||||
}
|
||||
break;
|
||||
case 2: // MP
|
||||
if ( strncmp( direntry,"mp_",3 ) == 0 ) {
|
||||
memcpy( direntry,"zz",2 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dirlist = g_slist_append( dirlist, direntry );
|
||||
}
|
||||
|
||||
g_dir_close( dir );
|
||||
|
||||
// sort them
|
||||
dirlist = g_slist_sort( dirlist, vfsPakSort );
|
||||
|
||||
// add the entries to the vfs and free the list
|
||||
while ( dirlist )
|
||||
{
|
||||
GSList *cur = dirlist;
|
||||
char* name = (char*)cur->data;
|
||||
|
||||
switch ( iGameMode )
|
||||
{
|
||||
case 1: // SP
|
||||
if ( strncmp( name,"mp_",3 ) == 0 ) {
|
||||
g_free( name );
|
||||
dirlist = g_slist_remove( cur, name );
|
||||
continue;
|
||||
}
|
||||
else if ( strncmp( name,"zz_",3 ) == 0 ) {
|
||||
memcpy( name,"sp",2 );
|
||||
}
|
||||
break;
|
||||
case 2: // MP
|
||||
if ( strncmp( name,"sp_",3 ) == 0 ) {
|
||||
g_free( name );
|
||||
dirlist = g_slist_remove( cur, name );
|
||||
continue;
|
||||
}
|
||||
else if ( strncmp( name,"zz_",3 ) == 0 ) {
|
||||
memcpy( name,"mp",2 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf( filename, "%s/%s", path, name );
|
||||
vfsInitPakFile( filename );
|
||||
|
||||
g_free( name );
|
||||
dirlist = g_slist_remove( cur, name );
|
||||
}
|
||||
}
|
||||
else{
|
||||
g_FuncTable.m_pfnSysFPrintf( SYS_WRN, "vfs directory not found: %s\n", path );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// frees all memory that we allocated
|
||||
// FIXME TTimo this should be improved so that we can shutdown and restart the VFS without exiting Radiant?
|
||||
// (for instance when modifying the project settings)
|
||||
void vfsShutdown(){
|
||||
while ( g_unzFiles )
|
||||
{
|
||||
unzClose( (unzFile)g_unzFiles->data );
|
||||
g_unzFiles = g_slist_remove( g_unzFiles, g_unzFiles->data );
|
||||
}
|
||||
|
||||
// avoid dangling pointer operation (makes BC hangry)
|
||||
GSList *cur = g_pakFiles;
|
||||
GSList *next = cur;
|
||||
while ( next )
|
||||
{
|
||||
cur = next;
|
||||
VFS_PAKFILE* file = (VFS_PAKFILE*)cur->data;
|
||||
g_free( file->name );
|
||||
g_free( file );
|
||||
next = g_slist_remove( cur, file );
|
||||
}
|
||||
g_pakFiles = NULL;
|
||||
}
|
||||
|
||||
void vfsFreeFile( void *p ){
|
||||
g_free( p );
|
||||
}
|
||||
|
||||
GSList* vfsGetFileList( const char *dir, const char *ext ){
|
||||
return vfsGetListInternal( dir, ext, false );
|
||||
}
|
||||
|
||||
GSList* vfsGetDirList( const char *dir ){
|
||||
return vfsGetListInternal( dir, NULL, true );
|
||||
}
|
||||
|
||||
void vfsClearFileDirList( GSList **lst ){
|
||||
while ( *lst )
|
||||
{
|
||||
g_free( ( *lst )->data );
|
||||
*lst = g_slist_remove( *lst, ( *lst )->data );
|
||||
}
|
||||
}
|
||||
|
||||
int vfsGetFileCount( const char *filename, int flag ){
|
||||
int i, count = 0;
|
||||
char fixed[NAME_MAX], tmp[NAME_MAX];
|
||||
GSList *lst;
|
||||
|
||||
strcpy( fixed, filename );
|
||||
vfsFixDOSName( fixed );
|
||||
g_strdown( fixed );
|
||||
|
||||
if ( !flag || ( flag & VFS_SEARCH_PAK ) ) {
|
||||
for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
|
||||
{
|
||||
VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
|
||||
|
||||
if ( strcmp( file->name, fixed ) == 0 ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !flag || ( flag & VFS_SEARCH_DIR ) ) {
|
||||
for ( i = 0; i < g_numDirs; i++ )
|
||||
{
|
||||
strcpy( tmp, g_strDirs[i] );
|
||||
strcat( tmp, fixed );
|
||||
if ( access( tmp, R_OK ) == 0 ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// open a full path file
|
||||
int vfsLoadFullPathFile( const char *filename, void **bufferptr ){
|
||||
FILE *f;
|
||||
long len;
|
||||
|
||||
f = fopen( filename, "rb" );
|
||||
if ( f == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek( f, 0, SEEK_END );
|
||||
len = ftell( f );
|
||||
rewind( f );
|
||||
|
||||
*bufferptr = g_malloc( len + 1 );
|
||||
if ( *bufferptr == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread( *bufferptr, 1, len, f );
|
||||
fclose( f );
|
||||
|
||||
// we need to end the buffer with a 0
|
||||
( (char*) ( *bufferptr ) )[len] = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// NOTE: when loading a file, you have to allocate one extra byte and set it to \0
|
||||
int vfsLoadFile( const char *filename, void **bufferptr, int index ){
|
||||
int i, count = 0;
|
||||
char tmp[NAME_MAX], fixed[NAME_MAX];
|
||||
GSList *lst;
|
||||
|
||||
*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 ( count == index ) {
|
||||
return vfsLoadFullPathFile( tmp,bufferptr );
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ( count == index ) {
|
||||
memcpy( file->zipfile, &file->zipinfo, sizeof( unz_s ) );
|
||||
|
||||
if ( unzOpenCurrentFile( file->zipfile ) != UNZ_OK ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*bufferptr = g_malloc( file->size + 1 );
|
||||
// we need to end the buffer with a 0
|
||||
( (char*) ( *bufferptr ) )[file->size] = 0;
|
||||
|
||||
i = unzReadCurrentFile( file->zipfile, *bufferptr, file->size );
|
||||
unzCloseCurrentFile( file->zipfile );
|
||||
if ( i > 0 ) {
|
||||
return file->size;
|
||||
}
|
||||
else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//#ifdef _DEBUG
|
||||
#if 1
|
||||
#define DBG_RLTPATH
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\param shorten will try to match against the short version
|
||||
recent switch back to short path names in project settings has broken some stuff
|
||||
with shorten == true, we will convert in to short version before looking for root
|
||||
FIXME WAAA .. the stuff below is much more simple on linux .. add appropriate #ifdef
|
||||
*/
|
||||
char* vfsExtractRelativePath_short( const char *in, bool shorten ){
|
||||
int i;
|
||||
char l_in[PATH_MAX];
|
||||
char check[PATH_MAX];
|
||||
static char out[PATH_MAX];
|
||||
out[0] = 0;
|
||||
|
||||
#ifdef DBG_RLTPATH
|
||||
Sys_Printf( "vfsExtractRelativePath: %s\n", in );
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
if ( shorten ) {
|
||||
// make it short
|
||||
if ( GetShortPathName( in, l_in, PATH_MAX ) == 0 ) {
|
||||
#ifdef DBG_RLTPATH
|
||||
Sys_Printf( "GetShortPathName failed\n" );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( l_in,in );
|
||||
}
|
||||
vfsCleanFileName( l_in );
|
||||
#else
|
||||
strcpy( l_in, in );
|
||||
vfsCleanFileName( l_in );
|
||||
#endif // ifdef WIN32
|
||||
|
||||
|
||||
#ifdef DBG_RLTPATH
|
||||
Sys_Printf( "cleaned path: %s\n", l_in );
|
||||
#endif
|
||||
|
||||
for ( i = 0; i < g_numDirs; i++ )
|
||||
{
|
||||
strcpy( check,g_strDirs[i] );
|
||||
vfsCleanFileName( check );
|
||||
#ifdef DBG_RLTPATH
|
||||
Sys_Printf( "Matching against %s\n", check );
|
||||
#endif
|
||||
|
||||
// try to find a match
|
||||
if ( strstr( l_in, check ) ) {
|
||||
strcpy( out,l_in + strlen( check ) + 1 );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if ( out[0] != 0 ) {
|
||||
#ifdef DBG_RLTPATH
|
||||
Sys_Printf( "vfsExtractRelativePath: success\n" );
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
#ifdef DBG_RLTPATH
|
||||
Sys_Printf( "vfsExtractRelativePath: failed\n" );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// FIXME TTimo: this and the above should be merged at some point
|
||||
char* vfsExtractRelativePath( const char *in ){
|
||||
static char out[PATH_MAX];
|
||||
unsigned int i, count;
|
||||
char *chunk, *backup = NULL; // those point to out stuff
|
||||
char *ret = vfsExtractRelativePath_short( in, false );
|
||||
if ( !ret ) {
|
||||
#ifdef DBG_RLTPATH
|
||||
Sys_Printf( "trying with a short version\n" );
|
||||
#endif
|
||||
ret = vfsExtractRelativePath_short( in, true );
|
||||
if ( ret ) {
|
||||
// ok, but we have a relative short version now
|
||||
// hack the long relative version out of here
|
||||
count = 0;
|
||||
for ( i = 0; i < strlen( ret ); i++ )
|
||||
{
|
||||
if ( ret[i] == '/' ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
// this is the clean, not short version
|
||||
strcpy( out, in );
|
||||
vfsCleanFileName( out );
|
||||
for ( i = 0; i <= count; i++ )
|
||||
{
|
||||
chunk = strrchr( out, '/' );
|
||||
if ( backup ) {
|
||||
backup[0] = '/';
|
||||
}
|
||||
chunk[0] = '\0';
|
||||
backup = chunk;
|
||||
}
|
||||
return chunk + 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vfsCleanFileName( char *in ){
|
||||
strlwr( in );
|
||||
vfsFixDOSName( in );
|
||||
int n = strlen( in );
|
||||
if ( in[n - 1] == '/' ) {
|
||||
in[n - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// HYDRA: this now searches VFS/PAK files in addition to the filesystem
|
||||
// if FLAG is unspecified then ONLY dirs are searched.
|
||||
// PAK's are searched before DIRs to mimic engine behaviour
|
||||
// index is ignored when searching PAK files.
|
||||
// see ifilesystem.h
|
||||
char* vfsGetFullPath( const char *in, int index, int flag ){
|
||||
int count = 0;
|
||||
static char out[PATH_MAX];
|
||||
char tmp[NAME_MAX];
|
||||
int i;
|
||||
|
||||
if ( flag & VFS_SEARCH_PAK ) {
|
||||
char fixed[NAME_MAX];
|
||||
GSList *lst;
|
||||
|
||||
strcpy( fixed, in );
|
||||
vfsFixDOSName( fixed );
|
||||
g_strdown( fixed );
|
||||
|
||||
for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
|
||||
{
|
||||
VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
|
||||
|
||||
char *ptr,*lastptr;
|
||||
lastptr = file->name;
|
||||
|
||||
while ( ( ptr = strchr( lastptr,'/' ) ) != NULL )
|
||||
lastptr = ptr + 1;
|
||||
|
||||
if ( strcmp( lastptr, fixed ) == 0 ) {
|
||||
strncpy( out,file->name,PATH_MAX );
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !flag || ( flag & VFS_SEARCH_DIR ) ) {
|
||||
for ( i = 0; i < g_numDirs; i++ )
|
||||
{
|
||||
strcpy( tmp, g_strDirs[i] );
|
||||
strcat( tmp, in );
|
||||
if ( access( tmp, R_OK ) == 0 ) {
|
||||
if ( count == index ) {
|
||||
strcpy( out, tmp );
|
||||
return out;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// TODO TTimo on linux the base prompt is ~/.q3a/<fs_game>
|
||||
// given the file dialog, we could push the strFSBasePath and ~/.q3a into the directory shortcuts
|
||||
// FIXME TTimo is this really a VFS functionality?
|
||||
// actually .. this should be the decision of the core isn't it?
|
||||
// or .. add an API so that the base prompt can be set during VFS init
|
||||
const char* vfsBasePromptPath(){
|
||||
#ifdef _WIN32
|
||||
static const char* path = "C:";
|
||||
#else
|
||||
static const char* path = "/";
|
||||
#endif
|
||||
return path;
|
||||
}
|
68
plugins/vfsqlpk3/vfs.h
Normal file
68
plugins/vfsqlpk3/vfs.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
Copyright (c) 2001, Loki software, inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
Neither the name of Loki software nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _VFS_H_
|
||||
#define _VFS_H_
|
||||
|
||||
#define VFS_MAXDIRS 8
|
||||
|
||||
void vfsInitDirectory( const char *path );
|
||||
void vfsShutdown();
|
||||
void vfsFreeFile( void *p );
|
||||
GSList* vfsGetFileList( const char *dir, const char *ext );
|
||||
GSList* vfsGetDirList( const char *dir );
|
||||
void vfsClearFileDirList( GSList **lst );
|
||||
int vfsGetFileCount( const char *filename, int flag );
|
||||
int vfsLoadFile( const char *filename, void **buffer, int index = 0 );
|
||||
int vfsLoadFullPathFile( const char *filename, void **buffer );
|
||||
|
||||
// some useful functions
|
||||
// clean a file name to a unique representation
|
||||
// very usefull if you have to do some weird manips on the files
|
||||
// works on regular files and dirs
|
||||
// will convert to lowercase, unix path ('/' filename seperator)
|
||||
// on win32, will build the short path name
|
||||
// directories will be cleaned, no ending filename seperator
|
||||
// we modify the entry directly, the size of the string can only go down
|
||||
void vfsCleanFileName( char * );
|
||||
// these return a static char*, doesn't need to be freed or anything
|
||||
// get the base path to use when raising file dialogs
|
||||
// we manually add "maps/" or "sounds/" or "mapobjects/models/" etc.
|
||||
const char* vfsBasePromptPath();
|
||||
// extract the relative path from a full path
|
||||
// will match against any of the base paths we have
|
||||
// returns NULL if not found
|
||||
char* vfsExtractRelativePath( const char *in );
|
||||
// returns the full path (in a static buff) to a file given it's relative path
|
||||
// returns the first file in the list or NULL if not found
|
||||
// see ifilesystem.h for more notes
|
||||
char* vfsGetFullPath( const char*, int index = 0, int flag = 0 );
|
||||
|
||||
#endif // _VFS_H_
|
101
plugins/vfsqlpk3/vfsqlpk3.cpp
Normal file
101
plugins/vfsqlpk3/vfsqlpk3.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Copyright (c) 2001, Loki software, inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
Neither the name of Loki software nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//
|
||||
// Quake Live Virtual FileSystem - reads files from different dirs and inside pak files
|
||||
//
|
||||
// QBall147
|
||||
//
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <wtypes.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "vfsqlpk3.h"
|
||||
#include "vfs.h"
|
||||
|
||||
// =============================================================================
|
||||
// SYNAPSE
|
||||
|
||||
_QERFuncTable_1 g_FuncTable;
|
||||
|
||||
CSynapseServer* g_pSynapseServer = NULL;
|
||||
CSynapseClientVFS g_SynapseClient;
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC visibility push(default)
|
||||
#endif
|
||||
extern "C" CSynapseClient * SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) {
|
||||
#if __GNUC__ >= 4
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
if ( strcmp( version, SYNAPSE_VERSION ) ) {
|
||||
Syn_Printf( "ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version );
|
||||
return NULL;
|
||||
}
|
||||
g_pSynapseServer = pServer;
|
||||
g_pSynapseServer->IncRef();
|
||||
Set_Syn_Printf( g_pSynapseServer->Get_Syn_Printf() );
|
||||
|
||||
g_SynapseClient.AddAPI( VFS_MAJOR, "qlpk3", sizeof( _QERFileSystemTable ) );
|
||||
g_SynapseClient.AddAPI( RADIANT_MAJOR, NULL, sizeof( _QERFuncTable_1 ), SYN_REQUIRE, &g_FuncTable );
|
||||
|
||||
return &g_SynapseClient;
|
||||
}
|
||||
|
||||
bool CSynapseClientVFS::RequestAPI( APIDescriptor_t *pAPI ){
|
||||
if ( !strcmp( pAPI->major_name, VFS_MAJOR ) ) {
|
||||
_QERFileSystemTable* pTable = static_cast<_QERFileSystemTable*>( pAPI->mpTable );
|
||||
pTable->m_pfnInitDirectory = &vfsInitDirectory;
|
||||
pTable->m_pfnShutdown = &vfsShutdown;
|
||||
pTable->m_pfnFreeFile = &vfsFreeFile;
|
||||
pTable->m_pfnGetDirList = &vfsGetDirList;
|
||||
pTable->m_pfnGetFileList = &vfsGetFileList;
|
||||
pTable->m_pfnClearFileDirList = &vfsClearFileDirList;
|
||||
pTable->m_pfnGetFileCount = &vfsGetFileCount;
|
||||
pTable->m_pfnLoadFile = &vfsLoadFile;
|
||||
pTable->m_pfnLoadFullPathFile = &vfsLoadFullPathFile;
|
||||
pTable->m_pfnExtractRelativePath = &vfsExtractRelativePath;
|
||||
pTable->m_pfnGetFullPath = &vfsGetFullPath;
|
||||
pTable->m_pfnBasePromptPath = &vfsBasePromptPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
Syn_Printf( "ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo() );
|
||||
return false;
|
||||
}
|
||||
|
||||
#include "version.h"
|
||||
|
||||
const char* CSynapseClientVFS::GetInfo(){
|
||||
return "Quake Live PK3 VFS module built " __DATE__ " " RADIANT_VERSION;
|
||||
}
|
7
plugins/vfsqlpk3/vfsqlpk3.def
Normal file
7
plugins/vfsqlpk3/vfsqlpk3.def
Normal file
|
@ -0,0 +1,7 @@
|
|||
; vfsqlpk3.def : Declares the module parameters for the DLL.
|
||||
|
||||
LIBRARY "VFSQLPK3"
|
||||
|
||||
EXPORTS
|
||||
; Explicit exports can go here
|
||||
Synapse_EnumerateInterfaces @1
|
63
plugins/vfsqlpk3/vfsqlpk3.h
Normal file
63
plugins/vfsqlpk3/vfsqlpk3.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright (c) 2001, Loki software, inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
Neither the name of Loki software nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _VFSQLPK3_H_
|
||||
#define _VFSQLPK3_H_
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
typedef void* HMODULE;
|
||||
typedef void* LPVOID;
|
||||
typedef char* LPCSTR;
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#include "synapse.h"
|
||||
#include "qerplugin.h"
|
||||
#include "ifilesystem.h"
|
||||
|
||||
extern _QERFuncTable_1 g_FuncTable;
|
||||
extern CSynapseServer* g_pSynapseServer;
|
||||
|
||||
#define Sys_Printf g_FuncTable.m_pfnSysPrintf
|
||||
#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
|
||||
|
||||
class CSynapseClientVFS : public CSynapseClient
|
||||
{
|
||||
public:
|
||||
// CSynapseClient API
|
||||
bool RequestAPI( APIDescriptor_t *pAPI );
|
||||
const char* GetInfo();
|
||||
|
||||
CSynapseClientVFS() { }
|
||||
virtual ~CSynapseClientVFS() { }
|
||||
};
|
||||
|
||||
#endif // _VFSQLPK3_H_
|
BIN
plugins/vfsqlpk3/vfsqlpk3.proj
Normal file
BIN
plugins/vfsqlpk3/vfsqlpk3.proj
Normal file
Binary file not shown.
200
plugins/vfsqlpk3/vfsqlpk3.vcproj
Normal file
200
plugins/vfsqlpk3/vfsqlpk3.vcproj
Normal file
|
@ -0,0 +1,200 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="vfsqlpk3"
|
||||
ProjectGUID="{9FD68F2C-B26A-461D-96E0-55AFC48AC9E0}"
|
||||
RootNamespace="vfsqlpk3"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="0"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)\install\modules"
|
||||
IntermediateDirectory="$(SolutionDir)\build\intermediate\$(ConfigurationName)\$(ProjectName)"
|
||||
ConfigurationType="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""$(SolutionDir)\libs";"$(SolutionDir)\include";"$(SolutionDir)\..\STLport-5.2.1\stlport";"$(SolutionDir)\..\gtk-2.16.6\include\glib-2.0";"$(SolutionDir)\..\gtk-2.16.6\lib\glib-2.0\include";"$(SolutionDir)\..\libxml2-2.7.3\include\libxml2""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;VFSPK3_EXPORTS;"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
DisableSpecificWarnings="4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/STACK:8388608"
|
||||
AdditionalDependencies="glib-2.0.lib libxml2.lib synapse.lib"
|
||||
AdditionalLibraryDirectories=""$(SolutionDir)\..\gtk-2.16.6\lib";"$(SolutionDir)\..\libxml2-2.7.3\lib";"$(SolutionDir)\build\$(ConfigurationName)\libs""
|
||||
ModuleDefinitionFile="vfsqlpk3.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)\install\modules"
|
||||
IntermediateDirectory="$(SolutionDir)\build\intermediate\$(ConfigurationName)\$(ProjectName)"
|
||||
ConfigurationType="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(SolutionDir)\libs";"$(SolutionDir)\include";"$(SolutionDir)\..\STLport-5.2.1\stlport";"$(SolutionDir)\..\gtk-2.16.6\include\glib-2.0";"$(SolutionDir)\..\gtk-2.16.6\lib\glib-2.0\include";"$(SolutionDir)\..\libxml2-2.7.3\include\libxml2""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;VFSPK3_EXPORTS;"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/STACK:8388608"
|
||||
AdditionalDependencies="glib-2.0.lib libxml2.lib synapse.lib"
|
||||
AdditionalLibraryDirectories=""$(SolutionDir)\..\gtk-2.16.6\lib";"$(SolutionDir)\..\libxml2-2.7.3\lib";"$(SolutionDir)\build\$(ConfigurationName)\libs""
|
||||
ModuleDefinitionFile="vfsqlpk3.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\qlvfs.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\unzip.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vfs.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vfsqlpk3.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vfsqlpk3.def"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
24
radiant.sln
24
radiant.sln
|
@ -1,6 +1,6 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "radiant", "radiant\radiant.vcproj", "{65D02375-63EE-4A8A-9F8E-504B1D5A1D02}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{14734EBB-B167-48D9-9B93-2277F645925F} = {14734EBB-B167-48D9-9B93-2277F645925F}
|
||||
|
@ -181,6 +181,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bkgrnd2d", "contrib\bkgrnd2
|
|||
{E13CCFB0-A366-4EF3-A66F-C374B563E4DF} = {E13CCFB0-A366-4EF3-A66F-C374B563E4DF}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vfsqlpk3", "plugins\vfsqlpk3\vfsqlpk3.vcproj", "{9FD68F2C-B26A-461D-96E0-55AFC48AC9E0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
|
@ -191,6 +193,10 @@ Global
|
|||
{65D02375-63EE-4A8A-9F8E-504B1D5A1D02}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{65D02375-63EE-4A8A-9F8E-504B1D5A1D02}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{65D02375-63EE-4A8A-9F8E-504B1D5A1D02}.Release|Win32.Build.0 = Release|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Release|Win32.Build.0 = Release|Win32
|
||||
{B99A58B4-E5AB-42F6-A28F-D7ACB80E0B06}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B99A58B4-E5AB-42F6-A28F-D7ACB80E0B06}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B99A58B4-E5AB-42F6-A28F-D7ACB80E0B06}.Release|Win32.ActiveCfg = Release|Win32
|
||||
|
@ -223,6 +229,10 @@ Global
|
|||
{818BAC3D-0399-4416-930D-0AA28D55F798}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{818BAC3D-0399-4416-930D-0AA28D55F798}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{818BAC3D-0399-4416-930D-0AA28D55F798}.Release|Win32.Build.0 = Release|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Release|Win32.Build.0 = Release|Win32
|
||||
{A43B5811-4BCC-483A-BDAC-F5721DCF9B4A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A43B5811-4BCC-483A-BDAC-F5721DCF9B4A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A43B5811-4BCC-483A-BDAC-F5721DCF9B4A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
|
@ -331,14 +341,10 @@ Global
|
|||
{D43C13B9-35AC-4EC1-8A90-DF6D7132B9BD}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D43C13B9-35AC-4EC1-8A90-DF6D7132B9BD}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D43C13B9-35AC-4EC1-8A90-DF6D7132B9BD}.Release|Win32.Build.0 = Release|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6C1116CE-D99E-4629-9E69-A9329335D706}.Release|Win32.Build.0 = Release|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CD40B764-1D47-4FAE-8C6A-EF036E478D65}.Release|Win32.Build.0 = Release|Win32
|
||||
{9FD68F2C-B26A-461D-96E0-55AFC48AC9E0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9FD68F2C-B26A-461D-96E0-55AFC48AC9E0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9FD68F2C-B26A-461D-96E0-55AFC48AC9E0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9FD68F2C-B26A-461D-96E0-55AFC48AC9E0}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Loading…
Reference in a new issue