mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 07:21:58 +00:00
Added search_getpackagename builtin to query which package a file is inside (flags&2 to get the gamedir of the package/gamedir too), also let the 'cvar' pseudo-cvar be queried via cvar_string.
This commit is contained in:
parent
bdfdface5b
commit
5842eb70e8
3 changed files with 163 additions and 52 deletions
102
Quake/common.c
102
Quake/common.c
|
@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "quakedef.h"
|
||||
#include "q_ctype.h"
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dirent.h>
|
||||
|
@ -559,11 +560,14 @@ float Q_atof (const char *str)
|
|||
// Q_ftoa: convert IEEE 754 float to a base-10 string with "infinite" decimal places
|
||||
void Q_ftoa(char *str, float in)
|
||||
{
|
||||
unsigned int i = *((int *)&in);
|
||||
struct {
|
||||
float f;
|
||||
unsigned int i;
|
||||
} u = {in};
|
||||
|
||||
int signbit = (i & 0x80000000) >> 31;
|
||||
int exp = (signed int)((i & 0x7F800000) >> 23) - 127;
|
||||
int mantissa = (i & 0x007FFFFF);
|
||||
int signbit = (u.i & 0x80000000) >> 31;
|
||||
int exp = (signed int)((u.i & 0x7F800000) >> 23) - 127;
|
||||
int mantissa = (u.i & 0x007FFFFF);
|
||||
|
||||
if (exp == 128) // 255(NaN/Infinity bits) - 127(bias)
|
||||
{
|
||||
|
@ -604,6 +608,42 @@ void Q_ftoa(char *str, float in)
|
|||
}
|
||||
}
|
||||
|
||||
int wildcmp(const char *wild, const char *string)
|
||||
{ //case-insensitive string compare with wildcards. returns true for a match.
|
||||
while (*string)
|
||||
{
|
||||
if (*wild == '*')
|
||||
{
|
||||
if (*string == '/' || *string == '\\')
|
||||
{
|
||||
//* terminates if we get a match on the char following it, or if its a \ or / char
|
||||
wild++;
|
||||
continue;
|
||||
}
|
||||
if (wildcmp(wild+1, string))
|
||||
return true;
|
||||
string++;
|
||||
}
|
||||
else if ((q_tolower(*wild) == q_tolower(*string)) || (*wild == '?'))
|
||||
{
|
||||
//this char matches
|
||||
wild++;
|
||||
string++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//failure
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while (*wild == '*')
|
||||
{
|
||||
wild++;
|
||||
}
|
||||
return !*wild;
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
|
@ -2263,7 +2303,7 @@ void COM_ListSystemFiles(void *ctx, const char *gamedir, const char *ext, qboole
|
|||
#endif
|
||||
}
|
||||
|
||||
void COM_ListFiles(void *ctx, const char *gamedir, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize))
|
||||
static void COM_ListFiles(void *ctx, searchpath_t *spath, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath))
|
||||
{
|
||||
char prefixdir[MAX_OSPATH];
|
||||
char *sl;
|
||||
|
@ -2285,14 +2325,14 @@ void COM_ListFiles(void *ctx, const char *gamedir, const char *pattern, qboolean
|
|||
char filestring[MAX_OSPATH];
|
||||
WIN32_FIND_DATA fdat;
|
||||
HANDLE fhnd;
|
||||
q_snprintf (filestring, sizeof(filestring), "%s/%s%s", gamedir, prefixdir, pattern);
|
||||
q_snprintf (filestring, sizeof(filestring), "%s/%s%s", spath->filename, prefixdir, pattern);
|
||||
fhnd = FindFirstFile(filestring, &fdat);
|
||||
if (fhnd == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
do
|
||||
{
|
||||
q_snprintf (filestring, sizeof(filestring), "%s%s", prefixdir, fdat.cFileName);
|
||||
cb (ctx, filestring, Sys_FileTimeToTime(fdat.ftLastWriteTime), fdat.nFileSizeLow);
|
||||
cb (ctx, filestring, Sys_FileTimeToTime(fdat.ftLastWriteTime), fdat.nFileSizeLow, spath);
|
||||
} while (FindNextFile(fhnd, &fdat));
|
||||
FindClose(fhnd);
|
||||
}
|
||||
|
@ -2302,22 +2342,60 @@ void COM_ListFiles(void *ctx, const char *gamedir, const char *pattern, qboolean
|
|||
DIR *dir_p;
|
||||
struct dirent *dir_t;
|
||||
|
||||
q_snprintf (filestring, sizeof(filestring), "%s/%s", gamedir, prefixdir);
|
||||
q_snprintf (filestring, sizeof(filestring), "%s/%s", spath->filename, prefixdir);
|
||||
dir_p = opendir(filestring);
|
||||
if (dir_p == NULL)
|
||||
return;
|
||||
while ((dir_t = readdir(dir_p)) != NULL)
|
||||
{
|
||||
if (*dir_t->d_name == '.') //ignore hidden paths... and parent etc weirdness.
|
||||
continue;
|
||||
if (!fnmatch(pattern, dir_t->d_name, FNM_NOESCAPE|FNM_PATHNAME|FNM_CASEFOLD))
|
||||
{
|
||||
struct stat s;
|
||||
q_snprintf (filestring, sizeof(filestring), "%s/%s%s", spath->filename, prefixdir, dir_t->d_name);
|
||||
if (stat(filestring, &s) < 0)
|
||||
memset(&s, 0, sizeof(s));
|
||||
|
||||
q_snprintf (filestring, sizeof(filestring), "%s%s", prefixdir, dir_t->d_name);
|
||||
cb (ctx, filestring, 0, 0);
|
||||
cb (ctx, filestring, s.st_mtime, s.st_size, spath);
|
||||
}
|
||||
}
|
||||
closedir(dir_p);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath))
|
||||
{
|
||||
searchpath_t *search;
|
||||
|
||||
if (*pattern == '/' || strchr(pattern, ':') //block absolute paths
|
||||
|| strchr(pattern, '\\') //block unportable paths (also ones that mess up other checks)
|
||||
|| strstr(pattern, "./")) //block evil relative paths (any kind)
|
||||
{
|
||||
Con_Printf("Blocking absolute/non-portable/dodgy search pattern: %s\n", pattern);
|
||||
return;
|
||||
}
|
||||
|
||||
//don't add the same pak twice.
|
||||
for (search = com_searchpaths; search; search = search->next)
|
||||
{
|
||||
if (search->pack)
|
||||
{
|
||||
pack_t *pak = search->pack;
|
||||
int i;
|
||||
for (i = 0; i < pak->numfiles; i++)
|
||||
{
|
||||
if (wildcmp(pattern, pak->files[i].name))
|
||||
cb(ctx, pak->files[i].name, pak->mtime, pak->files[i].filelen, search);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COM_ListFiles(ctx, search, pattern, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean COM_AddPackage(searchpath_t *basepath, const char *pakfile)
|
||||
{
|
||||
|
@ -2347,6 +2425,12 @@ static qboolean COM_AddPackage(searchpath_t *basepath, const char *pakfile)
|
|||
if (!pak)
|
||||
return false;
|
||||
|
||||
{
|
||||
struct stat s;
|
||||
if (stat(pakfile, &s) >= 0)
|
||||
pak->mtime = s.st_mtime;
|
||||
}
|
||||
|
||||
search = (searchpath_t *) Z_Malloc(sizeof(searchpath_t));
|
||||
search->path_id = basepath->path_id;
|
||||
search->pack = pak;
|
||||
|
|
|
@ -141,6 +141,7 @@ int Q_strncmp (const char *s1, const char *s2, int count);
|
|||
int Q_atoi (const char *str);
|
||||
float Q_atof (const char *str);
|
||||
void Q_ftoa(char *str, float in);
|
||||
int wildcmp(const char *wild, const char *string);
|
||||
|
||||
|
||||
#include "strl_fn.h"
|
||||
|
@ -221,6 +222,7 @@ typedef struct pack_s
|
|||
char filename[MAX_OSPATH];
|
||||
int handle;
|
||||
int numfiles;
|
||||
time_t mtime;
|
||||
packfile_t *files;
|
||||
} pack_t;
|
||||
|
||||
|
@ -244,6 +246,7 @@ extern char com_basedir[MAX_OSPATH];
|
|||
extern char com_gamedir[MAX_OSPATH];
|
||||
extern int file_from_pak; // global indicating that file came from a pak
|
||||
|
||||
void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath));
|
||||
const char *COM_GetGameNames(qboolean full);
|
||||
qboolean COM_GameDirMatches(const char *tdirs);
|
||||
|
||||
|
|
110
Quake/pr_ext.c
110
Quake/pr_ext.c
|
@ -2239,6 +2239,12 @@ static void PF_cvar_string(void)
|
|||
q_strlcpy(temp, var->string, STRINGTEMP_LENGTH);
|
||||
G_INT(OFS_RETURN) = PR_SetEngineString(temp);
|
||||
}
|
||||
else if (!strcmp(name, "game"))
|
||||
{ //game looks like a cvar in most other respects (and is a cvar in fte). let cvar_string work on it as a way to find out the current gamedir.
|
||||
char *temp = PR_GetTempString();
|
||||
q_strlcpy(temp, COM_GetGameNames(true), STRINGTEMP_LENGTH);
|
||||
G_INT(OFS_RETURN) = PR_SetEngineString(temp);
|
||||
}
|
||||
else
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
}
|
||||
|
@ -2905,14 +2911,16 @@ static struct filesearch_s
|
|||
qcvm_t *owner;
|
||||
size_t numfiles;
|
||||
size_t maxfiles;
|
||||
unsigned int flags;
|
||||
struct
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
time_t mtime;
|
||||
size_t fsize;
|
||||
searchpath_t *spath;
|
||||
} *file;
|
||||
} searches[16];
|
||||
static qboolean PR_Search_AddFile(void *ctx, const char *fname, time_t mtime, size_t fsize)
|
||||
static qboolean PR_Search_AddFile(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath)
|
||||
{
|
||||
struct filesearch_s *c = ctx;
|
||||
if (c->numfiles == c->maxfiles)
|
||||
|
@ -2923,10 +2931,10 @@ static qboolean PR_Search_AddFile(void *ctx, const char *fname, time_t mtime, si
|
|||
q_strlcpy(c->file[c->numfiles].name, fname, sizeof(c->file[c->numfiles].name));
|
||||
c->file[c->numfiles].mtime = mtime;
|
||||
c->file[c->numfiles].fsize = fsize;
|
||||
c->file[c->numfiles].spath = spath;
|
||||
c->numfiles++;
|
||||
return true;
|
||||
}
|
||||
void COM_ListFiles(void *ctx, const char *gamedir, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize));
|
||||
static void PF_search_shutdown(void)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -2947,14 +2955,16 @@ static void PF_search_begin(void)
|
|||
{
|
||||
size_t i;
|
||||
const char *pattern = G_STRING(OFS_PARM0);
|
||||
// qboolean caseinsensitive = !!G_FLOAT(OFS_PARM0);
|
||||
// qboolaen quiet = !!G_FLOAT(OFS_PARM0);
|
||||
unsigned int flags = G_FLOAT(OFS_PARM1);
|
||||
// qboolaen quiet = !!G_FLOAT(OFS_PARM2);
|
||||
// const char *pkgfilter = G_STRING(OFS_PARM3);
|
||||
|
||||
for (i = 0; i < countof(searches); i++)
|
||||
{
|
||||
if (!searches[i].owner)
|
||||
{
|
||||
COM_ListFiles(&searches[i], com_gamedir, pattern, PR_Search_AddFile);
|
||||
searches[i].flags = flags;
|
||||
COM_ListAllFiles(&searches[i], pattern, PR_Search_AddFile);
|
||||
if (!searches[i].numfiles)
|
||||
break;
|
||||
searches[i].owner = qcvm;
|
||||
|
@ -3009,7 +3019,7 @@ static void PF_search_getfilesize(void)
|
|||
}
|
||||
static void PF_search_getfilemtime(void)
|
||||
{
|
||||
char *ret = PR_GetTempString();
|
||||
char *ret;
|
||||
size_t handle = G_FLOAT(OFS_PARM0);
|
||||
size_t index = G_FLOAT(OFS_PARM1);
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
|
@ -3018,9 +3028,59 @@ static void PF_search_getfilemtime(void)
|
|||
if (index < 0 || index >= searches[handle].numfiles)
|
||||
return; //erk
|
||||
|
||||
ret = PR_GetTempString();
|
||||
strftime(ret, STRINGTEMP_LENGTH, "%Y-%m-%d %H:%M:%S", localtime(&searches[handle].file[index].mtime));
|
||||
G_INT(OFS_RETURN) = PR_SetEngineString(ret);
|
||||
}
|
||||
static void PF_search_getpackagename(void)
|
||||
{
|
||||
searchpath_t *spath;
|
||||
// char *ret;
|
||||
size_t handle = G_FLOAT(OFS_PARM0);
|
||||
size_t index = G_FLOAT(OFS_PARM1);
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
if (handle < 0 || handle >= countof(searches))
|
||||
return; //erk
|
||||
if (index < 0 || index >= searches[handle].numfiles)
|
||||
return; //erk
|
||||
|
||||
for (spath = com_searchpaths; spath; spath = spath->next)
|
||||
if (spath == searches[handle].file[index].spath)
|
||||
break;
|
||||
|
||||
if (spath)
|
||||
{
|
||||
if (searches[handle].flags & 2)
|
||||
{ //gamedir/packagename. not necessarily fopenable.
|
||||
if (spath->pack)
|
||||
{
|
||||
const char *pathname = spath->pack->filename;
|
||||
const char *last = pathname, *last2 = "";
|
||||
while (*pathname)
|
||||
{
|
||||
if (*pathname == '/')
|
||||
{
|
||||
last2 = last;
|
||||
last = pathname + 1;
|
||||
}
|
||||
pathname++;
|
||||
}
|
||||
G_INT(OFS_RETURN) = PR_MakeTempString(last2);
|
||||
}
|
||||
else
|
||||
G_INT(OFS_RETURN) = PR_MakeTempString(COM_SkipPath(spath->filename));
|
||||
}
|
||||
else
|
||||
{ //like whichpack thus like frik_file. which sucks.
|
||||
if (spath->pack)
|
||||
G_INT(OFS_RETURN) = PR_MakeTempString(COM_SkipPath(spath->pack->filename));
|
||||
else
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
G_INT(OFS_RETURN) = 0; //no idea where it came from. sorry.
|
||||
}
|
||||
|
||||
static void PF_whichpack(void)
|
||||
{
|
||||
|
@ -3419,43 +3479,6 @@ static void PF_bufstr_free(void)
|
|||
strbuflist[bufno].strings[index] = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int wildcmp(const char *wild, const char *string)
|
||||
{ //case-insensitive string compare with wildcards. returns true for a match.
|
||||
while (*string)
|
||||
{
|
||||
if (*wild == '*')
|
||||
{
|
||||
if (*string == '/' || *string == '\\')
|
||||
{
|
||||
//* terminates if we get a match on the char following it, or if its a \ or / char
|
||||
wild++;
|
||||
continue;
|
||||
}
|
||||
if (wildcmp(wild+1, string))
|
||||
return true;
|
||||
string++;
|
||||
}
|
||||
else if ((q_tolower(*wild) == q_tolower(*string)) || (*wild == '?'))
|
||||
{
|
||||
//this char matches
|
||||
wild++;
|
||||
string++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//failure
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while (*wild == '*')
|
||||
{
|
||||
wild++;
|
||||
}
|
||||
return !*wild;
|
||||
}
|
||||
static void PF_buf_cvarlist(void)
|
||||
{
|
||||
size_t bufno = G_FLOAT(OFS_PARM0)-BUFSTRBASE;
|
||||
|
@ -6216,6 +6239,7 @@ static struct
|
|||
{"search_getfilename",PF_search_getfilename,PF_search_getfilename,447,PF_search_getfilename,77, "string(searchhandle handle, float num)", "Retrieves name of one of the files that was found by the initial search."},
|
||||
{"search_getfilesize",PF_search_getfilesize,PF_search_getfilesize,0,PF_search_getfilesize,0, "float(searchhandle handle, float num)", "Retrieves the size of one of the files that was found by the initial search."},
|
||||
{"search_getfilemtime",PF_search_getfilemtime,PF_search_getfilemtime,0,PF_search_getfilemtime,0, "string(searchhandle handle, float num)", "Retrieves modification time of one of the files in %Y-%m-%d %H:%M:%S format."},
|
||||
{"search_getpackagename",PF_search_getpackagename,PF_search_getpackagename,0,PF_search_getpackagename,0, "string(searchhandle handle, float num)", "Retrieves the name of the package the file was found inside."},
|
||||
{"cvar_string", PF_cvar_string, PF_cvar_string, 448, PF_cvar_string,71, "string(string cvarname)"},//DP_QC_CVAR_STRING
|
||||
{"findflags", PF_findflags, PF_findflags, 449, PF_findflags,0, "entity(entity start, .float fld, float match)"},//DP_QC_FINDFLAGS
|
||||
{"findchainflags", PF_findchainflags, PF_findchainflags, 450, PF_NoMenu, "entity(.float fld, float match)"},//DP_QC_FINDCHAINFLAGS
|
||||
|
|
Loading…
Reference in a new issue